【发布时间】:2017-07-18 20:01:54
【问题描述】:
我正在使用.Net Core,遇到以下问题:
我想使用反射来转换对象的属性并将结果存储在该对象的新副本中。这对非集合和数组很有用,但我遇到了泛型集合的问题 (ICollection<T>)。
有两个问题:
1.) 如何确保运行时类型为ICollection<any T> 类型。我能够为 ICollection 实现这一点,但是如何检查对象是否实现了泛型接口?
我想做这样的事情:
public object Transform(object objectToTransform) {
var type = objectToTransform.GetType();
var obj = Activator.CreateInstance(type);
foreach (var propertyInfo in type.GetRuntimeProperties()) {
...
if(typeof(ICollection<???>).GetTypeInfo().IsAssignableFrom(propertyInfo.PropertyType.GetTypeInfo())) {
// transform all items and store them in a new collection of the same runtime type
}
...
}
return obj;
}
我尝试了typeof(ICollection<>),但这不起作用。 typeof(ICollection) 对我来说不是一个选项,因为我需要确保目标集合具有 ICollection<T> 的添加方法。
2.) 第二个问题是关于转换步骤的。
我尝试使用动态来忽略将转换后的项目添加到新集合的部分的静态类型:
var collection = (IEnumerable)propertyInfo.GetMethod.Invoke(objectToTransform, null);
dynamic x = Activator.CreateInstance(collection.GetType());
foreach (var item in collection) {
x.Add(Transform(item)); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
}
对动态对象“x”调用 Add 方法会引发以下异常:“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:System.Collections.Generic.List<SomeType>.Add(SomeType) 的最佳重载匹配有一些无效参数。”
我知道 Add 方法并未针对所有 ICollection<T> 实现,例如 ReadonlyCollections。目前我只想知道这个动态调用是否以及如何工作。
我知道动态是不安全的并且看起来像一个黑客,但我还没有找到另一个解决方案,它不涉及对集合接口的每个实现的转换。
【问题讨论】:
标签: c# generics dynamic reflection .net-core