调用通用接口

时间:2009-02-01 23:45:40

标签: c# generics

public interface IProcessor<T>
{
  void Process(T instance);
}


foreach(AbstractType instance in myClass.SomeCollection)
  OnProcess(instance);

public void OnProcess<T>(T instance)
{
  IProcessor<T> processor = 
    unityContainer.Resolve<IProcessor<T>>();
  processor.Process(instance);
}

此代码的问题在于中的OnProcess始终为AbstractType,而不是传递的实例的具体类型。我目前看到两种可能性。

01:创建非通用IProcessor并将其用作IProcessor的基础。任何实现者都必须实现泛型和非泛型Process方法,通常是类型转换并传递给泛型方法。

02:使用Type.MakeGenericType获取IProcessor,解决该问题,然后使用反射来调用Process方法。

这两种方法都有点“不干净”。任何人都可以想到一种方法,我可以做到这一点,而不必诉诸这些做法?

由于

皮特

2 个答案:

答案 0 :(得分:3)

2将成为性能杀手(必要的动态/重新选择调用特别慢)

1是这个问题的常见答案,特别是在明确实施的情况下;问题是获得类型...团结允许查询Type实例,而不是通过泛型?如果是这样的话......当然,您可能仍然需要使用MakeGenericType

Type intType = typeof(IProcessor<>).MakeGenericType(instanceType);
IProcessor proc = (IProcessor) IoC.Resolve(intType);

instanceType可能来自instance.GetType()。出于类似原因,将T作为Type公开IProcessor可能会有所帮助:

public interface IProcessor
{
    void Process(object instance);
    Type InstanceType {get;}
}
public interface IProcessor<T> : IProcessor
{
    void Process(T instance);
}
class SomeClass: IProcessor<int>
{
    public void Process(int instance)
    {
        throw new NotImplementedException();
    }
    Type IProcessor.InstanceType {get {return typeof(int);}}
    void IProcessor.Process(object instance)
    {
        Process((int)instance);
    }
}

当然,(可选的)基类可能允许您避免某些实现:

abstract class SomeBase<T> : IProcessor<T>
{
    public void Process(T instance)
    {
        OnProcess(instance);
    }
    Type IProcessor.InstanceType {get {return typeof(T);}}
    void IProcessor.Process(object instance)
    {
        Process((T)instance);
    }
    protected abstract void OnProcess(T instance);
}

答案 1 :(得分:0)

如果我理解您的问题,您希望调用依赖于2种类型(处理器类型和正在处理的对象)的进程。是对的吗?如果是这种情况,您可以使用多方法模式来解决此类问题。这是一个例子:

public interface IProcessor
{
    void Process( IThingToProcess p ); // Will call p.ProcessMe()
    void Process( ThingToProcess1 concreteP ); // Called back from ThingToProcess1.ProcessMe
}

public interface IThingToProcess
{
     void ProcessMe( IProcessor p );
}

public class ThingToProcess1 : IThingToProcess
{
    public void ProcessMe( IProcessor p ) { p.Process( this ); }
}