在Simple Injector中延迟创建实例

时间:2017-02-04 09:25:10

标签: c# .net dependency-injection inversion-of-control simple-injector

我在我的项目中使用Simple Injector来连接所有必需的依赖项,但我无法调用container.Verify,因为它之前为 http配置创建了一个Singleton实例实际的第一个请求

public interface IConfiguration { }
public class Configuration : IConfiguration
{
    public Configuration()
    {
        var httpContext = HttpContext.Current;
        var httpRequest = currentHttpContext.Request;
        var httpRequestUrl = currentHttpRequest.Url;

        this.UriScheme = currentHttpRequestUrl.Scheme;
        this.UriHost = currentHttpRequestUrl.Host;
        this.UriPort = currentHttpRequestUrl.Port;
    }

    public string UriScheme { get; private set; }
    public string UriHost { get; private set; }
    public int UriPort { get; private set; }
}

public class ServiceA
{
    private readonly _configuration;

    public ServiceA(IConfiguration configuration) 
    {
        _configuration = configuration 
    }
}

public class ServiceB
{
    private readonly _configuration;

    public ServiceB(IConfiguration configuration) 
    {
        _configuration = configuration
    }
}

这是该场景的基本示例。我目前拥有 60 服务,具体取决于IConfiguration

创建配置类时需要进行所有配置

这是我在容器中注册实例的方法

var container = new Container();

//container.RegisterSingleton<IConfiguration, Configuration>();

var lazy = new Lazy<InstanceProducer>(() =>
    Lifestyle.Singleton.CreateProducer(typeof(IConfiguration), typeof(Configuration), container));

container.Register<ServiceA>();
container.Register<ServiceB>();

container.Verify(); // Creates configuration class --> not desired

根据{{3}}

  

所以这里的技巧是在验证过程之后触发创建新的InstanceProducer实例

我知道解决方法是使用Lazy<T>InstanceCreator,但我无法正确连接我的代码

修改

Configuration类没有依赖项。 Configuration的问题是它在Singleton方法调用中被创建为container.Verify,那时currentHttpRequest.Url不是实际网址

我想我可以将配置从构造函数移动到方法(例如GetConfiguration)并进行一些重构但我很好奇是否可以在问题的情况下实现延迟实例创建

1 个答案:

答案 0 :(得分:2)

如Mark Seemann在this文章中所解释的那样,注射构造器应该简单可靠。他们不应做任何可能导致其失败的事情。在构造函数中调用HttpContext.Current会使其不可靠,因为这可能会失败。

除此之外,您的Configuration组件现在依赖于运行时数据(HttpContext.Current 运行时数据),这是一个罪,如this article中所述

然而,解决问题的方法非常简单明了。只需将您的Configuration课程更改为以下内容:

public sealed class Configuration : IConfiguration
{
    public string UriScheme => this.Url.Scheme;
    public string UriHost => this.Url.Host;
    public int UriPort => this.Url.Port;
    private Uri Url => HttpContext.Current.Request.Url;
}

这不仅简化了事情,还消除了您所应用的导致您麻烦的反模式。你的构造函数现在非常简单,它甚至不再存在(不能比这更简单)。现在,在构造对象图之后,仅请求运行时数据(来自HttpContext.Current)。这允许容器可靠地验证其配置。