好的,所以...
主要问题是我有这门课:
public class UniqueEntity {
[key]
public object Key { get; set; }
}
但是EntityFramework 在处理object 键时会搞乱表的创建。我的想法是键可以是任何类型,由子类指定。
我开始使用泛型:
public class UniqueEntity<T> where T : IComparable, IComparable<T>
{
[Key]
public T Key { get; set; }
}
这在开始时效果很好,但后来在创建我的通用存储库时导致了严重的设计问题(存储库定义类似于 IRepository<T,E>,而 IRepository<E> 就足够了。
因此,EntityFramework 使用带有Key 属性注释的属性的PropertyInfo 值来获取实体的键类型。如果我可以将该类型更改为用户想要的任何类型(在运行时),并且完全避免使用泛型,那就太好了。
事实证明你不能删除一个属性,或者改变它的类型buuuuuut..你实际上可以用自定义属性创建一个新的虚拟属性,然后从原来的Key属性中删除属性!!
为此,我们需要一个CustomReflectionContext (System.Reflection.Context):
public class Modifier : CustomReflectionContext
{
private string propName;
private object propValue;
public Modifier(string propName, object propValue)
{
this.propName = propName;
this.propValue = propValue;
}
protected override IEnumerable<PropertyInfo> AddProperties(Type type)
{
Type newType = MapType(propValue.GetType().GetTypeInfo());
return CreateProperty(newType, propName, o => propValue, (o, v) => propValue = v,
new Attribute[] { new KeyAttribute() }, new Attribute[] { }, new Attribute[] { });
}
protected override IEnumerable<object> GetCustomAttributes(MemberInfo member, IEnumerable<object> declaredAttributes)
{
return new Attribute[] { };
}
}
在这个小类的帮助下,我们能够创建自己的自定义类型以提供给EntityFramework,并使用现在具有[Key] 注释的新属性:
var context = new Modifier("NewKey", 0);
var uniqueEntityType = context.MapType(typeof(UniqueEntity).GetTypeInfo());
var keyType = uniqueEntityType.GetProperty("Key").PropertyType;
var keyAttrs = uniqueEntityType.GetProperty("Key").GetCustomAttributes();
var newKeyType = uniqueEntityType.GetProperty("NewKey").PropertyType;
var newKeyAttrs = uniqueEntityType.GetProperty("NewKey").GetCustomAttributes();
Console.WriteLine("Key Property. Type: {0}, Attribute: {1}", keyType, keyAttrs.FirstOrDefault());
Console.WriteLine("NewKey Property. Type: {0}, Attribute: {1}", newKeyType, newKeyAttrs.FirstOrDefault());
Console.ReadLine();