2016-11-21 73 views
6

我有一个ASP .Net Web API控制器,我想要2个参数。第一个是EF上下文,第二个是缓存界面。如果我只是有EF上下文中的构造函数将被调用,但是当我添加了缓存界面我得到的错误:注入到带有2个参数的构造函数不起作用

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>(); 
} 

我预计实体现在知道这两种类型的请求时,MyV1Controller函数应该能够实例化一个实例,因为该构造函数采用它知道的类型,但事实并非如此。任何想法为什么?

[编辑] 请注意,我创建了自己的类(IConfig)和注册,并将其添加到构造和它的工作,但每当我试图将IAppCache添加到我的构造函数,并向API我的请求得到错误告诉我它不能构建我的控制器类。我看到的唯一区别是IAppCache不在我的项目命名空间中,因为它是第三方类,但根据我的理解,这应该不重要。

这里是CachingService

建设者
public CachingService() : this(MemoryCache.Default) { } 

public CachingService(ObjectCache cache) { 
    if (cache == null) throw new ArgumentNullException(nameof(cache)); 
    ObjectCache = cache; 
    DefaultCacheDuration = 60*20; 
} 
+0

是类注册意味着是一个单身?同时检查'IAppCache'实现'CachingService'以确保该类在初始化时不会抛出任何异常。该无参数异常是在尝试创建控制器时发生错误时的默认消息。 – Nkosi

+0

什么是CachingService的依赖关系您提到它是第三方接口/类。它可能会请求容器不知道的依赖项。 – Nkosi

+0

它使用MemoryCache.Default:https://github.com/alastairtree/LazyCache/blob/master/LazyCache/CachingService.cs – user441521

回答

9

检查IAppCache实施CachingService,以确保当初始化类不抛出任何异常。该无参数异常是在尝试创建控制器时发生错误时的默认消息。这不是一个非常有用的例外,因为它不能准确指出发生的真实错误。

你提到它是第三方接口/类。它可能会请求容器不知道的依赖项。

引用Unity Framework IoC with default constructor

统一呼吁与在这种情况下是最参数的构造......

public CachingService(ObjectCache cache) { ... } 

由于集装箱一无所知ObjectCache将在null通过其根据构造函数中的代码将抛出异常。

更新:

添加此评论,因为它可以证明对他人有用。

container.RegisterType<IAppCache, CachingService>(new InjectionConstructor(MemoryCache.Default)); 

这里引用Register Constructors and Parameters了解更多详情。

+0

是实施:公共CachingService():这个(MemoryCache.Default) {} 公共CachingService(ObjectCache缓存) { 如果(缓存== NULL) 抛出新ArgumentNullException(nameof(缓存)); ObjectCache = cache; DefaultCacheDuration = 60 * 20; } – user441521

+0

那么我的猜测是'cache == null'是'true'。 – Nkosi

+0

如果我在UnityConfig中创建一个CachingService()的实例:RegisterTypes(),它不是null,所以当我的控制器在应用程序生命中稍后的时间点创建时,看不到为什么它是null。无论如何,当它为控制器ctor创建对象的这些创作以获得更好的外观时,还可以接入Unity吗? – user441521

3

尝试解析类型时,大多数DI容器总是查找具有最大参数数的构造函数。这就是为什么默认情况下调用CachingService(ObjectCache缓存)构造函数的原因。由于ObjectCache实例未在Unity中注册,因此解析失败。一旦你强制类型注册来调用特定的构造函数,一切正常。

因此,如果您注册IAppCache并强制它调用CachingService() - 参数较少的构造函数,它将按预期工作。

container.RegisterType<IAppCache, CachingService>(new InjectionConstructor()); 

注册这种方式,将迫使参数调用的构造函数,并在内部将依傍任何第三部分图书馆要为默认使用。你的情况,这将是

CachingService():这个(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.

相关问题