好的,我知道我可能已经误入了过于复杂的事情,但我仍然想知道如何做下面的工作。我要重新修改实际的应用程序,不要这么做,但为了将来的参考,这似乎是一个很好的问题。
情况:
我有一个ExpandoObject
我通过string paramName
添加了属性。这一切都很好,但后来我意识到有时候我想要一个ExpandoObject属性,它是某种IEnumerable<>
,当我为第二次和随后的时间设置参数时,我不想改变它存储列表,但我想连接它。
问题当然是IEnumerable
没有Add
方法。所以,我可以用两个相同类型的IEnumerable<>
的串联替换。我可以牺牲使用非通用IEnumerables的能力。
我感到非常聪明,直到IntelliSense不允许我写eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);
正如您从完整代码中看到的那样,我确信,param
和eo[paramName]
都是某种{ {1}},但我不知道如何告诉编译器我希望他做什么。
有什么建议吗?
IEnumerable<>
答案 0 :(得分:1)
您可以使用反射强制它。我宣布了一个这样的方法:
public IEnumerable<T> Concat<T>(IEnumerable<T> obj, IEnumerable<T> obj2)
{
return obj.Concat(obj2);
}
然后代替行eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);
插入此代码:
MethodInfo info = GetType().GetMethod("Concat");
info = info.MakeGenericMethod(enumerableType);
eo[paramName] = info.Invoke(this, new [] {eo[paramName], param});
答案 1 :(得分:-1)
您必须为IEnumerable<T>
指定类型参数。 并且你不能连续两个不同类型的枚举。例如,这是不允许的:作为评论中提到的Servy,它允许连接两个不同类型的枚举。即使它们没有明确地共享基类型,因为.NET中的每个引用类型都是object
类型。所以允许:
IEnumerable<Apple> apples = new List<Apple>();
IEnumerable<Car> cars = new List<Car>();
cars.Concat(apples); // compiler error
IEnumerable<object> enuerableOfObjets = cars.Concat<object>(apples);
但在我看来,这导致了泛型集合的整个概念,这是荒谬的。
您可以通过两种方法分割方法来完成您想要的任务:
private void SetParam<T>(IDictionary<string, object> eo, string paramName, T param)
{
// is not IEnumerable<>, but it might be not-supported IEnumerable
if (typeof(T).GetInterfaces().Contains(typeof(System.Collections.IEnumerable)))
throw new NotSupportedException("Non-generic collection types are not supported");
// it is just plain not-colection, so set value
eo[paramName] = param;
}
private void SetParam<T>(IDictionary<string, object> eo, string paramName, IEnumerable<T> param)
{
if (!eo.ContainsKey(paramName))
eo[paramName] = param;
else
eo[paramName] = (eo[paramName] as IEnumerable<T>).Concat(param);
}
此解决方案使用相同类型IEnumerable<T>
对T
进行联合。如果现有的枚举与您尝试添加的类型不同,则会导致运行时错误。