[英]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
將成為TestClassB
而ObservableCollection<TestClassC> CollectionB
是您的目標屬性。
property.GetValue(TestClassB someB)
將返回一個對象,該對象不具備調用void CollectionRefresh(collection2)
資格,因此您現在被卡住了,對嗎?
這是一個嵌套的通用問題。 如果您也將TestClassC
為T2
那將非常容易。
通常,我們將有一個非泛型基類,以便可以將其顯式轉換為該基類。 不幸的是, 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.