假设我有以下课程:
public class UniqueEntity {
public object Key { get; set; }
}
我想要的是能够在运行时将Key
的类型从System.Object
更改为System.Int32
。
我猜这是可以实现的唯一方法(如果可以的话)是使用反射。
属性的类型可以通过PropertyType
的{{1}}属性获取(对不起冗余)。
PropertyInfo
问题是它是只读的。我无法将值设置为typeof(UniqueEntity).GetProperty("Key").PropertyType;
。
是否有可能改变财产的类型?
答案 0 :(得分:0)
没有。任何类成员的类型,无论是字段,属性还是方法返回值,以及任何方法参数的类型,都是在编译时确定的。
在您的示例中,您可以在属性中存储Int32
。它将被“装箱”,您可以根据需要将其强制转换回Int32
。但属性本身的类型仍为Object
。
答案 1 :(得分:0)
好的,所以......
主要问题是我有这个课程:
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
使用带有PropertyInfo
属性注释的属性的Key
值来获取实体的密钥类型。如果我只能将该类型更改为用户想要的类型(在运行时),并且完全避免使用泛型,那就太棒了。
事实证明,您无法删除属性或更改其类型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();