簡體   English   中英

使用反射更改屬性的類型

[英]Change a Property's type using reflection

假設我有以下課程:

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

我想要的是能夠在運行時將Key的類型從System.Object更改為System.Int32

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

屬性的類型可以通過獲得PropertyType的的屬性PropertyInfo (遺憾的冗余)。

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

問題是它是只讀的。 我不能將值設置為PropertyType = typeof(int);

有沒有可能更改屬性類型的方法?

否。任何類成員的類型,無論是字段,屬性還是方法的返回值,以及任何方法參數的類型都是在編譯時確定的。

在您的示例中,您可以在屬性中存儲一個Int32 它將被“裝箱”,您可以根據需要將其投射回Int32 但是屬性本身的類型將保持Object

好吧

主要問題是我上了這個課:

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

但是, EntityFramework在處理object鍵時會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.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();

證明圖片

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM