Entering a constructor with 2 parameters does not work

I have an ASP.NET Web API controller that I want to take 2 parameters. The first is the EF context, and the second is the caching interface. If I just have an EF context, the constructor gets called, but when I add the caching interface, I get an error:

An error occurred while trying to create a controller of type 'MyV1Controller. Make sure the controller has an unsigned public constructor.

private MyEntities dbContext; private IAppCache cache; public MyV1Controller(MyEntities ctx, IAppCache _cache) { dbContext = ctx; cache = _cache; } 

My UnityConfig.cs

 public static void RegisterTypes(IUnityContainer container) { // TODO: Register your types here container.RegisterType<MyEntities, MyEntities>(); container.RegisterType<IAppCache, CachingService>(); } 

I would expect Entity to now know about all types, when a request is made for the MyV1Controller function, it should be able to instantiate an instance, since this constructor uses types that it knows about, but it is not. Any idea why?

[EDIT] Note that I created my own class ( IConfig ) and registered it and added to the constructor, and it worked, but whenever I try to add IAppCache to my constructor and make an API request, I get an error I can not build my controller class. The only difference that I see is that IAppCache not in the project namespace, because it is a third-party class, but it does not matter from what I understand.

Here are the constructors for the CachingService

 public CachingService() : this(MemoryCache.Default) { } public CachingService(ObjectCache cache) { if (cache == null) throw new ArgumentNullException(nameof(cache)); ObjectCache = cache; DefaultCacheDuration = 60*20; } 
+6
source share
2 answers

Check the implementation of IAppCache CachingService to make sure that the class does not throw any exceptions during initialization. this exception without parameters is the default message when an error occurs while trying to create controllers. This is not a very useful exception because it does not accurately indicate what happened with a true error.

You mentioned that this is a third-party interface / class. It can request a dependency that the container is not aware of.

Unity Framework IoC reference with default constructor

Unity calls the constructor with the largest parameter, which in this case ...

 public CachingService(ObjectCache cache) { ... } 

Since the container does not know anything about ObjectCache , it will pass in null , which according to the code in the constructor will throw an exception.

UPDATE:

Adding this from the comments as it may prove useful to others.

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

Link here Register constructors and parameters for more details.

+9
source

When trying to resolve a type, most DI containers always look for a constructor with the maximum number of parameters. For this reason, the CachingService constructor (ObjectCache cache) was called by default. Because the ObjectCache instance is not registered with Unity, permission is not enforced. After you force a type to call a specific constructor, everything works.

So, if you register IAppCache and force it to call CachingService (), the constructor with a lower value, it will work as expected.

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

By registering it this way, force the constructor to be called with fewer constructors and internally it will be discarded to what the third part library wants to use by default. In your case it will be

CachingService (): this is (MemoryCache.Default)

Another option that was mentioned in other answers is to register and pass the constructor parameter yourself.

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

This will also work, but here you take the responsibility of providing the cache provider. In my opinion, I would prefer a third-party library to handle its own defaults instead of me when the consumer took on this responsibility.

Please look. How does Unity.Resolve know which constructor to use?

And some more info for Niject https://github.com/ninject/ninject/wiki/Injection-Patterns

If none of the constructors has an [Inject] attribute, Ninject will select one with most of the parameters that Ninject understands how to allow.

+3
source

Source: https://habr.com/ru/post/1012540/


All Articles