2014-11-24 219 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