Shi*_*mmy 6 c# dependency-injection prism ioc-container unity-container
我有一个类在其构造函数中有一些原始类型参数,如字符串等.
我应该如何使用统一容器注册类型?
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;
}
}
Run Code Online (Sandbox Code Playgroud)
更新:
Remeber的IRegionManager和IEventAggregator已知类型的棱镜UnityBootstrapper这是在我的情况下,容器包装.我必须重新注册吗?我想保持类型注册尽可能简单.
这会被视为坏习惯吗?有更好的选择吗?
Ste*_*ven 15
尝试防止在构造函数中具有原始或难以解析类型的类设计.正如你已经从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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以让你LoginManager依赖LoginManagerConfiguration:
public LoginManager(IRegionManager regionManager,
IEventAggregator eventAggregator,
LoginManagerConfiguration configuration)
{
...
}
Run Code Online (Sandbox Code Playgroud)
该LoginManagerConfiguration可以简单地注册这样的:
container.RegisterInstance<LoginManagerConfiguration>(
new LoginManagerConfiguration(
login: new Uri("Login"),
target: new Uri("Target"),
mainRegionName: ConfigurationManager.AppSettings["MainRegion"]));
Run Code Online (Sandbox Code Playgroud)
指定应用程序范围的配置对象而不是此类型特定的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"))
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
将此类定义在应用程序的组合根附近.该类成为DI配置的实现细节.现在,您的类型注册将非常简单:
container.RegisterType<ILoginManager, DILoginManager>();
Run Code Online (Sandbox Code Playgroud)
虽然调用了延迟加载配置值,但是要非常小心ConfigurationManager.AppSettings["MainRegion"].这很容易导致应用程序启动期间未捕获配置错误的情况,这确实是首选.
选项3:使用工厂代表
我想提出的最后一个选项是工厂.这看起来很像Traveses的答案,但更类型安全:
var mainRegion = ConfigurationManager.AppSettings["MainRegion"];
container.Register<ILoginManager>(new InjectionFactory(c =>
{
return new LoginManager(
c.Resolve<IRegionManager>(),
c.Resolve<IEventAggregator>(),
ConfigurationManager.AppSettings["MainRegion"],
new Uri("Login"),
new Uri("Target"));
}));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3276 次 |
| 最近记录: |