使用Unity的构造函数中使用的属性依赖注入

时间:2012-06-20 18:29:35

标签: c# dependency-injection inversion-of-control unity-container containers

好的,我有一个在基类中定义的依赖属性,我试图在其派生类的构造函数中使用它,但是这不起作用,该属性显示为null。 Unity使用container.Resolve()解析实例后解析依赖属性;

我有一个替代方法是将IUnityContainer参数添加到我的MyViewModel类构造函数中,并将ILogger属性设置为我自己的类似:

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

编辑: @Wiktor_Zychla的另一个建议是将构造函数注入的参数传递为:

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

这似乎工作正常,但我必须为我所有派生的ViewModels做到这一点..

但是我没有在我的基类中使用带注释的ILogger依赖项。  请参阅下面的课程示例。问题是:我有哪些替代方案,或者我做错了什么?

谢谢!

我有一个像这样的ViewModel基类:

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

然后我有一个类得出:

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

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

在我的应用程序入口点,我将我的ILogger注册为单例和我的MyViewModel类:

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

2 个答案:

答案 0 :(得分:7)

  

Unity解析依赖属性后解析实例   container.Resolve();

如果你考虑一下这很明显。只是尝试手动执行此操作。你不会成功的。为了能够注入一个属性,必须有一个实例,并且有一个实例,意味着已经调用了构造函数。

您的问题是由于您在构造函数中执行的操作过多导致的。从依赖注入的角度来看,构造函数应该只接受它的依赖项(检查它们不是null),并将它们存储在私有字段中。做更多的事情是一种反模式。你的构造函数中不应该有任何逻辑。

构造函数中的逻辑使得创建对象图不可靠,而构建对象图应该快速可靠。

当你遵循这个原则时,就不会有问题,因为一旦你运行任何业务逻辑,你的类就会被完全实例化。由于构造函数除了设置私有字段之外什么都不做,因此没有任何问题可以解决,并且没有任何理由像你一样调用Logger.Error("PRINT AN ERROR");

答案 1 :(得分:2)

1)您只需删除ContainerControlledLifetimeManager即可在每个视图模型中使用记录器的其他实例。

2)您可以在注册时指定每个视图模型的不同Type记录器。

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

使用构造函数注入,您的viewmodel将注入一个全新的MyOtherLogger实例。

由于属性注入应保留为“很好有”值,并且您的类显然依赖于记录器的存在,我强烈建议使用ctor注入。