我使用StructureMap v4.6.1.0,我有一个结构,在其中使用构造函数创建实例,并在该实例中插入该类的接口,并且该类通常在其服务中调用具有其参数的构造函数,使用
private readonly IFirstService _firstService;
private readonly ISecondService _secondService;
private readonly ILog _log;
public ProductController(IFirstService firstService, ISecondService secondService, ILog log)
{
_firstService = firstService;
_secondService = secondService;
_log = log;
}
[Route("Default")]
public ActionResult First()
{
var model = _firstService.DoIt();
return View("~/Views/First/index.cshtml", model);
}
[Route("Default")]
public ActionResult Second()
{
var model = _secondService.DoIt();
return View("~/Views/Second/index.cshtml", model);
}
此解决方案的主要问题是然后我调用Controller,然后使它成为2个实例(一个用于firstService,第二个用于secondService),但是我为特定的控制器页面方法调用此服务。
例如,在工厂,日志和存储库加载器的构造函数接口中进行服务调用,这意味着当我调用控制器构造函数时,我将从这两个服务中加载所有存储库-
当我使用Lazy时,我收到消息,然后未定义被调用的过程
我正在寻找最佳的体系结构解决方案,我尝试了一些Lazy并优化了代码,但是我一直遇到问题
编辑:
StructureMap容器注册
Scan(
scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
For<ILog>().Use(c => LogManager.GetLogger(GetType())).Singleton();
For<IFirstService>().Use<FirstService>().Singleton();
For<ISecondService>().Use<SecondService>().Singleton();
我的解决方案:
在类构造函数中,我使用StructureMap的接口
private readonly IContainer _container;
private readonly ILog _log;
public ProductController(IContainer container, ILog log)
{
_container = container;
_log = log;
}
在我使用的方法中
var model = _container.GetInstance<IFirstService>().DoIt();
我使用静态System.Web.HttpRuntime;的.NET库 ,并在存储库类的构造函数中调用的方法中使用以下代码
if (!(Cache[_cacheName] is IEnumerable<YourObject> result)) // Cache is empty
{
_log.Info("-- Loading from DB --");
lock (CacheLockObject)
{
result = Cache[_cacheName] as IEnumerable<YourObject>;
if (result == null)
{
result = LoadAll(); // load data from DB
Cache.Insert(_cacheName, result, null,
DateTime.Now.AddMinutes(10), TimeSpan.Zero);
}
return result;
}
}
_log.Info("-- Loading from Cache --");
return result;
谢谢
答案 0 :(得分:2)
当前依赖项注入的解决方案是使用服务定位器反模式。容器不应作为依赖项传递。这样做是服务定位器的明确指示。
您可以使用Lazy<T>
或Func<T>
来推迟初始化
例如,以下使用Func<T>
private readonly Func<IFirstService> _firstService;
private readonly Func<ISecondService> _secondService;
private readonly ILog _log;
public ProductController(Func<IFirstService> firstService, Func<ISecondService> secondService, ILog log) {
_firstService = firstService;
_secondService = secondService;
_log = log;
}
[Route("Default")]
public ActionResult First() {
IFirstService service = _firstService();//invoke delegate to get service
var model = service.DoIt();
return View("~/Views/First/index.cshtml", model);
}
[Route("Default")]
public ActionResult Second() {
ISecondService service = _secondService();
var model = service.DoIt();
return View("~/Views/Second/index.cshtml", model);
}
Func
充当工厂委托,仅在需要时才延迟依赖项的初始化/激活。
因此在上面的示例中,如果请求了First()
,则仅为该请求调用_firstService()
委托,而不是两个服务都被调用。
您可以使用Lazy<T>
private readonly Lazy<IFirstService> _firstService;
private readonly Lazy<ISecondService> _secondService;
private readonly ILog _log;
public ProductController(Lazy<IFirstService> firstService, Lazy<ISecondService> secondService, ILog log) {
_firstService = firstService;
_secondService = secondService;
_log = log;
}
[Route("Default")]
public ActionResult First() {
IFirstService service = _firstService.Value;//lazy load service
var model = service.DoIt();
return View("~/Views/First/index.cshtml", model);
}
[Route("Default")]
public ActionResult Second() {
ISecondService service = _secondService.Value;
var model = service.DoIt();
return View("~/Views/Second/index.cshtml", model);
}
StructureMap Documentation: Lazy Resolution
StructureMap具有一些内置功能,可以解决“懒惰”的已解决依赖关系,因此,您的应用程序服务可以代替让结构映射实现对{{ 1}}或
IExpensiveToBuildService
,仅当需要从最初创建父对象的任何Container中获取该昂贵的服务时,才可以使用它。