我正在写一些反射代码。呃,好吧。
我有一个
IEnumerable<TData>
值对象,和一个 Expression<Func<TInstance, IEnumerable<TData>>>
表示其类型实现(但未声明)IEnumerable<TData>
的属性.
例如我有一个属性(property)声明为:
public SomeProp List<String> {get;set;}
, 一个值对象 new[] {"a", "bee", "sea"}
,以及表达式 obj => obj.SomeProp
我已经成功编写了提取信息的代码:
the concrete implementation of
IEnumerable<>
forSomeProp
isList<>
因此我可以调用 values.ToList()
在我的 IEnumerable<string>
values 对象并成功将结果分配给属性。
对于 IEnumerable<>
的任何特定实现我可以手动编写代码来检测该实现,并编写代码来创建满足它的具体对象。
实际上,我目前有一个小型映射字典,其中涵盖了一些情况:
new Dictionary<Type, Func<IEnumerable<TProp>, IEnumerable<TProp>>>
{
{ typeof(List<>), (vals) => vals.ToList() },
{ typeof(IList<>), (vals) => vals.ToList() },
{ typeof(Collection<>), (vals) => new Collection<TProp>(vals.ToList()) },
{ typeof(ICollection<>), (vals) => new Collection<TProp>(vals.ToList()) },
};
当然,这甚至没有涵盖大多数常见情况,更不用说涵盖所有可能的情况了!
有什么方法可以编写采用任意“值”的反射代码 IEnumerable<T>
和目标具体 IEnumerable<T>
,并根据值创建具体实例?
这似乎有点乐观,但我觉得值得一问 :)
最佳答案
TL;DR:在一般情况下,这是不可能的。最后,这只是接口(interface)不能直接构造的问题。
在 .NET 框架类型中
如果你的目标类型确实是像List<>
这样的具体类型或 Collection<>
, 那么就可以从它的 Type
中创建一个实例目的。您仍然必须假设存在一个接受 IEnumerable<T>
的构造函数作为第一个也是唯一的论点。即使使用常见的框架类型也不是这种情况:
Type[] types = { typeof(List<string>), typeof(IList<string>), typeof(Collection<string>), typeof(ICollection<string>) };
IEnumerable<T> values = new List<T> { /* ... */ };
foreach (var type in types) {
var concreteInstance = type.GetConstructor(new Type[] { typeof(IEnumerable<T>) })?.Invoke(new object[] { values });
// Succeeds for List<>.
// Fails for IList<> as not a concrete type.
// Fails for Collection<> as no constructor accepts IEnumerable as first argument.
// Fails for ICollection as not a concrete type.
}
一般情况
让我们定义以下接口(interface):
interface IArbitrary<T> : IEnumerable<T> { }
事实上,目前还没有这个接口(interface)的具体实现。因此,无论您多么努力地尝试,反射代码都不可能从 IArbitrary<T>
中创建“目标具体 IEnumerable<T>
”。
关于c# - 从另一个 IEnumerable 填充任意具体的 IEnumerable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58834774/