从 C# 中的一堆 ICollection<Implementation> 创建一个 IEnumerable<Interface>

rou*_*tic 3 c# reflection collections casting interface

我有一个由许多集合组成的类,如下所示:

public virtual ICollection<C> CStuff { get; set; }
public virtual ICollection<D> DStuff { get; set; }
public virtual ICollection<E> EStuff { get; set; }
Run Code Online (Sandbox Code Playgroud)

每种类型都实现一个公共接口。

public class C : IStuff {}
public class D : IStuff {}
public class E : IStuff {}
Run Code Online (Sandbox Code Playgroud)

我想在我的班级中创建所有 IStuff 的集合,如下所示:

IEnumerable<IEnumerable<IStuff>> AllStuffCollections 
{
    get { /* how??? */ }
}

public IEnumerable<IStuff> AllStuff 
{ 
   get 
   { 
       foreach (IEnumerable<IStuff> stuffCollection in AllStuffCollections) 
       {
           foreach (IStuff stuff in stuffCollection) 
           {
               yield return stuff;
           }
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在不显式添加每个集合的情况下完成此操作(反射 OK)?就像,我不想这样做:

IEnumerable<IEnumerable<IStuff>> AllStuffCollections 
{
    get 
    { 
        return new List<IEnumerable<IStuff>>() 
        { 
            CStuff.Cast<IStuff>, 
            DStuff.Cast<IStuff>,
            EStuff.Cast<IStuff>
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

最终这个类将IStuff随着时间的推移添加更多的集合,我担心AllStuffCollections当它发生变化时我会忘记将它们包含在内。

此外,集合本身是惰性的(EF 填充的),所以我不想做任何会强制立即“查询所有事情”发生的事情。

Gyö*_*zeg 5

如果反射没问题并且你不介意它的性能,你可以像这样实现它:

public IEnumerable<IEnumerable<IStuff>> GetStuffCollections()
{
    var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
    foreach (var property in properties)
    {
        Type pt = property.PropertyType;
        if (pt.IsGenericType
            && pt.GetGenericTypeDefinition() == typeof(ICollection<>)
            && typeof(IStuff).IsAssignableFrom(pt.GetGenericArguments()[0]))
        {
            yield return (IEnumerable<IStuff>)property.GetValue(this);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)