簡體   English   中英

如何在泛型集合中強制轉換對象?

[英]How to cast an object in generic collection?

我需要將一個對象轉換為通用集合,看:

var currentEntityProperties = currentEntity.GetType().GetProperties();

foreach (var currentEntityProperty in currentEntityProperties)
{
    if (currentEntityProperty.PropertyType.GetInterfaces().Any(
                x => x.IsGenericType &&
                x.GetGenericTypeDefinition() == typeof(ICollection<>)))
    {
        var collectionType = currentEntityProperty.PropertyType.GetInterfaces().Where(
                                x => x.IsGenericType &&
                                x.GetGenericTypeDefinition() == typeof(ICollection<>)).First();

        var argumentType = collectionType.GetGenericArguments()[0];

        // now i need to convert the currentEntityProperty into a collection, something like that (this is wrong, so, what is thr right way?):
        var currentCollection = (ICollection<argumentType.GetType()>)currentEntityProperty.GetValue(currentEntity, null);
    }
}

我怎樣才能做到這一點?

觀察:我需要使用此集合來調用另一個集合的except方法(該集合我以與currentCollection相同的方式獲取,並使用anotherEntityProperty.GetValue(anotherEntity, null)

var itens = currentCollection.Except(anotherCollection);

動態類型使您可以使編譯器和DLR在這里完成所有工作:

dynamic currentCollection = ...;
dynamic anotherCollection = ...;
dynamic items = Enumerable.Except(currentCollection, anotherCollection);

在執行時,這將為您完成所有反射工作,並選擇最合適的type參數。

對於Except擴展方法,您只需要ICollection<T>實現的IEnumerable<T> 因此,您可以將屬性轉換為IEnumerable<object> (至少在T是引用類型的情況下)。

編輯:

如果確實需要,可以嘗試通過反射對對象變量調用Except:

// x and y are your object variables of the collections, 
// argumentType is the generic type you determined
  var methods = from m in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
              where m.ContainsGenericParameters
              && m.Name == "Except"
              && m.GetParameters().Count() == 2
              && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
              && m.ReturnType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
              select m;
  var method = methods.First();
  IEnumerable things = method.MakeGenericMethod(new Type[] { argumentType }).Invoke(null, new [] { x, y }) as IEnumerable;

您不能使用ICollection<some_type_determined_at_run_time> -編譯器將無法為其生成任何有意義的代碼。

如果類型與 ICollection<Base_Class>類型轉換相關 ICollection<Base_Class>則應在4.0中工作 -錯誤...此類轉換適用於IEnumerable(因為它的類型為“ out T”),但不適用於ICollection。

這不是直接回答您的問題,而是在評論中通過我們的討論回答問題:

如何使用反射調用Except方法?

Except方法不是ICollection<T>的成員,這就是您的GetMethod調用返回null的原因。 相反,它是在靜態類型System.Linq.Enumerable上定義的擴展方法。 要使用反射進行調用,您必須將其視為靜態方法。 像這樣:

// there are two overloads of Except and I'm too lazy to construct the type parameters to get the correct overload
var methods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public);
var exceptMethod = methods.Where(m => m.Name.Equals("Except") && m.GetParameters().Lengh == 2).Single();

object[] arguments = new [] { currentCollection, anotherCollection };
object items = exceptMethod.Invoke(null, arguments);

這是喬恩·斯基特(Jon Skeet)的“簡單方法”(C#4.0及更高版本):

dynamic items = Enumerable.Except((dynamic)currentCollection, (dynamic)anotherCollection);

暫無
暫無

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

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