Property Dependency Injection used in Constructor using Unity

落爺英雄遲暮 提交于 2019-12-07 06:33:23

问题


Ok, I have a dependent property defined in a base class and I'm trying to use it inside of the constructor of its derived class but that does not work, the property appears as null. Unity resolves the dependent property AFTER resolving an instance with container.Resolve();

One alternative I have is to add a IUnityContainer parameter to my MyViewModel class constructor and set the ILogger property my self with something like:

public MyViewModel(IUnityContainer container)
{
  Logger = container.Resolve<ILogger>();
}

EDIT: Another suggestion by @Wiktor_Zychla is to pass a constructor-injected parameter as:

public MyViewModel(ILogger _logger)
{
    Logger = _logger;
}

This seems to work fine, but I would have to do that for all my derived ViewModels..

But then I'm not using the annotated ILogger dependency in my base class. See my class samples below. The question is: Which alternatives do I have, or what am I doing wrong?

Thanks!

I have a ViewModel base class like this:

public abstract class ViewModelBase
{
    [Dependency]
    public ILogger Logger { get; set; }
....
}

Then I have a class deriving that:

public class MyViewModel : ViewModelBase
{
    public MyViewModel()
    {
         //I want to use my dependent property in constructor, but doesn't 

         Logger.Error("PRINT AN ERROR");
    }
}

And in my application entry point I am registering my ILogger as a singleton and my MyViewModel class:

container.RegisterType<ILogger, MyAppLogger>(new ContainerControlledLifetimeManager());
container.RegisterType<MyViewModel>();

回答1:


Unity resolves the dependent property AFTER resolving an instance with container.Resolve();

Which is quite obvious, if you think about it. Just try to do this manually. You won't succeed. To be able to inject a property, there must be an instance, and having an instance, means the constructor has been called.

Your problem is caused because you are doing too much in your constructor. From a dependency injection perspective, a constructor should do nothing more than accept its dependencies (check that they are not null), and store them in private fields. Doing anything more than this is an anti-pattern. You shouldn't have any logic in your constructor.

Having logic in constructors makes creating the object graph unreliable, while constructing object graphs should be fast and reliable.

When you follow this principle, there will not be a problem, since once you run any business logic, your class will be completely instantiated. Since the constructor should do nothing more than set private fields, nothing can go wrong and there can't be any reason to call Logger.Error("PRINT AN ERROR"); as you are doing.




回答2:


1) You can use a different instance of your logger in every viewmodel by simply dropping the ContainerControlledLifetimeManager.

2) You can register a different Type of logger for every viewmodel by specifying it at registration time.

container.RegisterType<ILogger, MyAppLogger>();
container.RegisterType<ILogger, MyOtherLogger>("uniqueNameOfAnILoggerRegistration);
container.RegisterType<MyViewModel>(new InjectionConstructor(
    new ResolvedParameter(typeof(ILogger), "uniqueNameOfAnILoggerRegistration")));

Using constructor injection your viewmodel will be injected with a brand new instance of MyOtherLogger.

As property injection should be reserved for "nice to have" values and your classes obviously rely on the existence of a logger I would strongly recommend to use ctor injection.



来源:https://stackoverflow.com/questions/11125883/property-dependency-injection-used-in-constructor-using-unity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!