我尝试使用自定义参数" server"注册通信服务。但我希望自动解决ILogger依赖关系,而不是设置此依赖关系两次。
最好的办法是什么?
SimpleInjector注册
var diContainer = new Container();
diContainer.Register<ILogger, DefaultLogger>();
//Good
diContainer.Register<ICommunicationService>(
() => new CommunicationService("server1"),
Lifestyle.Singleton);
//Bad
diContainer.Register<ICommunicationService>(
() => new CommunicationService(new DefaultLogger(), "server1"),
Lifestyle.Singleton);
CommunicationService Class
public class CommunicationService : ICommunicationService
{
public CommunicationService(ILogger logger, string server)
{
}
}
更新2017-11-27
@Steven我想运行两个CommunicationService
的不同配置实例。在我的示例server1和server2中。
var container = new Container();
container.Register<ILogger, DefaultLogger>();
container.RegisterSingleton(new CommunicationServiceConfig { Server = "server1" });
container.RegisterSingleton(new CommunicationServiceConfig { Server = "server2" });
diContainer.Register<ICommunicationService, CommunicationService>(Lifestyle.Singleton);
diContainer.Register<ICommunicationService, CommunicationService>(Lifestyle.Singleton);
答案 0 :(得分:4)
原始类型的注入始终是DI容器的一个问题,因为string
int
和bool
等基本类型会导致歧义。
因此,最简单的解决方案是将此string
配置值包装到其自己的配置类中,例如:
public class CommunicationServiceConfig
{
public string Server { get; set; }
}
让CommunicationService
依靠CommunicationServiceConfig
而不是string
:
public class CommunicationService : ICommunicationService
{
public CommunicationService(ILogger logger, CommunicationServiceConfig config)
{
}
}
通过此更改,组合根变为:
var container = new Container();
container.Register<ILogger, DefaultLogger>();
container.RegisterSingleton(new CommunicationServiceConfig { Server = "server1" });
diContainer.Register<ICommunicationService, CommunicationService>(Lifestyle.Singleton);
答案 1 :(得分:1)
不理想,但似乎你可以捕获容器本身来解决已经注册的依赖关系,在实际的自举阶段本身,然后可以传递给工厂函数注册,即:
diContainer.Register<ICommunicationService>(
() => new CommunicationService(
diContainer.GetInstance<ILogger>(), "server1"), Lifestyle.Singleton);
因此允许硬编码值的混合,例如,对于Config,连接字符串等,以及其他已解析的依赖项,尽管如果构造函数签名发生更改,这将导致很多维护工作。
有一点需要注意的是,SimpleInjector在第一个分辨率完成后会冻结注册,因此,例如,以下内容是不可能的:
var sharedLogger = diContainer.GetInstance<ILogger>();
diContainer.Register<ICommunicationService>(
() => new CommunicationService(sharedLogger, "server1"), Lifestyle.Singleton);
// Other registrations with `sharedLogger`
System.InvalidOperationException:第一次调用GetInstance后无法更改容器
即。你需要确保你的工厂方法保持懒惰。