我有两个接口,一个是泛型的,一个是非泛型的,具有继承层次结构:
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上可用的强类型属性。不幸的是,这是不可能的,因为我似乎无法省略类型参数。
有没有人知道枚举实现通用接口的控件的方法,以防止我必须编写几个循环而不是一个循环?或许使用反射?
答案 0 :(得分:3)
这是不可能的,因为IGenericRelation<T,F>
是与IGenericRelation<G,I>
完全不同的类型。如果您需要访问所有IGenericRelation
共有的特定属性,那么您需要在IRelation
层实现它们,或者在IRelation
和IGenericRelation<,>
之间引入第三个接口。实现这些的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。