如何枚举实现通用接口的所有项目?

时间:2009-06-10 15:08:37

标签: c# generics reflection collections

我有两个接口,一个是泛型​​的,一个是非泛型的,具有继承层次结构:

public interface IGenericRelation<TParent, TChild> : IRelation

public interface IRelation

通用的一个是由几个动态加载的服务器控件实现的,我希望枚举实现此接口的控件集合。我可以做以下

    foreach (IRelation relationControl in this.uiPlhControls.Controls.OfType<IRelation)
    { ... }

但我真正希望能做的是......

    foreach (IGenericRelation<,> relationControl in this.uiPlhControls.Controls.OfType<IGenericRelation<,>)
    { ... }

然后能够将relationControl与它提供的类型一起使用,然后我就可以访问IGenericRelation上可用的强类型属性。不幸的是,这是不可能的,因为我似乎无法省略类型参数。

有没有人知道枚举实现通用接口的控件的方法,以防止我必须编写几个循环而不是一个循环?或许使用反射?

2 个答案:

答案 0 :(得分:3)

这是不可能的,因为IGenericRelation<T,F>是与IGenericRelation<G,I>完全不同的类型。如果您需要访问所有IGenericRelation共有的特定属性,那么您需要在IRelation层实现它们,或者在IRelationIGenericRelation<,>之间引入第三个接口。实现这些的object。这样做的原因是编译器无法推断出要实现的类型。

最简单的方法是在较高级别(IRelation或中间接口)将您的两个属性实现为IGenericRelation<,>,并在{{1}}级别强类型

答案 1 :(得分:1)

您尝试访问哪些强类型属性?如果它们是强类型的,因为它们是泛型的输入类型,那么在不提供foreach循环中的类型的情况下,您将无法访问它们。如果它们是强类型的,但与提供的类型相关,您可以将它们移动到IRelation类吗?

使用代码示例会更有意义 - 假设您的类类似于:

public IRelation
{
   public string RelationshipType { get; set; }
}

public IGenericRelation<TParent, TChild> : IRelation
{
    public TParent Parent { get; set; }
    public TChild Child { get; set; }
}

如果您的列表中包含一个IGenericRelation<Foo, Bar>和一个IGenericRelation<Fizz, Buzz>,则无法在不知道您要查找的具体类型的情况下进行枚举并同时返回:

//Theoretical, non-compiling example....
foreach (IGenericRelation<,> relationControl in this.uiPlhControls.Controls.OfType<IGenericRelation<,>>)
{ 
    //This wouldn't work for type IGenericRelation<Fizz, Buzz>
    relationControl.Parent.FooProperty = "Wibble";

    //You would be able to access this, but there is no advantage over using IRelation
    relationControl.RelationshipType = "Wibble";
}

(请注意,我还必须从示例代码中更改foreach中的relationControl类型,以便可能的用法有所帮助。)


从根本上说,将.NET泛型与C ++模板类相同可能会有所帮助(我知道实现是不同的,但在这方面的效果是相同的)。想象一下,在编译时,将检查所有代码是否使用IGenericRelation类,并通过对TParent和TChild关键字执行查找并将其替换为请求的类型来创建具体的非泛型类。由于两个创建的类与任何其他两个.NET类是分开的,因此请求“所有以该模板开头的类”是没有意义的,您可以做的最好的事情是查找共享基类或接口 - 在这种情况下IRelation。