2014-01-17 15 views
0

我有几个成员C#调用泛型方法的类的每个领域

public interface IEquipmentHolder 
{ 
    ITypedServiceProvider<IGrabberChannel> VideoChannels { get; } 
    ITypedServiceProvider<IMicrophone> Microphones { get; } 
    ITypedServiceProvider<ISpeaker> Speakers { get; } 
    ... 
} 

和功能

void visitChilds<T>(ITypedServiceProvider<T> childsList) where T : INamedComponent 
    { 
     ... 
    } 

在一些地方我的代码数据类,我想调用函数数据类的每个字段。所以我这样做:

visitChilds(equipment.VideoChannels); 
visitChilds(equipment.Microphones); 
... 

但是,可能我会在数据类中添加一些新的字段,并不想忘记在这之后修复这些地方。

我的问题:是否有可能使用反射为类的每个数据成员调用泛型函数?如果不是,我们可以把编译时检查新的字段在C#代码中吗?

+0

是的,可以。反射是一种选择。 –

+3

还要考虑到这种问题 - 担心在另一个代码中添加代码时会在一个地方忘记一些代码,并且很好地通过单元测试解决。检查每个属性的反射代码可以作为确保每个属性都包含在内的单元测试的基础。你会写没有反射的实时代码,测试会告诉你,如果你错过了任何。 –

回答

0
  1. 你打算多久添加一些字段,而“忘记”更新调用代码?
  2. 你有多快就会发现忘记添加电话visitChilds()
  3. IEquipmentHolder怎么样只有一个属性ITypedServiceProvider<INamedComponent> Items { get; }

反射比直接调用要慢(也许你应该发射IL?),其他代码可能只是不值得'改进',特别是如果它很容易发现它没有访问的新设置。

另请注意,添加一组新的INamedComponents需要对IEquipmentHolder接口和全部实现进行重大更改。

0

您可以使用Expression框架生成一个lambda,该接口将为每个属性调用visitChilds

您需要使用反射来生成表达式,但这将是一次性击中。之后,您将拥有一个动态编译的lambda,您可以调用该lambda会更快。

我已经做过类似的事情,因此我将对象的实例转换为Dictionary<string,object>,其中每个键都是属性的名称,值是该属性的值。我们为每种我们想要转换的类型生成一个lambda,并且它工作得非常好。

0

如果ITypedServiceProvider是协变的,即,声明如下,

ITypedServiceProvider<out T> 
{ 
    ... 
} 

那么你可以有

IEquipmentHolder 
{ 
    IEnumerable<ITypedServiceProvider<INamedComponent>> 
     NamedComponents { get; } 
} 

那么你可以做

void VisitChildren(IEquipmentHolder equipment) 
{ 
    foreach(var provider in equipment.NamedComponents) 
    { 
     provider.SomeMemberOfITypedServiceProvider(); 
    } 
}