问题描述
我有许多类,这些类具有实现IEnumerable
的各种属性(例如IEnumerable<string>
,IEnumerable<bool>
,IEnumerable<enum>
等)。我正在尝试编写一些代码来筛选这些属性的值(例如,如果值为{ "one","two","three" }
,则可能要筛选.Contains("t")
的位置)。
这是我所拥有的精髓:
class MyObject
{
public IEnumerable<string> stringProp { get; set; } = new[] { "one","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>
?
解决方法
我理解正确吗?您是否正在寻找类似的东西?
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);
}
摘要:泛型和dynamic关键字通常不会以这种方式混合-使用动态泛型参数是没有意义的。将动态视为实际上意味着“对象”的东西,但也可以让您根据自己的喜好编写任何东西。当然,IEnumerable