C#为类的每个字段调用泛型方法

时间:2014-01-17 13:40:43

标签: c# generics system.reflection

我有一个包含多个成员的数据类

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#代码中对新字段进行编译时检查吗?

3 个答案:

答案 0 :(得分:0)

  1. 您多久会添加更多字段并“忘记”更新主叫代码?
  2. 您发现忘记添加visitChilds()的电话的速度有多快?
  3. IEquipmentHolder只有一个属性ITypedServiceProvider<INamedComponent> Items { get; }
  4. 反射比直接调用慢(也许你应该发出IL?)而额外的代码可能不值得“改进”,特别是如果很容易发现它没有被访问的新集。

    另外请注意,添加一组新的INamedComponents需要对IEquipmentHolder界面和所有实施进行重大更改。

答案 1 :(得分:0)

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

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

我之前做过类似的事情,我将对象的实例转换为Dictionary<string,object>,其中每个键都是属性的名称,值是属性的值。我们为每个我们想要转换的类型生成了一个lambda,它运行得非常好。

答案 2 :(得分:0)

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

ITypedServiceProvider<out T>
{
    ...
}

然后你可以

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

那么你可以做到

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