延迟在 Simple Injector 中创建实例
Delay creation of instance in 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
创建配置 class 时需要进行所有配置
这就是我在容器中注册实例所做的工作
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
根据
So the trick here is to trigger the creation of new InstanceProducer
instances after the verification process
我知道解决方法是使用 Lazy<T>
和 InstanceCreator
但我无法正确完成挂钩我的代码
编辑
Configuration
class 没有依赖关系。 Configuration
的问题是它在 container.Verify
方法调用时被创建为 Singleton
,而那时 currentHttpRequest.Url
不是实际的 url
我想我可以将配置从构造函数移动到一个方法(例如GetConfiguration
)并进行一些重构,但我很好奇是否可以在问题的场景下实现延迟实例创建
正如 Mark Seemann 在 this 文章中所解释的那样,注入构造函数应该简单可靠。他们不应该做任何可能导致它失败的事情。在构造函数中调用 HttpContext.Current
会使其变得不可靠,因为这可能会失败。
除此之外,您的 Configuration
组件现在依赖于运行时数据(HttpContext.Current
是 运行时数据),这是一个错误,如this article.
然而,您的问题的解决方案非常简单明了。只需将 Configuration
class 更改为以下内容:
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;
}
这不仅简化了事情,还删除了您正在应用的给您带来麻烦的 anti-patterns。您的构造函数现在非常简单,甚至不再存在(没有比这更简单的了)。现在仅在构建对象图后才请求运行时数据(来自 HttpContext.Current
)。这允许容器可靠地验证其配置。
我在我的项目中使用 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
创建配置 class 时需要进行所有配置
这就是我在容器中注册实例所做的工作
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
根据
So the trick here is to trigger the creation of new
InstanceProducer
instances after the verification process
我知道解决方法是使用 Lazy<T>
和 InstanceCreator
但我无法正确完成挂钩我的代码
编辑
Configuration
class 没有依赖关系。 Configuration
的问题是它在 container.Verify
方法调用时被创建为 Singleton
,而那时 currentHttpRequest.Url
不是实际的 url
我想我可以将配置从构造函数移动到一个方法(例如GetConfiguration
)并进行一些重构,但我很好奇是否可以在问题的场景下实现延迟实例创建
正如 Mark Seemann 在 this 文章中所解释的那样,注入构造函数应该简单可靠。他们不应该做任何可能导致它失败的事情。在构造函数中调用 HttpContext.Current
会使其变得不可靠,因为这可能会失败。
除此之外,您的 Configuration
组件现在依赖于运行时数据(HttpContext.Current
是 运行时数据),这是一个错误,如this article.
然而,您的问题的解决方案非常简单明了。只需将 Configuration
class 更改为以下内容:
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;
}
这不仅简化了事情,还删除了您正在应用的给您带来麻烦的 anti-patterns。您的构造函数现在非常简单,甚至不再存在(没有比这更简单的了)。现在仅在构建对象图后才请求运行时数据(来自 HttpContext.Current
)。这允许容器可靠地验证其配置。