5

我正在使用 ASP.NET MVC 4 应用程序。

主控制器的构造函数使用 2 个参数进行参数化(Iservice1 service1,Iservice2 service2) 并非所有代码路径都使用任何服务(service1,service2),仅在某些代码路径中我需要 service1 实例/对象或 service2 实例/对象。

我不想使用 container.Resolve< <Lazy<IService1>>();

从这个链接(http://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx)我了解到unity.mvc 4使用具有延迟加载支持的unity 3,但是如何在 ASP.NET MVC 4 中执行此操作。

4

2 回答 2

13

一般来说,实例构造函数应该做的只是正确的空检查并存储传入的引用。这使得对象图的构建快速而可靠。任何初始化都应推迟到稍后的时间,即第一次使用组件的时间。

在大多数情况下,这将防止需要延迟创建组件以提高性能,如果这仍然是一个问题,您可能需要考虑一个具有更好性能的容器。

对于那些需要延迟创建的空闲时间,不要Lazy<T>为此使用 a 。注入Lazy<T>是一种泄漏抽象,就像IDisposable放置在接口上一样。注入Lazy<T>泄漏,因为从理论上讲,每个依赖项都可能很慢或可能需要推迟。为了避免在引入较慢的服务实现时必须在整个应用程序中进行彻底的更改,我们最好将应用程序中的每个依赖项都放在Lazy<IDependency>前面,因为这样可以避免我们在以后进行更改。

但这当然是愚蠢和丑陋的。但是,即使应用程序足够小,可以承受如此彻底的改变,消费者为什么要知道或关心该服务需要延迟初始化的事实呢?这不是一个实现细节吗?为什么我们要把这种懒惰的行为加入到这个服务的契约中呢?这样做会使我们的代码和我们需要编写的测试更加复杂。这是不必要的意外复杂性

因此Lazy<IService1>,您应该简单地注入 aIService1并实现并注册实现惰性行为的代理,而不是注入 a 。这实际上很容易做到,如下所示:

public class LazyService1Proxy : IService1
{
    private Lazy<IService1> service;

    public LazyService1Proxy(Lazy<IService1> service) => this.service = service;

    void IService1.Method1() => this.service.Value.Method1();

    object IService1.Method2(string foo) => this.service.Value.Method2(foo);
}

这个代理可以注册如下:

container.Register<IService1>(new InjectionFactory(c => 
    new LazyService1Proxy(
        new Lazy<IService1>(
            () => c.Resolve<RealService1Impl>()))));
于 2014-02-12T10:04:59.440 回答
-2

由于我不知道如何在 DI 注册级别实现延迟加载,所以我经常使用这种方式来延迟加载服务。我会和你分享我的方法。

每个服务接口都将继承 IService 接口,该接口是所有服务接口的基础。

public interface IService
{
    // I just want to be sure I'm instantiating ONLY services types.
    // This is my base interface 
}

public interface IMyService : IService
{
    void DoSomeWork();
}

然后,每个服务都会实现自己的接口:

public class MyService : IMyService
{
    public void DoSomeWork()
    {
        // Some action performed.
    }
}

我的抽象 BaseController 类实现了这个逻辑

public abstract class BaseController : Controller
{
    public T LoadService<T>() where T : IService
    {
        return (T)System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(T));
    }
}

最后,在我继承 BaseController 的控制器中,我可以做到这一点:

public class TestController : BaseController
{
    // Only parameterless constructor exists created by the compiler.

    [HttpPost]
    public ActionResult PerformWork()
    {
        var testService = LoadService<IMyService>();
        testService.DoSomeWork();

        return View();
    }
}

我很想看到延迟加载服务的更好实现,或者了解如何使用 Unity 或 Ninject 在类型注册级别实现延迟加载。

于 2016-01-28T18:15:35.280 回答