如何在泛型集合中强制转换对象
本文关键字:转换 对象 集合 泛型 | 更新日期: 2023-09-27 18:26:12
我需要将一个对象转换为一个通用集合,看:
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);
}
}
我该怎么做?
Obs:我需要用这个集合调用另一个集合的except方法(这个集合我用与currentCollection相同的方法获得,用anotherEntityProperty.GetValue(anotherEntity, null)
)
var itens = currentCollection.Except(anotherCollection);
动态类型可以让编译器和DLR完成这里的所有工作:
dynamic currentCollection = ...;
dynamic anotherCollection = ...;
dynamic items = Enumerable.Except(currentCollection, anotherCollection);
在执行时,这将为您完成所有的反射工作,并选择最合适的类型参数。
对于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>
-编译器将无法为其生成任何有意义的代码。
如果类型与-错误。。。这样的强制转换适用于IEnumerable(因为它的类型为"out T"),但不适用于ICollection。ICollection<Base_Class>
相关,则铸造应在4.0中工作
这不会直接回答您的问题,而是回答了我们在评论中讨论的问题:
如何使用反射调用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);