Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.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#_Generics_Dependency Injection_Factory_Simple Injector - Fatal编程技术网

C# 如何通过单个实例解析通用接口,而不提供单独的具体实现

C# 如何通过单个实例解析通用接口,而不提供单独的具体实现,c#,generics,dependency-injection,factory,simple-injector,C#,Generics,Dependency Injection,Factory,Simple Injector,我有一个类MyBusiness,我在SimpleInjector注册 container.RegisterSingleton<MyBusiness>(() => new MyBusiness(Konstants.ConnectionString)); container.RegisterSingleton(()=>newmybusiness(Konstants.ConnectionString)); 现在MyBusiness实现了一个接口IRepositoryProvide

我有一个类MyBusiness,我在SimpleInjector注册

container.RegisterSingleton<MyBusiness>(() => new MyBusiness(Konstants.ConnectionString));
container.RegisterSingleton(()=>newmybusiness(Konstants.ConnectionString));
现在MyBusiness实现了一个接口IRepositoryProvider,如下所示

public interface IRepositoryProvider{
  IReader<Entity> Get<Entity>();
  IWriter<Entity> Writer<Entity>();
}
公共接口IRepositoryProvider{
IReader Get();
IWriter Writer();
}
IReaderIWriter都继承了IDisposable,实体是某个数据库实体,如果您愿意的话,它是一个POCO类,可能相当多(假设某个工具生成的应用程序中有50多个实体)。MyBusiness为作为通用参数传递的任何实体提供IReaderIWriter的实现,我不为任何IReaderIWriter提供实现

因此,在代码中,它们的用法如下:

var biz = container.GetInstance<MyBusiness>();
using(var users = biz.Get<User>()){
...

}
var biz=container.GetInstance();
使用(var users=biz.Get()){
...
}
由于上述原因,我无法在构造函数注入中使用IReaderIWriter

public class MyUserController:Controller{
   public MyUserController(IReader<User> arg){
   }
   // other functionality
}
公共类MyUserController:Controller{
公共MyUserController(IReader参数){
}
//其他功能
}
上面对IReader IWriter的调用是否可以减少到这个程度

var users = container.GetInstance<IReader<User>>());
var users=container.GetInstance());
这样我就可以轻松地使用IReaderIWriter实现作为依赖注入

IReader和IWriter都实现IDisposable

让我们从这个开始:抽象一般不应该实现
IDisposable
。这样做是在通过抽象泄漏实现细节。这意味着您违反了,其中规定:

抽象不应该依赖于细节。细节应该取决于抽象

您正在泄漏实现细节,因为该抽象的所有实现通常不太可能都有需要处置的资源。例如:

  • 您可能有不需要处理的模拟或伪实现
  • 如果您为这种抽象创建了装饰器或拦截器,那么它们通常没有任何需要处理的资源
不过,由于客户机希望dispose实际处理“真实的东西”,因此这些装饰器和其他实现被迫将调用委托给任何包装好的调用

但是如果装饰器确实通过构造函数注入获得了一个实例呢。它是否知道如何处理依赖关系?也许它有一个漫长的生活方式和处置它实际上打破了系统

解决方案是从抽象中删除
IDisposable
。这通常会使应用程序代码更简单,因为客户端代码不再能够调用
Dispose
。这意味着要测试的代码更少,出错的事情也更少(因为有人调用了dispose,而他不应该这样做)

然而,这确实意味着,我们应该转移处理该实例的责任,这通常是依赖注入给我们的。它在应用程序(称为)中为我们提供了一个中心位置,它确切地知道何时处理什么

通常,当使用DI容器时,解决方案是将此类类型注册到一个限定范围的生活方式。这意味着实例存在一定的时间。在类的生命周期结束后,DI容器如何代表您控制调用
Dispose

对于简单喷油器,通常按如下方式进行:

container.Register(typeof(IReader<>), typeof(ReaderImpl<>), Lifestyle.Scoped);
换句话说,这正是您描述的代码

但是请注意,不要让任何应用程序代码依赖于容器。这是一个众所周知的反模式,叫做。相反,将
IRepositoryProvider
实现移动到合成根目录中

IReader和IWriter都实现IDisposable

让我们从这个开始:抽象一般不应该实现
IDisposable
。这样做是在通过抽象泄漏实现细节。这意味着您违反了,其中规定:

抽象不应该依赖于细节。细节应该取决于抽象

您正在泄漏实现细节,因为该抽象的所有实现通常不太可能都有需要处置的资源。例如:

  • 您可能有不需要处理的模拟或伪实现
  • 如果您为这种抽象创建了装饰器或拦截器,那么它们通常没有任何需要处理的资源
不过,由于客户机希望dispose实际处理“真实的东西”,因此这些装饰器和其他实现被迫将调用委托给任何包装好的调用

但是如果装饰器确实通过构造函数注入获得了一个实例呢。它是否知道如何处理依赖关系?也许它有一个漫长的生活方式和处置它实际上打破了系统

解决方案是从抽象中删除
IDisposable
。这通常会使应用程序代码更简单,因为客户端代码不再能够调用
Dispose
。这意味着要测试的代码更少,出错的事情也更少(因为有人调用了dispose,而他不应该这样做)

然而,这确实意味着,我们应该转移处理该实例的责任,这通常是依赖注入给我们的。它在应用程序(称为)中为我们提供了一个中心位置,它确切地知道何时处理什么

通常,当使用DI容器时,解决方案是将此类类型注册到一个限定范围的生活方式。这意味着
container.GetInstance<IReader<User>>());