使用primitive-arguments构造函数注册一个类型?

我有一个类在其构造函数中有一些原始类型参数,如字符串等。

我应该如何使用统一容器注册类型?

public LoginManager( IRegionManager regionManager, IEventAggregator eventAggregator, string mainRegionName, Uri login, Uri target) { this.regionManager = regionManager; this.eventAggregator = eventAggregator; this.mainRegionName = mainRegionName; this.login = login; this.target = target; } } 

更新
请记住, IRegionManagerIEventAggregator是Prism UnityBootstrapper的已知类型,在我的情况下是容器包装器。 我必须重新注册吗? 我想保持类型注册尽可能简单。

这会被视为坏习惯吗? 有更好的选择吗?

尝试防止在构造函数中具有原始或难以解析类型的类设计。 正如你已经从Tavares的回答中看到的那样,你的配置变得非常脆弱( 更新:Tavares似乎因为我不清楚的原因而删除了他的答案 )。 您失去了编译时支持,对该构造函数的每次更改都会使您更改DI配置。

有多种方法可以改变您的设计以防止这种情况发生。 哪一个适用于你取决于你,但这里有一些想法:

选项1:使用不可变配置DTO:

 private sealed class LoginManagerConfiguration { public Uri Login { get; private set; } public Uri Target { get; private set; } public string MainRegionName { get; private set; } public LoginManagerConfiguration(Uri login, Uri target, string mainRegionName) { this.Login = login; this.Target = target; this.MainRegionName = mainRegionName; } } 

现在您可以让您的LoginManager依赖于LoginManagerConfiguration

 public LoginManager(IRegionManager regionManager, IEventAggregator eventAggregator, LoginManagerConfiguration configuration) { ... } 

LoginManagerConfiguration可以像这样注册:

 container.RegisterInstance( new LoginManagerConfiguration( login: new Uri("Login"), target: new Uri("Target"), mainRegionName: ConfigurationManager.AppSettings["MainRegion"])); 

指定一个应用程序范围的配置对象而不是这个特定于类型的DTO可能很诱人,但这是一个陷阱。 这种应用程序范围的配置对象是Service Locator反模式的配置等价物。 不清楚类型需要什么配置值,并使类更难测试。

选项2:从该类派生

另一种选择是从该类派生,仅用于DI配置。 当您无法更改类签名时(即当它是第三方组件时),这尤其有用:

 private sealed class DILoginManager : LoginManager { DILoginManager(IRegionManager regionManager, IEventAggregator eventAggregator) : base(regionManager, eventAggregator, ConfigurationManager.AppSettings["MainRegion"], new Uri("Login"), new Uri("Target")) { ... } } 

将此类定义在应用程序的组合根附近。 该类成为DI配置的实现细节。 现在,您的类型注册非常简单:

 container.RegisterType(); 

尽管调用了延迟加载配置值,例如ConfigurationManager.AppSettings["MainRegion"] ,但要非常小心。 这很容易导致在应用程序启动期间未捕获配置错误的情况,这确实是更可取的。

选项3:使用工厂代表

我想提出的最后一个选项是工厂。 这看起来很像Traveses的答案,但更类型安全:

 var mainRegion = ConfigurationManager.AppSettings["MainRegion"]; container.Register(new InjectionFactory(c => { return new LoginManager( c.Resolve(), c.Resolve(), ConfigurationManager.AppSettings["MainRegion"], new Uri("Login"), new Uri("Target")); })); 

不,这不是一个坏习惯。 这是一个非常有效的场景。 自从我离开Unity以来已经过去了几年,但是从头顶开始,你必须明确地指向你想要的构造函数并枚举所有参数,对于原始的参数,我们需要new ResolvedParameter("your value")

另外我注意到你有一个Type参数。 对Unity要谨慎,因为它有……处理这些问题的非常令人惊讶的方式。 我在这里有一篇博文详细介绍。