簡體   English   中英

使用反射強制轉換泛型

[英]Casting in generics using reflection

我有3個具有以下結構的課程。 我有一個通用的方法來刷新集合以檢查集合是否以任何方式更新。 此方法可以正常工作,除非您要更新的模型中具有Observablecollection。

因此,在TestClassA ,我正在為TestClassB調用通用的Collectionrefresh方法。 但是TestClassB有一個ObservableCollection,它不會更新。

public class TestClassA
{
   public ObservableCollection<TestClassB> CollectionA {get; set;}

   CollectionA.CollectionRefresh(CollectionB)    //Here CollectionB is the updated list
}

public class TestClassB
{
   public ObservableCollection<TestClassC> TestClassB {get; set;}
   public string Name {get; set;}
}

public class TestClassC
{
   public string FirstName {get; set;}
   public string LastName {get; set;}
}

現在,為了克服這個問題,我已經用這種方式修改了我的方法。

public static void CollectionRefresh<T>(this ObservableCollection<T> collection, List<T> items)
{
   //Method Content

   PropertyInfo[] properties = typeof(T).GetProperties();


   foreach(PropertyInfo property in properties)
   {
      if (property.PropertyType.IsGenericType && typeof(ObservableCollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
      {
         //I am getting the oldCollection and newList from somewherelse in the method.
         var collection1 = (dynamic)property.GetValue(oldCollection);
         var collection2 = (dynamic) property.GetValue(newList);

         collection1.CollectionRefresh(collection2);
      }
   }

   //Method Content
}

這不起作用,因為dynamic將是一個object並且我希望將其ObservableCollection<TestClassC>轉換為ObservableCollection<TestClassC> 如果我ObservableCollection<T>則會給我錯誤的強制轉換錯誤,因為那時T將為TestClassB ,而我希望它為TestClassC 在將ObservableCollection<TestClassC>轉換為collection1和collection2時,我的問題已解決,但是由於我正在執行泛型,因此我試圖找到一種使它成為泛型的方法。

以我的理解,您的最終目標將是void collection1.CollectionRefresh(collection2)

其中collection1.GetType()==collection2.GetType()==typeof(ObservableCollection<TestClassC>)

我想你想打電話

TestClassA testA = new TestClassA();
List<TestClassB> list = new List<TestClassB>();
testA.CollectionA.CollectionRefresh(list);

然后T將成為TestClassBObservableCollection<TestClassC> CollectionB是您的目標屬性。

property.GetValue(TestClassB someB)將返回一個對象,該對象不具備調用void CollectionRefresh(collection2)資格,因此您現在被卡住了,對嗎?

這是一個嵌套的通用問題。 如果您也將TestClassCT2那將非常容易。

通常,我們將有一個非泛型基類,以便可以將其顯式轉換為該基類。 不幸的是, ObservableCollection<T>不是從功能性ObservableCollection類繼承的。

這是我的建議。 您必須同時使用表達式樹和反射來獲取CollectionRefresh方法,然后再調用它,但這可能是一個過大的選擇。

無論如何,嘗試一下。

public static void CollectionRefresh<T>(this ObservableCollection<T> collection, List<T> items)
{
   //Method Content

   PropertyInfo[] properties = typeof(T).GetProperties();


   foreach(PropertyInfo property in properties)
   {
      if (property.PropertyType.IsGenericType && typeof(ObservableCollection<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
      {
        MethodInfo refreshMethod = property.PropertyType.GetMethod("CollectionRefresh");

        var instanceT1 = Expression.Parameter(typeof(T), "otherT1");
        var instanceT2 = Expression.Parameter(typeof(T), "otherT2");
        var prop1 = Expression.Call(instanceT1, property.GetMethod);
        var prop2 = Expression.Call(instanceT2, property.GetMethod);
        var collection1 = Expression.Convert(prop1, property.PropertyType);
        var collection2 = Expression.Convert(prop2, property.PropertyType);
        var refresh = Expression.Call(collection1, refreshMethod, collection2);
        var lambda = Expression.Lambda<Action<T, T>>(refresh, instanceT1, instanceT2);

        Action<T, T> func = lambda.Compile();
        func(oldCollection, newList);
      }
   }

   //Method Content
}

暫無
暫無

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

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