C# 使用Simple Injector解析具有相同类和接口的多个对象
在我的新项目中,我正在尝试从Unity迁移到Simple Injector。它比统一快得多,我必须试一试。我有过一些颠簸,但没有什么是我不能克服的。但我用“按键查找”打了另一个 我已经读过SimpleInjector的创建者在其中陈述他的信念,即每个接口不需要解析多个类 我必须是一个差劲的程序员,因为我已经用Unity做了这件事(Unity非常支持它),并且想在我当前的项目中做这件事 我的设想是我有一个IRepository接口。我想使用IRepository接口抽象两个独立的存储库。像这样:C# 使用Simple Injector解析具有相同类和接口的多个对象,c#,.net,simple-injector,C#,.net,Simple Injector,在我的新项目中,我正在尝试从Unity迁移到Simple Injector。它比统一快得多,我必须试一试。我有过一些颠簸,但没有什么是我不能克服的。但我用“按键查找”打了另一个 我已经读过SimpleInjector的创建者在其中陈述他的信念,即每个接口不需要解析多个类 我必须是一个差劲的程序员,因为我已经用Unity做了这件事(Unity非常支持它),并且想在我当前的项目中做这件事 我的设想是我有一个IRepository接口。我想使用IRepository接口抽象两个独立的存储库。像这样:
container.Register<FirstData>(() => new FirstData());
container.Register<IRepository>(
() => new GenericRepository(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register<IRepository>(
() => new GenericRepository(container.GetInstance<SecondData>()));
container.Register(()=>newfirstdata());
集装箱。登记(
()=>新的GenericRepository(container.GetInstance());
container.Register(()=>newsecondentities());
集装箱。登记(
()=>新的GenericRepository(container.GetInstance());
IRepository/GenericRepository是一个相当常见的抽象,但在SimpleInjector中只能有一个
在Unity中,我可以注册我的两个存储库,然后设置构造函数注入来注入我需要的实例。这是使用实例的键来完成的。(我不需要在我的普通代码中执行Resolve
调用,也不需要在设置之外向Unity添加依赖项。)
对于简单的喷油器,这不起作用。但是,不管是好是坏,Simple Injector的所有者认为这个功能是个坏主意
注意:作者的“应用内”系统看起来像是使用字符串键进行查找,但每次都需要不同的类(DefaultRequestHandler
、OrdersRequestHandler
和CustomersRequestHandler
)我只有一个GenericRepostory
,它允许我抽象我的存储库方法,而不管我连接到什么。
我想每次我想实例化它时,我都可以继承我的GenericRepostory
。或者让它接受一个我不需要的随机类型参数。但这让我的设计变得混乱,所以我希望能找到另一种方法
那么,有没有什么解决办法不让我创建虚假类型来区分我的两个IRepository/GenericRepository实例?我们最终将我们的通用存储库更改为如下所示:
/// The Type parameter has no funcionality within the repository,
/// it is only there to help us differentiate when registering
/// and resolving different repositories with Simple Injector.
public class GenericRepository<TDummyTypeForSimpleInjector> : IRepository
container.Register<FirstData>(() => new FirstData());
container.Register(() => new GenericRepository<FirstDataSelector>
(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register(() => new GenericRepository<SecondDataSelector>
(container.GetInstance<SecondData>()));
然后我可以这样注册它们:
/// The Type parameter has no funcionality within the repository,
/// it is only there to help us differentiate when registering
/// and resolving different repositories with Simple Injector.
public class GenericRepository<TDummyTypeForSimpleInjector> : IRepository
container.Register<FirstData>(() => new FirstData());
container.Register(() => new GenericRepository<FirstDataSelector>
(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register(() => new GenericRepository<SecondDataSelector>
(container.GetInstance<SecondData>()));
container.Register(()=>newfirstdata());
container.Register(()=>新的GenericRepository
(container.GetInstance());
container.Register(()=>newsecondentities());
container.Register(()=>新的GenericRepository
(container.GetInstance());
(请注意GenericRepository上的泛型类型参数,我没有将其注册为IRepository。这两个更改对于实现此功能至关重要。)
这个很好用。然后我就可以在业务逻辑的构造函数注入中使用该注册
container.Register<IFirstBusiness>(() => new FirstBusiness
(container.GetInstance<GenericRepository<FirstDataSelector>>()));
container.Register<ISecondBusiness>(() => new SecondBusiness
(container.GetInstance<GenericRepository<SecondDataSelector>>()));
container.Register(()=>newfirstbusiness
(container.GetInstance());
container.Register(()=>newsecondbusiness
(container.GetInstance());
由于我的业务类采用了IRepository
,因此它工作正常,不会向业务类公开IOC容器或我的存储库的实现
我基本上使用类型参数作为查找键。(我知道,但我的选择有限。)
不得不在我的设计中添加虚拟类有点令人失望,但我们的团队认为这个缺点是值得的,而不是放弃简单的注入器并返回Unity。我们最终将通用存储库更改为这样:
/// The Type parameter has no funcionality within the repository,
/// it is only there to help us differentiate when registering
/// and resolving different repositories with Simple Injector.
public class GenericRepository<TDummyTypeForSimpleInjector> : IRepository
container.Register<FirstData>(() => new FirstData());
container.Register(() => new GenericRepository<FirstDataSelector>
(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register(() => new GenericRepository<SecondDataSelector>
(container.GetInstance<SecondData>()));
然后我可以这样注册它们:
/// The Type parameter has no funcionality within the repository,
/// it is only there to help us differentiate when registering
/// and resolving different repositories with Simple Injector.
public class GenericRepository<TDummyTypeForSimpleInjector> : IRepository
container.Register<FirstData>(() => new FirstData());
container.Register(() => new GenericRepository<FirstDataSelector>
(container.GetInstance<FirstData>()));
container.Register<SecondEntities>(() => new SecondEntities());
container.Register(() => new GenericRepository<SecondDataSelector>
(container.GetInstance<SecondData>()));
container.Register(()=>newfirstdata());
container.Register(()=>新的GenericRepository
(container.GetInstance());
container.Register(()=>newsecondentities());
container.Register(()=>新的GenericRepository
(container.GetInstance());
(请注意GenericRepository上的泛型类型参数,我没有将其注册为IRepository。这两个更改对于实现此功能至关重要。)
这个很好用。然后我就可以在业务逻辑的构造函数注入中使用该注册
container.Register<IFirstBusiness>(() => new FirstBusiness
(container.GetInstance<GenericRepository<FirstDataSelector>>()));
container.Register<ISecondBusiness>(() => new SecondBusiness
(container.GetInstance<GenericRepository<SecondDataSelector>>()));
container.Register(()=>newfirstbusiness
(container.GetInstance());
container.Register(()=>newsecondbusiness
(container.GetInstance());
由于我的业务类采用了IRepository
,因此它工作正常,不会向业务类公开IOC容器或我的存储库的实现
我基本上使用类型参数作为查找键。(我知道,但我的选择有限。)
不得不在我的设计中添加虚拟类有点令人失望,但我们的团队认为这个缺点是值得的,而不是放弃简单的注入器并返回Unity。您自己的答案实际上相当不错,但不幸的是,您将泛型类型参数视为虚拟;您应该使其成为您设计的头等公民:
public interface IRepository<TData> { }
public clss GenericRepository<TData> : IRepository<TData>
{
public GenericRepository(TData data) { }
}
更进一步说,您的业务类也可能受益于泛型类型。例如,看看每个业务操作都有自己的类,但所有业务操作都隐藏在相同的泛型ICommandHandler
抽象后面。执行此操作时,所有业务类都可以通过单个调用注册:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
container.RegisterManyForOpenGeneric(typeof(ICommandHandler),
类型(ICommandHandler).Assembly);
此调用在提供的程序集中搜索ICommandHandler
接口的实现,并注册找到的每个实现