sTo*_*rov 4 architecture dependency-injection simple-injector
我正在研究一个小型类库,并为我的DI使用简单注入器。类库具有一个访问点(我猜是public某种internal 服务),并且具有一些服务和存储库。
我看到Simple Injector不支持内部构造函数的构造函数注入。例如,我的产品服务如下:
internal class ProductService : IProductService
{
private IProductRepository _productRepository;
internal ProductService(IProductRepository repository)
{
if (repository == null) throw new ArgumentNullException("repository");
_productRepository = repository;
}
}
Run Code Online (Sandbox Code Playgroud)
而我的设置:
container.Register<IProductService, ProductService>();
container.Register<IProductRepository>(() => new ProductRepository());
Run Code Online (Sandbox Code Playgroud)
运行代码时,出现以下异常:
For the container to be able to create ProductService, it should contain exactly one public constructor, but it has 0.
Run Code Online (Sandbox Code Playgroud)
我的问题:
1)是否有特定原因导致注入内部类在体系结构/设计方面不起作用?
2)如何实现这种行为(使用不应该公开的类进行依赖注入),并希望得到这种行为?
Simple Injector会尝试为您提供明智的默认设置。默认情况下,它仅限于具有单个公共构造函数的自动装配类型,因为具有多个构造函数是一种反模式。默认情况下,Simple Injector仅注入公共构造函数,因为为了使Simple Injector能够安全地调用类型的构造函数,此对象必须是公共的。例如,当应用程序在(部分信任)沙箱中运行时,Simple Injector将无法调用内部构造函数,尽管可以完全信任地调用内部构造函数,但是创建此类类型的速度较慢。为了提高性能,最好使类型和构造函数保持公开状态。
除了这些技术限制之外,在正常情况下,组件及其构造函数也将是公共的,因为您通常总是需要访问该组件的外部使用者。这样的使用者的例子是您的单元测试项目和您的组合根项目。
因此,明智的默认设置是“一个公共构造函数”,但是类型本身不必是公共的,尽管解析内部类型会比较慢,并且可能并不总是在沙箱中工作。换句话说,当您不在沙盒中运行时(例如Silverlight或Windows Phone),Simple Injector将能够解析内部类型,只要它们具有单个公共构造函数即可。
但是,如果您确实需要或希望构造函数是内部的,则可以通过实现和注册一个custom来覆盖构造函数解析行为IConstructorResolutionBehavior。这是一个例子:
public class InternalConstructorResolutionBehavior : IConstructorResolutionBehavior
{
private IConstructorResolutionBehavior original;
public InternalConstructorResolutionBehavior(Container container) {
this.original = container.Options.ConstructorResolutionBehavior;
}
public ConstructorInfo GetConstructor(Type implementationType) {
if (!implementationType.GetConstructors().Any()) {
var internalCtors = implementationType.GetConstructors(
BindingFlags.Instance | BindingFlags.NonPublic)
.Where(c => !c.IsPrivate)
.ToArray();
if (internalCtors.Length == 1) return internalCtors.First();
}
return this.original.GetConstructor(implementationType);
}
}
Run Code Online (Sandbox Code Playgroud)
可以按以下方式注册此自定义构造函数解析行为:
var container = new Container();
container.Options.ConstructorResolutionBehavior =
new InternalConstructorResolutionBehavior(container);
// Normal registrations here
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2542 次 |
| 最近记录: |