2014-11-24 120 views
1
更改属性的类型

让我们假设我有下面的类:使用反射

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

我要的是能够改变的类型Key,从System.ObjectSystem.Int32,在运行时。

我想这可以完成(如果可以的话)的唯一方法是使用反射

该物业的类型可以通过PropertyTypePropertyInfo(遗憾的冗余)获得。

typeof(UniqueEntity).GetProperty("Key").PropertyType; 

问题是它是只读的。我无法将该值设置为PropertyType = typeof(int);

有没有可能的方法来改变属性的类型?

+0

备案。我想这样做,因为'Key'将被标注一个属性。外部框架将识别该属性并从'PropertyType'中获取它的类型。如果返回'System.Int32'而不是'System.Object',将会很棒。 – 2014-11-24 05:00:08

+0

有趣的问题。我不相信你可以在运行时做到这一点。但作为一个对象,你可以在其中存储任何东西,然后做运行时投射。 – 2014-11-24 05:04:43

+0

不可能是你想要的,但是你可以继承这个类并创建新的属性来转换该属性,而你只使用新的属性。 – 2014-11-24 05:05:30

回答

0

否。编译时确定任何类成员的类型,无论是字段,属性还是方法返回值,以及任何方法参数的类型。

在您的示例中,您可以在该属性中存储Int32。这将是“盒装”,你可以根据需要将它重新放回Int32。但属性本身的类型将保持Object

+0

问题是外部框架使用'PropertyType'中的值来完成它的工作。如果它的'System.Object'发生混乱。 – 2014-11-24 05:09:50

+0

@MatiCicero:你不能为这个属性创建不同类型的不同类型吗?你可以使用属性来调整框架的行为吗?在框架中是否存在可让您执行自定义处理的钩子? – siride 2014-11-24 05:11:11

+0

@MatiCicero:对不起。具体问题不会改变语言的规则。这听起来像你将不得不创建一个“填充”对象,它可以充当外部框架和内部实体类型之间的代理。 – 2014-11-24 05:11:20

0

好了,所以......

的主要问题是,我有这个类:处理object键时

public class UniqueEntity { 
    [key] 
    public object Key { get; set; } 
} 

EntityFramework弄乱表的创建。我的想法是,关键可以是任何类型,由子类指定。

我开始使用泛型:

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。上下文):

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