gpt4 book ai didi

c# - 如何在 C# 和 DataAnnotation 中创建通用的 UniqueValidationAttribute?

转载 作者:太空狗 更新时间:2023-10-30 00:09:12 25 4
gpt4 key购买 nike

我正在尝试使用 System.ComponentModel.DataAnnotations.ValidationAttribute 创建一个 UniqueAttribute

我希望它是通用的,因为我可以传递 Linq DataContext、表名、字段并验证传入值是否唯一。

这是我现在卡住的不可编译的代码片段:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Data.Linq;
using System.ComponentModel;

namespace LinkDev.Innovation.Miscellaneous.Validation.Attributes
{
public class UniqueAttribute : ValidationAttribute
{
public string Field { get; set; }

public override bool IsValid(object value)
{
string str = (string)value;
if (String.IsNullOrEmpty(str))
return true;

// this is where I'm stuck
return (!Table.Where(entity => entity.Field.Equals(str)).Any());
}
}
}

我应该在我的模型中使用它,如下所示:

[Required]
[StringLength(10)]
[Unique(new DataContext(),"Groups","name")]
public string name { get; set; }

编辑:注意根据这个:Why does C# forbid generic attribute types?我不能对属性使用通用类型。

所以我这里的新方法是使用反射/表达式树动态构建 Lambda 表达式树。

最佳答案

好吧,经过一番搜索,我找到了:http://forums.asp.net/t/1512348.aspx我想通了,尽管它涉及相当多的代码。

用法:

[Required]
[StringLength(10)]
[Unique(typeof(ContactsManagerDataContext),typeof(Group),"name",ErrorMessage="Group already exists")]
public string name { get; set; }

验证器代码:

public class UniqueAttribute : ValidationAttribute
{
public Type DataContextType { get; private set; }
public Type EntityType { get; private set; }
public string PropertyName { get; private set; }

public UniqueAttribute(Type dataContextType, Type entityType, string propertyName)
{
DataContextType = dataContextType;
EntityType = entityType;
PropertyName = propertyName;
}

public override bool IsValid(object value)
{
string str = (string) value;
if (String.IsNullOrWhiteSpace(str))
return true;

// Cleanup the string
str = str.Trim();

// Construct the data context
ConstructorInfo constructor = DataContextType.GetConstructor(new Type[0]);
DataContext dataContext = (DataContext)constructor.Invoke(new object[0]);

// Get the table
ITable table = dataContext.GetTable(EntityType);

// Get the property
PropertyInfo propertyInfo = EntityType.GetProperty(PropertyName);

// Expression: "entity"
ParameterExpression parameter = Expression.Parameter(EntityType, "entity");

// Expression: "entity.PropertyName"
MemberExpression property = Expression.MakeMemberAccess(parameter, propertyInfo);

// Expression: "value"
object convertedValue = Convert.ChangeType(value, propertyInfo.PropertyType);
ConstantExpression rhs = Expression.Constant(convertedValue);

// Expression: "entity.PropertyName == value"
BinaryExpression equal = Expression.Equal(property, rhs);

// Expression: "entity => entity.PropertyName == value"
LambdaExpression lambda = Expression.Lambda(equal, parameter);

// Instantiate the count method with the right TSource (our entity type)
MethodInfo countMethod = QueryableCountMethod.MakeGenericMethod(EntityType);

// Execute Count() and say "you're valid if you have none matching"
int count = (int)countMethod.Invoke(null, new object[] { table, lambda });
return count == 0;
}

// Gets Queryable.Count<TSource>(IQueryable<TSource>, Expression<Func<TSource, bool>>)
private static MethodInfo QueryableCountMethod = typeof(Queryable).GetMethods().First(m => m.Name == "Count" && m.GetParameters().Length == 2);
}

我不介意它丑陋,因为我会将它打包到一个 DLL 中并重用它,这比每个表/字段实现多个 UniqueAttribute 好得多。

关于c# - 如何在 C# 和 DataAnnotation 中创建通用的 UniqueValidationAttribute?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2691444/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com