Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通用参数对象处理程序的工厂_C#_Dependency Injection_Polymorphism_Factory_Factory Pattern - Fatal编程技术网

C# 通用参数对象处理程序的工厂

C# 通用参数对象处理程序的工厂,c#,dependency-injection,polymorphism,factory,factory-pattern,C#,Dependency Injection,Polymorphism,Factory,Factory Pattern,我有一个API,涉及几个无行为参数对象,每个对象都有自己的处理程序: //some POCOs public class CustomerChange : IChange{ public int CustomerId {get;set;} public DateTime TimeStamp {get;set;} } public class SomeOtherChange : IChange{ public int AParameter {get;set;}

我有一个API,涉及几个无行为参数对象,每个对象都有自己的处理程序:

//some POCOs
public class CustomerChange : IChange{

    public int CustomerId {get;set;}

    public DateTime TimeStamp {get;set;}

}

public class SomeOtherChange : IChange{

    public int AParameter {get;set;}

    public string AnotherParameter {get;set;}

    public DateTime TimeStamp {get;set;}

}

// stateless handlers that will be resolve with a DI container (Ninject in my case)
public interface IChangeHandler<TChange>{
     public Handle(T change);
}

public class CustomerChangeHandler : IChangeHandler<CustomerChange>{

     private readonly ICustomerRepository customerRepository;

     public  CustomerChangeHandler(ICustomerRepository repo){
          customerRepository = repo;
     }

     public Handle(CustomerChange change){

           customerRepository.DoStuff(change.CustomerId);

     }
}
//一些POCO
公共类CustomerChange:IChange{
public int CustomerId{get;set;}
公共日期时间时间戳{get;set;}
}
公共类其他更改:IChange{
公共int参数{get;set;}
公共字符串另一个参数{get;set;}
公共日期时间时间戳{get;set;}
}
//将使用DI容器解析的无状态处理程序(在我的例子中为Ninject)
公共接口IChangeHandler{
公共处理(T变更);
}
公共类CustomerChangeHandler:IChangeHandler{
专用只读ICCustomerRepository customerRepository;
公共CustomerChangeHandler(ICCustomerRepository repo){
customerRepository=回购;
}
公共句柄(CustomerChange更改){
customerRepository.DoStuff(change.CustomerId);
}
}
等等

当IChange的类型在编译时已知时,这非常有效,但是,我遇到了需要处理未知类型的IChange的情况

在理想的世界中,我希望能够做到以下几点:

public class ChangeHandlerFactory {

   public void HandleChange(IChange change){
        // get the change handler from the DI container based on the concrete type of IChange
        var handlerType = typeof(IChangeHandler<>)
            .MakeGenericType(change.GetType());

        object handler = container.GetInstance(handlerType);  //is this an acceptable way to use a DI container?  I would need a dependency on IKernel in this case

        handler.Handle(change);  // I would need to cast the change object to the appropriate type for the handler or make handler dynamic which seems like it has the potential for hard to debug issues
   }


}
公共类changerHandlerFactory{
公共无效处理更改(IChange更改){
//根据IChange的具体类型从DI容器中获取更改处理程序
var handlerType=typeof(IChangeHandler)
.MakeGenericType(change.GetType());
objecthandler=container.GetInstance(handlerType);//这是使用DI容器的一种可接受的方式吗?在这种情况下,我需要依赖IKernel
Handle.Handle(change);//我需要将change对象强制转换为处理程序的适当类型,或者使处理程序成为动态的,这可能会导致难以调试的问题
}
}
我对将处理程序作为动态处理程序的关注是,可能有人做了一些不正确的事情,并出现难以调试的错误

我可以让每个POCO实现一个GetHandler方法来检索处理程序,但这基本上破坏了将它们分开的初衷


在这样的情况下,怎样才能让处理者得到最好的帮助?有没有一种方法可以不使用我的DI容器(ninject)作为服务定位器和/或不使用dynamics来实现这一点?我发现我已经多次遇到这种情况,但还没有找到一种感觉正确的解决方案。

最简单的是依赖项反转。让POCO提供一个委托来获取自己的处理程序,因为它显然已经知道它是什么类型

interface IChange
{
    IChangeHandler GetHandler(Container container);
}

public class SomeOtherChange : IChange
{
    public int AParameter {get;set;}

    public string AnotherParameter {get;set;}

    public DateTime TimeStamp {get;set;}

    public IChangeHandler GetHandler(Container container) => container.GetInstance<SomeOtherChangeHandler>();

}
当然,这就给你留下了一个问题:一旦你拥有了处理器,该如何处理它。同样,您可以让POCO完成以下工作:

public class SomeOtherChange : IChange
{
    public int AParameter {get;set;}

    public string AnotherParameter {get;set;}

    public DateTime TimeStamp {get;set;}

    public void GetAndCallHandler(Container container)
    {
        var handler = container.GetInstance<SomeOtherChangeHandler>();
        handler.Handle(this);
    }
}
public类SomeOtherChange:IChange
{
公共int参数{get;set;}
公共字符串另一个参数{get;set;}
公共日期时间时间戳{get;set;}
public void GetAndCallHandler(容器)
{
var handler=container.GetInstance();
处理(这个);
}
}
当IChange的类型在运行时已知时,这种方法非常有效。但是,我遇到了一种情况,需要在运行时处理未知类型的IChange。你是说编译时吗?如果您在运行时无法判断某事物是什么类型,那么就会发生一些真正错误的事情:D
public class SomeOtherChange : IChange
{
    public int AParameter {get;set;}

    public string AnotherParameter {get;set;}

    public DateTime TimeStamp {get;set;}

    public void GetAndCallHandler(Container container)
    {
        var handler = container.GetInstance<SomeOtherChangeHandler>();
        handler.Handle(this);
    }
}