4

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

一种选择我是一个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>(); 
+1

再次,“公共MyViewModel(ILogger记录器)”有什么问题? –

+0

我绝对可以这样做,我只是想避免必须将我的本地ILogger属性设置为所有派生的ViewModel的构造函数注入参数,但似乎没有办法解决它。 –

+1

我认为这是一个优势,因为依赖关系的意图是明确的。另一方面,在建设者通过容器闻起来很糟糕;) –

回答

7

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

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

您的问题是由于您在构造函数中做得太多而引起的。从依赖注入的角度来看,构造函数只能接受它的依赖关系(检查它们是否为空),并将它们存储在私有字段中。除此之外,做任何事都是反模式。你的构造函数中不应该有任何逻辑。

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

当你遵循这个原则时,不会有问题,因为一旦你运行任何业务逻辑,你的类将被完全实例化。由于构造函数只能设置私有字段,因此不会出现任何错误,因此不会像原来那样调用Logger.Error("PRINT AN ERROR");

+0

史蒂文。就一个问题。不解决服务定位器模式?如果是,那么如何在不调用第一级的Resolve的情况下解决所有的依赖关系? –

+1

@HasanFahim,你将永远需要你的应用程序中至少有一个地方是你需要解析的地方。这可以。一般来说,只要它们位于组合根中,就可以调用Resolve。在组合根之外调用解析(在应用程序代码中)被认为是服务定位器,因此是反模式。 – Steven

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注入。

相关问题