使用 2 个参数注入构造函数不起作用
Injecting into constructor with 2 params is not working
我有一个 ASP .Net Web API 控制器,我想使用 2 个参数。第一个是 EF 上下文,第二个是缓存接口。如果我只有 EF 上下文,则会调用构造函数,但是当我添加缓存接口时,我会收到错误消息:
An error occurred when trying to create a controller of type
'MyV1Controller'. Make sure that the controller has a
parameterless public constructor.
private MyEntities dbContext;
private IAppCache cache;
public MyV1Controller(MyEntities ctx, IAppCache _cache)
{
dbContext = ctx;
cache = _cache;
}
我的UnityConfig.cs
public static void RegisterTypes(IUnityContainer container)
{
// TODO: Register your types here
container.RegisterType<MyEntities, MyEntities>();
container.RegisterType<IAppCache, CachingService>();
}
我希望 Entity 现在知道这两种类型,当对 MyV1Controller 函数发出请求时,它应该能够实例化一个实例,因为该构造函数采用它知道的类型,但事实并非如此。知道为什么吗?
[编辑]
请注意,我创建了自己的 class (IConfig
) 并将其注册并将其添加到构造函数中并且它起作用了,但是每当我尝试将 IAppCache
添加到我的构造函数并发出请求时API 我收到错误消息,告诉我它无法构建我的控制器 class。我看到的唯一区别是 IAppCache
不在我的项目命名空间中,因为它是第 3 方 class,但根据我的理解,这无关紧要。
这是 CachingService
的构造函数
public CachingService() : this(MemoryCache.Default) { }
public CachingService(ObjectCache cache) {
if (cache == null) throw new ArgumentNullException(nameof(cache));
ObjectCache = cache;
DefaultCacheDuration = 60*20;
}
检查 IAppCache
实现 CachingService
以确保 class 在初始化时没有抛出任何异常。该无参数异常是在尝试创建控制器时发生错误时的默认消息。这不是一个非常有用的异常,因为它不能准确指出发生的真正错误是什么。
你提到它是第 3 方 interface/class。它可能正在请求容器不知道的依赖项。
引用 Unity Framework IoC with default constructor
Unity 使用最多的参数调用构造函数,在本例中是...
public CachingService(ObjectCache cache) { ... }
由于容器对ObjectCache
一无所知,它将传入null
,根据构造函数中的代码将抛出异常。
更新:
从评论中添加这个,因为它可以证明对其他人有用。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor(MemoryCache.Default));
参考此处Register Constructors and Parameters了解更多详情。
大多数 DI 容器在尝试解析类型时总是寻找具有最大参数数量的构造函数。这就是为什么默认调用 CachingService(ObjectCache cache) 构造函数的原因。由于ObjectCache实例没有注册到Unity,所以解析失败。一旦强制类型注册调用特定构造函数,一切正常。
因此,如果您注册 IAppCache 并强制它调用 CachingService() - 无参数构造函数,它将按预期工作。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor());
以这种方式注册,将强制调用无参数构造函数,并且在内部它将退回到第三方库想要用作默认值的任何内容。在你的情况下它将是
缓存服务() : 这个(MemoryCache.Default)
其他答案中提到的另一个选项是自己注册并传递构造函数参数。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor(MemoryCache.Default));
这也可行,但在这里您要负责提供缓存提供程序。在我看来,我宁愿让第三方库处理它自己的默认值,而不是让我作为消费者来承担这个责任。
请看How does Unity.Resolve know which constructor to use?
关于 Niject 的其他信息很少
https://github.com/ninject/ninject/wiki/Injection-Patterns
If no constructors have an [Inject] attribute, Ninject will select the
one with the most parameters that Ninject understands how to resolve.
对于 LazyCache 版本 2.1.2(甚至更早),现有解决方案不再有效(没有接收 MemoryCache 的构造函数),但它的工作原理很简单:
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor());
这适用于 .NET Framework 4.6.1、Unity Abstractions 3.1.0。
我有一个 ASP .Net Web API 控制器,我想使用 2 个参数。第一个是 EF 上下文,第二个是缓存接口。如果我只有 EF 上下文,则会调用构造函数,但是当我添加缓存接口时,我会收到错误消息:
An error occurred when trying to create a controller of type 'MyV1Controller'. Make sure that the controller has a parameterless public constructor.
private MyEntities dbContext;
private IAppCache cache;
public MyV1Controller(MyEntities ctx, IAppCache _cache)
{
dbContext = ctx;
cache = _cache;
}
我的UnityConfig.cs
public static void RegisterTypes(IUnityContainer container)
{
// TODO: Register your types here
container.RegisterType<MyEntities, MyEntities>();
container.RegisterType<IAppCache, CachingService>();
}
我希望 Entity 现在知道这两种类型,当对 MyV1Controller 函数发出请求时,它应该能够实例化一个实例,因为该构造函数采用它知道的类型,但事实并非如此。知道为什么吗?
[编辑]
请注意,我创建了自己的 class (IConfig
) 并将其注册并将其添加到构造函数中并且它起作用了,但是每当我尝试将 IAppCache
添加到我的构造函数并发出请求时API 我收到错误消息,告诉我它无法构建我的控制器 class。我看到的唯一区别是 IAppCache
不在我的项目命名空间中,因为它是第 3 方 class,但根据我的理解,这无关紧要。
这是 CachingService
的构造函数public CachingService() : this(MemoryCache.Default) { }
public CachingService(ObjectCache cache) {
if (cache == null) throw new ArgumentNullException(nameof(cache));
ObjectCache = cache;
DefaultCacheDuration = 60*20;
}
检查 IAppCache
实现 CachingService
以确保 class 在初始化时没有抛出任何异常。该无参数异常是在尝试创建控制器时发生错误时的默认消息。这不是一个非常有用的异常,因为它不能准确指出发生的真正错误是什么。
你提到它是第 3 方 interface/class。它可能正在请求容器不知道的依赖项。
引用 Unity Framework IoC with default constructor
Unity 使用最多的参数调用构造函数,在本例中是...
public CachingService(ObjectCache cache) { ... }
由于容器对ObjectCache
一无所知,它将传入null
,根据构造函数中的代码将抛出异常。
更新:
从评论中添加这个,因为它可以证明对其他人有用。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor(MemoryCache.Default));
参考此处Register Constructors and Parameters了解更多详情。
大多数 DI 容器在尝试解析类型时总是寻找具有最大参数数量的构造函数。这就是为什么默认调用 CachingService(ObjectCache cache) 构造函数的原因。由于ObjectCache实例没有注册到Unity,所以解析失败。一旦强制类型注册调用特定构造函数,一切正常。
因此,如果您注册 IAppCache 并强制它调用 CachingService() - 无参数构造函数,它将按预期工作。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor());
以这种方式注册,将强制调用无参数构造函数,并且在内部它将退回到第三方库想要用作默认值的任何内容。在你的情况下它将是
缓存服务() : 这个(MemoryCache.Default)
其他答案中提到的另一个选项是自己注册并传递构造函数参数。
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor(MemoryCache.Default));
这也可行,但在这里您要负责提供缓存提供程序。在我看来,我宁愿让第三方库处理它自己的默认值,而不是让我作为消费者来承担这个责任。
请看How does Unity.Resolve know which constructor to use?
关于 Niject 的其他信息很少 https://github.com/ninject/ninject/wiki/Injection-Patterns
If no constructors have an [Inject] attribute, Ninject will select the one with the most parameters that Ninject understands how to resolve.
对于 LazyCache 版本 2.1.2(甚至更早),现有解决方案不再有效(没有接收 MemoryCache 的构造函数),但它的工作原理很简单:
container.RegisterType<IAppCache, CachingService>(new InjectionConstructor());
这适用于 .NET Framework 4.6.1、Unity Abstractions 3.1.0。