使用反射更改属性的类型

时间:2014-11-24 04:54:29

标签: c# .net reflection types properties

假设我有以下课程:

public class UniqueEntity {
    public object Key { get; set; }
}

我想要的是能够在运行时将Key的类型从System.Object更改为System.Int32

我猜这是可以实现的唯一方法(如果可以的话)是使用反射

属性的类型可以通过PropertyType的{​​{1}}属性获取(对不起冗余)。

PropertyInfo

问题是它是只读的。我无法将值设置为typeof(UniqueEntity).GetProperty("Key").PropertyType;

是否有可能改变财产的类型?

2 个答案:

答案 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();

Proof Image