连接两个对象,我知道它们是相同的IEnumerable<>类型

时间:2015-01-27 13:54:48

标签: c# generics ienumerable

好的,我知道我可能已经误入了过于复杂的事情,但我仍然想知道如何做下面的工作。我要重新修改实际的应用程序,不要这么做,但为了将来的参考,这似乎是一个很好的问题。

情况:

我有一个ExpandoObject我通过string paramName添加了属性。这一切都很好,但后来我意识到有时候我想要一个ExpandoObject属性,它是某种IEnumerable<>,当我为第二次和随后的时间设置参数时,我不想改变它存储列表,但我想连接它。

问题当然是IEnumerable没有Add方法。所以,我可以用两个相同类型的IEnumerable<>的串联替换。我可以牺牲使用非通用IEnumerables的能力。

我感到非常聪明,直到IntelliSense不允许我写eo[paramName] = (eo[paramName] as IEnumerable<>).Concat(param as IEnumerable<>);正如您从完整代码中看到的那样,我确信,parameo[paramName]都是某种{ {1}},但我不知道如何告诉编译器我希望他做什么。

有什么建议吗?

IEnumerable<>

2 个答案:

答案 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进行联合。如果现有的枚举与您尝试添加的类型不同,则会导致运行时错误。