5

好的,我在基类中定义了一个依赖属性,我试图在其派生类的构造函数中使用它,但这不起作用,该属性显示为 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>();
4

2 回答 2

7

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

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

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

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

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

于 2012-06-20T20:55:11.150 回答
2

1)您可以在每个视图模型中使用不同的记录器实例,只需删除ContainerControlledLifetimeManager.

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

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

使用构造函数注入,您的视图模型将被注入一个全新的MyOtherLogger.

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

于 2012-06-20T19:49:57.140 回答