Reputation: 33
I am using Simple Injector in my project to hook up all the required dependencies, but I cannot call container.Verify
because it creates a Singleton
instance for an http configuration before the actual first request
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
}
}
This is a basic example of the scenario. I currently have around 60 services all depending on IConfiguration
All the configuration needs to happen when the configuration class is created
This is what I do to register the instances in the container
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
As per How can I skip verification of an object in the container
So the trick here is to trigger the creation of new
InstanceProducer
instances after the verification process
I know the workaround is using Lazy<T>
and InstanceCreator
but I cannot finish hooking my code correctly
EDIT
The Configuration
class has no dependencies. The problem with Configuration
is that it gets created as a Singleton
on the container.Verify
method call and at that time the currentHttpRequest.Url
is not the actual url
I suppose I can move the configuration from the constructor to a method (e.g GetConfiguration
) and do some refactoring but I am curious if delaying the instance creation can be achieved under the scenario of the question
Upvotes: 2
Views: 478
Reputation: 172606
As explained by Mark Seemann in this article, injection constructors should be simple and reliable. They shouldn't do anything that might cause it to fail. Calling HttpContext.Current
inside the constructor makes it unreliable, since this is something that might fail.
Besides this, your Configuration
component now depends upon runtime data (the HttpContext.Current
is runtime data), which is a sin, as explained in this article.
The solution to your problem however is really simple and straightforward. Just change your Configuration
class to the following:
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;
}
Not only does this simplify things, it also removes the anti-patterns that you were applying which caused you trouble. Your constructor is now so simple, that it isn't even there anymore (can't get any simpler than this). And the runtime data is now only requested (from HttpContext.Current
) after the object graph is constructed. This allows the container to verify its configuration reliably.
Upvotes: 3