通过反射动态修改 IEnumerable 属性
Posted
技术标签:
【中文标题】通过反射动态修改 IEnumerable 属性【英文标题】:Dynamically modifying an IEnumerable property via reflection 【发布时间】:2020-12-14 16:50:31 【问题描述】:我有各种各样的类,它们具有实现IEnumerable
的各种属性(例如IEnumerable<string>
、IEnumerable<bool>
、IEnumerable<enum>
等)。我正在尝试编写一些代码来过滤这些属性的值(例如,如果值为 "one", "two", "three"
,我可能想过滤.Contains("t")
的位置)。
这是我所拥有的精髓:
class MyObject
public IEnumerable<string> stringProp get; set; = new[] "one", "two", "three" ;
public IEnumerable<bool> boolProp get; set; = new[] true, false, true ;
public IEnumerable<int> intProp get; set; = new[] 1, 2, 3 ;
public static void Main(string[] args)
MyObject obj = new MyObject();
foreach (PropertyInfo prop in typeof(MyObject).GetProperties())
prop.SetValue(obj, (prop.GetValue(obj) as IEnumerable<dynamic>).Where(val => val != null));
问题是,当我尝试将值设置回对象 (property.SetValue
) 时,会引发错误,因为新值是 IEnumerable<object>
。
Object of type 'System.Linq.Enumerable+WhereArrayIterator`1[System.Object]' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[System.String]'
我尝试过Convert.ChangeType
,但这不起作用,因为IEnumerable
没有实现IConvertible
。
我该如何做到这一点?为什么 LINQ Where
查询将 IEnumerable<dynamic>
更改为 IEnumerable<object>
?
【问题讨论】:
能否请您添加错误和minimal reproducible example ? 另外,转换类型的不是Where
,而是compiler
IEnumerabledynamic
会为它解决的每个问题多产生 2 个问题。
我添加了一个最小的可重现示例
【参考方案1】:
我理解正确吗?你在寻找这样的东西吗?
var obj = new MyObject();
foreach (var prop in typeof(MyObject).GetProperties())
//assumming all things are IEnumerable<something>
var type = prop.PropertyType.GenericTypeArguments[0];
//We can't "instantiate" something as ephemeral as an IEnumerable,
//so we need something more concrete like a List
//There might be other ways to filter - this seemed to be the easiest
var listType = typeof(List<>).MakeGenericType(type);
var instance = (IList)Activator.CreateInstance(listType);
var currentEnum = (IEnumerable)prop.GetValue(obj);
foreach (var item in currentEnum)
if (item != default) // != null would be silly for booleans and ints
instance.Add(item);
prop.SetValue(obj, instance);
总结:泛型和动态关键字通常不会以这种方式混合使用 - 使用动态泛型参数是没有意义的。将动态视为实际上意味着“对象”的东西,但也可以让你写任何你喜欢的东西。当然,IEnumerable
【讨论】:
啊,是的!这样可行!我不知道MakeGenericType
或Activator.CreateInstance
根据您实际想要在代码中执行的操作,您可能还需要查看表达式和函数。也许你可以在没有这些讨厌的反射的情况下做到这一点:)以上是关于通过反射动态修改 IEnumerable 属性的主要内容,如果未能解决你的问题,请参考以下文章