C# 结构图&;通过带接口的构造函数进行延迟初始化

C# 结构图&;通过带接口的构造函数进行延迟初始化,c#,asp.net-mvc,architecture,lazy-loading,structuremap,C#,Asp.net Mvc,Architecture,Lazy Loading,Structuremap,我使用StructureMap v4.6.1.0,我有一个结构,在这个结构中,我使用构造函数创建一个实例,并在其中插入该类的接口,该类通常调用构造函数,该构造函数的参数位于它们使用的服务中 private readonly IFirstService _firstService; private readonly ISecondService _secondService; private readonly ILog _log; public ProductController(IF

我使用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);
 }
这个解决方案的主要问题是,然后我调用控制器,然后它生成2个实例(一个用于firstService,第二个用于secondService),但这个服务我调用特定的控制器页面方法

例如,在工厂、日志和存储库加载器的构造函数接口中调用服务,这意味着当我调用控制器构造函数时,我将从这两个服务中加载所有存储库-

  • 我可以使用C#.NET Lazy(T)或Func吗
  • 我可以在所选页面的方法中将界面用作参数吗
  • 我可以对存储库中的只读数据使用缓存吗
  • 另一个解决方案
当我使用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();
在我使用的方法中

var model = _container.GetInstance<IFirstService>().DoIt();
var模型=_container.GetInstance().DoIt();
  • 我可以对存储库中的只读数据使用缓存吗
我使用.NET lib使用静态System.Web.HttpRuntime;并在repository类的构造函数中调用的方法中使用下面的代码

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;
如果(!(Cache[\u cacheName]是IEnumerable result))//缓存为空
{
_log.Info(“--Loading from DB--”);
锁(CacheLockObject)
{
结果=缓存[_cacheName]为IEnumerable;
如果(结果==null)
{
result=LoadAll();//从数据库加载数据
Insert(_cacheName,result,null,
DateTime.Now.AddMinutes(10),TimeSpan.Zero);
}
返回结果;
}
}
_log.Info(“--从缓存加载--”;
返回结果;

谢谢

依赖项注入的当前解决方案是使用服务定位器反模式。容器不应作为依赖项传递。这样做是服务定位器的明确指示

您可以使用
Lazy
Func

例如,以下使用
Func

StructureMap具有一些用于“惰性”解析依赖项的内置功能,因此,您的应用程序服务不必直接依赖于
IEExpensiveToBuildService
,而可能不需要依赖它,相反,您可以让StructureMap实现对
Lazy
Func
的依赖,只有当需要从最初创建父对象的容器中检索昂贵的服务时,才可以使用该服务


从你的问题来看,你不太清楚你想要实现什么。你能在注册所有依赖项的地方发布结构映射类吗。另外,如果您想在请求中共享相同的存储库实例,请查看上下文范围的生命周期,如此答案[here]()您好,感谢您的回答,我已经找到了我一直在寻找的解决方案,请查看我的更新当我使用Lazy或Func时,当我调用服务方法时,此错误:
Severity code Description项目文件行抑制状态错误CS1061'Func'不包含'DoIt'的定义,并且找不到接受'Func'类型的第一个参数的可访问扩展方法'DoIt'(是否缺少using指令或程序集引用?)
@JanSršeň您必须调用该函数。请看我是如何在操作“\u firstService()”中进行调用的。注意括号。然后你可以调用激活对象的成员,也可以查看文档中的示例。@JanSršeň我重写了它,让你更好地理解如何使用它们现在它可以工作了,我只忽略了括号,我重写了它并检查了功能,Lazy和Func之间有什么区别吗?或者建议使用哪一种?@JanSršeňFunc只是一个委托,而Lazy是一个使用Func委托的类,该委托在调用
Lazy.Value
属性时被调用。Func是框架最初的工作方式。后来添加了Lazy。这两种方法都有效,只是你喜欢用哪一种方法的问题<代码>惰性更容易使用,更直观。
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;
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);
}
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);
}