我正在考虑从运行时动态生成 EntityTypeConfiguration 并且我不希望模型中有任何 EF 依赖项[这就是我避免数据注释的原因]。
所以我声明了一个自定义属性(或者以后可以是任何配置文件)
[AttributeUsage(AttributeTargets.Property, AllowMultiple=true )]
public class PersistableMemberAttribute : Attribute
{
public bool Iskey;
public bool IsRequired;
public bool IsIgnored;
public bool IsMany;
public string HasForeignKey;
public bool PropertyIsRequired;
public bool PropertyIsOptional;
}
这是我的一个模型的样子:
public class Blog
{
[PersistableMember(Iskey=true)]
public Guid BlogId { get; set; }
[PersistableMember(PropertyIsRequired = true)]
public string Name { get; set; }
public string Url { get; set; }
[PersistableMember(IsIgnored=true)]
public int Rating { get; set; }
[PersistableMember(IsMany =true)]
public ICollection<Post> Posts { get; set; }
}
现在我要编写一个通用的 EntityTypeConfiguration ,它将根据属性值在运行时动态创建配置:
public class GenericEntityConfiguration<T> : EntityTypeConfiguration<T> where T : class
{
public GenericEntityConfiguration()
{
var members = typeof(T).GetProperties();
if (null != members)
{
foreach (var property in members)
{
var attrb= property.GetCustomAttributes(typeof( PersistableMemberAttribute ),false).OfType<PersistableMemberAttribute>();
if (attrb != null && attrb.Count() > 0)
{
foreach (var memberAttributute in attrb)
{
if (memberAttributute.Iskey || memberAttributute.IsIgnored)
{
var entityMethod = this.GetType().GetMethod("Setkey");
entityMethod.MakeGenericMethod(property.PropertyType)
.Invoke(this, new object[] { property, memberAttributute });
}
if (memberAttributute.IsRequired)
{
var entityMethod = this.GetType().GetMethod("SetRequired");
entityMethod.MakeGenericMethod(property.PropertyType)
.Invoke(this, new object[] { property, memberAttributute });
}
if (memberAttributute.PropertyIsRequired || memberAttributute.PropertyIsOptional)
{
var entityMethod = this.GetType().GetMethod("SetPropertyConfiguration");
entityMethod.MakeGenericMethod(property.PropertyType)
.Invoke(this, new object[] { property, memberAttributute });
}
}
}
}
}
}
public void SetPropertyConfiguration<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute)
{
var functorParam = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda(
Expression.Property(functorParam, propertyInfo)
, functorParam);
if (attribute.PropertyIsRequired)
{
this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsRequired();
}
if (attribute.PropertyIsOptional)
{
this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsOptional();
}
}
public void Setkey<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute)
{
var functorParam = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda(
Expression.Property(functorParam, propertyInfo)
, functorParam);
if (attribute.Iskey)
{
this.HasKey<TResult>((Expression<Func<T,TResult>>)lambda);
}
if (attribute.IsIgnored)
{
this.Ignore<TResult>((Expression<Func<T, TResult>>)lambda);
}
}
public void SetRequired<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute) where TResult : class
{
var functorParam = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda(
Expression.Property(functorParam, propertyInfo)
, functorParam);
if (attribute.IsRequired)
{
this.HasRequired<TResult>((Expression<Func<T, TResult>>)lambda);
}
}
}
但我得到了编译错误
错误 1 类型“TResult”必须是不可为空的值类型,才能在泛型类型或方法“System.Data.Entity.ModelConfiguration.Configuration.StructuralTypeConfiguration.Property(System.Linq. Expressions.Expression>)' D:\R&D\UpdateStorePOC\UpdateStorePOC\Data\GenericEntityConfiguration.cs 63 17 UpdateStorePOC
这对于这两个语句:
this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsRequired();
this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsOptional();
这意味着我需要对我的方法施加约束以将其限制为值类型。在 C# 中,这是通过 'struct' 关键字完成的。
public void SetPropertyConfiguration<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute) Where TResult : struct
但它不是解决方案,因为我的属性类型可以是一个类,例如 string 或 int、bool double 等。所以完全不清楚我是否可以将它们发送到这种方法中。请帮助我解决这个问题是否有任何其他方法可以做到这一点。