将 属性 注入 Prism 中的单例服务(Unity、MVVM)
Injecting a property into a singleton service in Prism (Unity, MVVM)
作为参考,我有一个服务想在统一容器中注册为单例。我希望此服务通过 属性 或构造函数注入以某种方式将 IEventAggerator 注入到服务中。
public class BeckhoffService: IProgrammableLogicController
{ ...}
我要么想要这个:
[Dependency]
public IEventAggregator eventAggregator{get;set;}
或者在构造函数中:
BeckhoffService(IEventAggregator eventAggregator)
当我在 unity 容器中将此服务注册为单例时,我的问题就来了。
在我的初始化模块中,这些是我尝试过的选项:
IProgrammableLogicController controllerSingleton = new BeckhoffService();
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
以上正确注册为单例,但 "controllerSingleton" 中的依赖项未得到解析。
_container.RegisterInstance<IProgrammableLogicController>(new BeckhoffService());
以上解决了 "new BeckhoffService()" 中的依赖关系,但容器在解决时没有 return 单例实例。
我能够通过手动将 IEventAggregator 传递到 Beckhoff 服务来实现它,而无需将 Unity 容器直接注入到服务中,但这看起来有点丑陋:
IProgrammableLogicController controllerSingleton = new BeckhoffService(_container.Resolve<IEventAggregator>());
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
是否有更好或更喜欢的方式来完成我想要的?谢谢!
哪些依赖项?
IProgrammableLogicController controllerSingleton = new BeckhoffService();
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
在您的第一个示例中,您自己初始化 BeckhoffService()
并使用无参数构造函数,因此您当然不会注入任何东西。
第二个例子也一样。您自己初始化对象,而不是通过 IoC 容器。
您要么必须自己初始化 class 并自己传递依赖项,要么必须将类型注册到 IoC 容器并让容器解析它!
例如:
container.Register<IProgrammableLogicController, BeckhoffService>(new ContainerControlledLifetimeManager());
然后用
解决
IProgrammableLogicController controller = container.Resolve<IProgrammableLogicController>();
ContainerControlledLifetimeManager
生命周期管理器是 Unity 等同于单例的(技术上非常接近它),至于容器的生命周期,总是相同的实例将被 returned。由于您的组合根靠近 App 启动(至少它应该,否则您可能会遇到问题),主 IoC 容器通常只要 App 存在就存在。
Unity 还允许创建子容器,如果您需要针对特定操作链的单例,您将创建一个子容器,并且在此操作中,IoC 将 return 始终是同一实例。操作完成后,您将处理容器,下一个操作链将在该操作期间再次实例化单例等。
通常,您使用 RegisterInstance
来表示不可解析的类型(即第 3 方库)或需要配置的类型(例如,如果您想要配置记录器服务的实例)。然后你自己实例化它,配置它并将它作为实例注册到 IoC。这对对象图设置期间的配置有效。
如果你有 classes,它只需要依赖而不需要 configuration/initialization,你应该使用 RegisterType
方法。
如果你有 classes,它在 运行 时需要某个参数或依赖项,你需要通过一个 "Abstract Factory" 和 create/resolve 实现实例请求参数的方法。这避免了您忘记调用对象配置方法。
不好:
// ctor
public MyClass(IMyDependency dep) {
dep.RuntimeDependencyValue = 42; // Bad if RuntimeDependencyValue is required for the class to work
// or
dep.Initialize(42);
}
更好:
public MyClass(IMyDependencyFactory depFactory) {
IMyDependency dep = depFactory.Create(42);
}
第二个更好,因为抽象resolve/creation加上工厂后面的初始化class。现在你不能错过用重要参数初始化它,因为创建它的唯一方法是通过强制你传递所需参数的方法。
作为参考,我有一个服务想在统一容器中注册为单例。我希望此服务通过 属性 或构造函数注入以某种方式将 IEventAggerator 注入到服务中。
public class BeckhoffService: IProgrammableLogicController
{ ...}
我要么想要这个:
[Dependency]
public IEventAggregator eventAggregator{get;set;}
或者在构造函数中:
BeckhoffService(IEventAggregator eventAggregator)
当我在 unity 容器中将此服务注册为单例时,我的问题就来了。
在我的初始化模块中,这些是我尝试过的选项:
IProgrammableLogicController controllerSingleton = new BeckhoffService();
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
以上正确注册为单例,但 "controllerSingleton" 中的依赖项未得到解析。
_container.RegisterInstance<IProgrammableLogicController>(new BeckhoffService());
以上解决了 "new BeckhoffService()" 中的依赖关系,但容器在解决时没有 return 单例实例。
我能够通过手动将 IEventAggregator 传递到 Beckhoff 服务来实现它,而无需将 Unity 容器直接注入到服务中,但这看起来有点丑陋:
IProgrammableLogicController controllerSingleton = new BeckhoffService(_container.Resolve<IEventAggregator>());
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
是否有更好或更喜欢的方式来完成我想要的?谢谢!
哪些依赖项?
IProgrammableLogicController controllerSingleton = new BeckhoffService();
_container.RegisterInstance<IProgrammableLogicController>(controllerSingleton);
在您的第一个示例中,您自己初始化 BeckhoffService()
并使用无参数构造函数,因此您当然不会注入任何东西。
第二个例子也一样。您自己初始化对象,而不是通过 IoC 容器。
您要么必须自己初始化 class 并自己传递依赖项,要么必须将类型注册到 IoC 容器并让容器解析它!
例如:
container.Register<IProgrammableLogicController, BeckhoffService>(new ContainerControlledLifetimeManager());
然后用
解决IProgrammableLogicController controller = container.Resolve<IProgrammableLogicController>();
ContainerControlledLifetimeManager
生命周期管理器是 Unity 等同于单例的(技术上非常接近它),至于容器的生命周期,总是相同的实例将被 returned。由于您的组合根靠近 App 启动(至少它应该,否则您可能会遇到问题),主 IoC 容器通常只要 App 存在就存在。
Unity 还允许创建子容器,如果您需要针对特定操作链的单例,您将创建一个子容器,并且在此操作中,IoC 将 return 始终是同一实例。操作完成后,您将处理容器,下一个操作链将在该操作期间再次实例化单例等。
通常,您使用 RegisterInstance
来表示不可解析的类型(即第 3 方库)或需要配置的类型(例如,如果您想要配置记录器服务的实例)。然后你自己实例化它,配置它并将它作为实例注册到 IoC。这对对象图设置期间的配置有效。
如果你有 classes,它只需要依赖而不需要 configuration/initialization,你应该使用 RegisterType
方法。
如果你有 classes,它在 运行 时需要某个参数或依赖项,你需要通过一个 "Abstract Factory" 和 create/resolve 实现实例请求参数的方法。这避免了您忘记调用对象配置方法。
不好:
// ctor
public MyClass(IMyDependency dep) {
dep.RuntimeDependencyValue = 42; // Bad if RuntimeDependencyValue is required for the class to work
// or
dep.Initialize(42);
}
更好:
public MyClass(IMyDependencyFactory depFactory) {
IMyDependency dep = depFactory.Create(42);
}
第二个更好,因为抽象resolve/creation加上工厂后面的初始化class。现在你不能错过用重要参数初始化它,因为创建它的唯一方法是通过强制你传递所需参数的方法。