Dependency Injection and initialization methods - c#

I read Miško Hevery's Guide: Writing Testable Code and it states a warning sign if an "Object not fully initialized after the constructor finishes (watch out for initialize methods)".
Let's say I wrote a Redis wrapper class that has an init method that accepts hostname and port. This according to Miško, is a warning sign, since I need to call its init method.
The solution I'm contemplating with is the following:
For every class that need this kind of initialization, create a factory class that has a Create method which creates the class, and also call its init method.
Now in code: Instead of using something like:
class Foo
{
private IRedisWrapper _redis;
public Foo(IRedisWrapper redis)
{
_redis = redis;
}
}
....
IRedisWrapper redis = new RedisWrapper();
redis.init("localhost", 1234);
Foo foo = new Foo(redis);
I'd use something like:
class Foo
{
private IRedisWrapper _redis;
public Foo(IRedisWrapper redis)
{
_redis = redis;
}
}
....
RedisWrapperFactory redisFactory = new RedisWrapperFactory();
IRedisWrapper redisWrapper = redisFactory.Create();
Foo foo = new Foo(redisWrapper);
I'm using Simple Injector as an IOC framework, which makes this the above solution probelmatic - in this case I'd use something like:
class Foo
{
private RedisWrapper _redis;
public Foo(IRedisWrapperFactory redisFactory)
{
_redis = redisFactory.Create();
}
}
I'd really like to hear your input on the above solution.
Thanks

Perhaps I misunderstood your question, but I don't think Simple Injector is a limiting factor here. Since constructors should do as little as possible, you shouldn't call the Create method from within your constructor. It's even an odd thing to do, since a factory is meant to delay the creation of a type, but since you call Create inside the constructor the creation is not delayed.
Your Foo constructor should simply depend on IRedisWrapper and you should extract the redisFactory.Create() call to your DI configuration like this:
var redisFactory = new RedisWrapperFactory();
container.Register<IRedisWrapper>(() => redisFactory.Create());
But since the factory's sole purpose is to prevent duplicate initialization logic throughout the application, it now lost its purpose, since the only place the factory is used is within the DI configuration. So you can throw the factory out and write the following registration:
container.Register<IRedisWrapper>(() =>
{
IRedisWrapper redis = new RedisWrapper();
redis.init("localhost", 1234);
return redis;
});
You now placed the body of the Create method inside the anonymous delegate. Your RedisWrapper class currently has a default constructor, so this approach is fine. But if the RedisWrapper starts to get dependencies of its own, it's better to let the container create that instance. This can be done as follows:
container.Register<IRedisWrapper>(() =>
{
var redis = container.GetInstance<RedisWrapper>();
redis.init("localhost", 1234);
return redis;
});
When you need your class to be initialized after creation, as the RedisWrapper clearly needs, the adviced approach is to use the RegisterInitializer method. The last code snippet can written as follows:
container.Register<IRedisWrapper, RedisWrapper>();
container.RegisterInitializer<RedisWrapper>(redis =>
{
redis.init("localhost", 1234);
});
This registers the RedisWrapper to be returned when an IRedisWrapper is requested and that RedisWrapper is initialized with the registered initializer. This registration prevents the hidden call back to the container. This improves performance and improves the ability for the container to diagnose your configuration.

Having RedisWrapperFactory as the dependency doesn't seem quite right, since it's not really the factory you want. Unless of course there were specific parameters that you needed to pass to Create().
I don't know Simple Injector, but I would suggest that if it doesn't allow you to customise the creation of you objects to use your factory, you might want to look at some other DI frameworks. I use StructureMap, but there are others to choose from.
Edit: Having said that, if the contract for IRedisWrapper is that it must be initialised in some specific way after the constructor is called, it will look a little odd if you use it in Foo without calling init(). Especially to someone who is familiar with IRedisWrapper (many people), and not with the IOC setup of that particular application (not many people). Certainly, if you are going to use a factory, as Arghya C has said, use that through an interface too, otherwise you haven't actually achieved anything because you don't get to choose which IRedisWrapper you are injecting.

If your RedisWrapperFactory is defined in some other layer (where it gets data from DB/File/some service), the the code will kill the purpose of dependncy injection. Your layer becomes directly dependent on the other. Also, that is not testable anymore as you cannot create a mock/fake object of that for testing. Obviously you don't want to do real DB operations or I/O read-write or service call in testing.
You might want to do something like...
class Foo
{
private IRedisWrapper _redis;
public Foo(IRedisWrapperFactory redisFactory)
{
_redis = redisFactory.Create();
}
}
In the other layer
public class RedisWrapperFactory : IRedisWrapperFactory
{
public IRedisWrapper Create()
{
var r = RedisWrapper();
r.Init("localhost", 1234); //values coming from elsewhere
return r;
}
}
In your Bootstrapper() or application_Start() method, inject the factory, something like
container.Register<IRedisWrapperFactory, RedisWrapperFactory>();

Related

Conditional inheritance: base class depend on environment variable

I have two abstracts classes, 'ValidationsWithStorage' inherits 'Validations'
public abstract class Validations {
// methods..
}
public abstract class ValidationsWithStorage : Validations {
// ...
}
I also have a class:
public abstract class TestsValidations : T
T should be depend on the environment variable:
Environment.GetEnvironmentVariable("useStorage")
If this variable is null I want that T will be Validations.
Else, I want that T will be ValidationsWithStorage.
What is the best way to do it?
Thanks
I am not sure you can do this with inheritance. This is not the logic of inheritance. It will be better if you use something like factory pattern and change your current deisgn.
May be you can do something like this. I didn't test but i think it will be easier like this:
public interface Validations
{
void ValidationsStuff();
}
public class ValidationsWithStorage : Validations
{
public void ValidationsStuff()
{
//do something
}
}
public class TestsValidations : Validations
{
public void ValidationsStuff()
{
//do something
}
}
public class ValidationsFactory
{
public Validations geValidationsComponent(string useStorage)
{
if (string.IsNullOrEmpty(useStorage))
return new ValidationsWithStorage();
else
return new TestsValidations();
}
}
I don't think you can do what you want to do in the way you do it.
Why not let your class TestValidations take a parameter in its constructor of either type Validations or ValidationsWithStorage. If they both follow the same interface, your TestsValidations class wouldn't need to know (or care) which of the two it's working with.
So basically:
Create an interface for your Validations and ValidationsWithStorage class
Check your environment variable
Pass the correct class into the TestsValidation constructor according to the environment variable
Does that help?
You can do that using conditional compilation:
public abstract class TestsValidations
#if USESTORAGE
: ValidationsWithStorage
#else
: Validations
#endif
{
}
You can set it in project configuration or by passing additional parameters to msbuild: /p:DefineConstants="USESTORAGE"
I don't think this is good design, but it is doable.
If you want to work with inheritance I think your problem will be solved if you use the Generic Constraints
What not to do:
I don't recommend conditionally changing the definition of a class. There are weird, one-off reasons to do that, but we rarely encounter them and shouldn't make them a normal part of how we write code.
I also don't recommend a factory. A factory implies that you're making a decision at runtime, in production, whether to use a "real" class or a test class. A factory only makes sense if some data available only at runtime determines which implementation you want to use. For example, if you want to validate an address, you might use its country to determine whether to us a US validator, Canadian validator, etc, like this:
var validator = _validatorFactory.GetValidator(address.Country);
Also, that means that the "test" class would be referenced from your production code. That's undesirable and a little strange.
What to do:
If you aren't making such a decision at runtime then this should be determined in the composition root - that is, in the part of our application that determines, at startup, which classes we're going to use.
To start with, you need an abstraction. This is most often an interface, like this:
public interface IValidator
{
ValidationResult Validate(Something value);
}
The class that needs the validation would look like this:
public class ClassThatNeedsValidation
{
private readonly IValidator _validator;
public ClassThatNeedsValidation(IValidator validator)
{
_validator = validator;
}
// now the method that needs to use validation can
// use _validator.
}
That's dependency injection. ClassThatNeedsValidation isn't responsible for creating an instance of a validator. That would force it to "know" about the implementation of IValidator. Instead, it expects to have an IValidator provided to it. (In other words its dependency - the thing it needs - is injected into it.)
Now, if you're creating an instance of ClassThatNeedsValidation, it might look like this:
var foo = new ClassThatNeedsValidation(new ValidationWithStorage());
Then, in your unit test project, you might have a test implementation of IValidator. (You can also use a framework like Moq, but I'm with you - sometimes I prefer to write a test double - a test class that implements the interface.)
So in a unit test, you might write this:
var foo = new ClassThatNeedsValidation(new TestValidator());
This also means that TestValidator can be in your test project, not mixed with your production code.
How to make it easier:
In this example:
var foo = new ClassThatNeedsValidation(new ValidationWithStorage());
You can see how this might get messy. What if ValidationWithStorage has its own dependencies? Then you might have to start writing code like this:
var foo = new ClassThatNeedsValidation(
new ValidationWithStorage(
connectionString,
new SomethingElse(
new Whatever())));
That's not fun. That's why we often use an IoC container, a.k.a dependency injection container.
This is familiar if we use ASP.NET Core, although it's important to know that we don't have to use ASP.NET Core to do this. We can add Microsoft.Extensions.DependencyInjection, Autofac, Windsor, or others to a project.
Explaining this is somewhat beyond the scope of this answer, and it might be more than what you need right now. But it enables us to write code that looks like this:
services.AddSingleton<IValidator, ValidationWithStorage>();
services.AddSingleton<Whatever>();
services.AddSingleton<ISomethingElse, SomethingElse>();
services.AddSingleton<ClassThatNeedsValidation>();
Now, if the container needs to create an instance of ClassThatNeedsValidation, it will look at the constructor, figure out what dependencies it needs, and create them. If those classes have dependencies it creates them too, and so on.
This takes a minute or several or some reading/trying if it's a new concept, but trust me, it makes writing code and unit tests much easier. (Unless we do it wrong, then it makes everything harder, but that's true of everything.)
What if, for some reason, you wanted to use a different implementation of IValidator in a different environment? Because the code above is executed once, at startup, that's easy:
if(someVariable = false)
services.AddSingleton<IValidator, OtherValidator>();
else
services.AddSingleton<IValidator, ValidationWithStorage>();
You're making the decision, but you're making it once. A class that depends on IValidator doesn't need to know about this decision. It doesn't need to ask which environment it's in. If we go down that route, we'll end up with stuff like that polluting all of our classes. It will also make our unit tests much more difficult to write and understand. Making decisions like this at startup - the composition root - eliminates all of that messiness.

Condition Decorator with Runtime Data

Using Simple Injector I can see that I can register decorators based on information available at design-time, but is it possible to get the same behavior with run-time data?
Here is a simple example (in reality there are many more decorators):
public class LineageIdDecorator : IDataReader
{
public LineageIdDecorator(IDataReader dataReader)
{
_dataReader = dataReader;
}
// Implementation skipped...
}
public class RuntimeConfig
{
public bool IncludeLineage { get; set; }
public string ConnectionString { get; set; }
public string Query { get; set; }
}
public class DataSource
{
public IDataReader CreateDataReader(RuntimeConfig config)
{
var connection = new SqlConnection(config.ConnectionString);
var command = new SqlCommand(config.Query, connection);
connection.Open();
IDataReader dataReader = command.ExecuteQuery();
if (config.IncludeLineage)
{
dataReader = new LineageIdDecorator(dataReader);
}
return dataReader;
}
}
With the important part being:
if (config.IncludeLineage)
{
dataReader = new LineageIdDecorator(dataReader);
}
Am I stuck always instantiating these decorators myself? Or am I missing some Simple Injector feature?
Edit
Based on Steven's answer I am now trying to use scope and an IRuntimeConfigurationProvider to construct the decorators with the information they need to either be enabled or disabled. I am providing more context.
My goal is to write a plugin for an in-house workflow system. The contract looks like this:
public interface IWorkflowAction<T>
{
async Task<Markdown> Execute(T marshalledData)
}
This contract is company wide and I cannot change it. Markdown is a class provided in the same internal nuget package as the contract. T represents the type of configuration data I expect in my action. The host takes JSON, configured in a web site by a user, and automatically materializes it to the type I specify.
public class MyWorkflowAction : IWorkflowAction<List<RuntimeConfiguration>>
{
private readonly MyActionEngine _engine;
public MyWorkflowAction()
{
container = new Container();
// register components
container.Verify();
_engine = container.GetInstance<MyActionEngine>
}
public async Task<Markdown> Execute(List<RuntimeConfiguration> runtimeConfiguration)
{
foreach (var config in runtimeConfiguration)
{
await _engine.SendAsync(config);
}
_engine.Complete();
await _engine.Completion;
return new Markdown();
}
}
This is my entry point. I create MyWorkflowEngine in the constructor using SimpleInjector. MyWorkflowEngine is an implementation of an IActionBlock<T> from the TPL DataFlow library.
Each request is queued using SendAsync and executes in parallel depending on how app.config values have configured the MaxDOP.
The code inside MyActionEngine is manually building a an IDataReader and applying the required decorators based on the values in the config object.
Once all the work has been queued the action block is told to expect no more data. We then wait for completion and exit.
It's clear to me that I need to use the AsyncScopedLifestyle, but I'm still unclear on how to construct the decorators at run-time if they depend on the IRuntimeProviderContext, which itself depends on the current instance of the configuration object.
It’s not so much that you can’t apply decorators conditionally based on runtime information in Simple Injector, but this is a practice that is discouraged.
Making registrations based on runtime information is discouraged, because it makes your configuration hard to impossible to verify, since verification depends on being able to construct object graphs, which is often impossible, since this required runtime information is often not available at the time of verification (which could be at application startup or when running the test suite).
Instead you should not change the structure of your object graph based on runtime information, but instead use this runtime information to decide which call graph to take on an already constructed object graph.
Because of this discouragement, the built-in decorator facilities do not allow registering decorators conditionally based on runtime information. There are examples of how to do runtime based decoration in the code samples project in the Github repository, but they are mere examples, again, I would recommend against using them.
Instead of applying the decorator at runtime conditionally, apply the decorator constantly, and implement the branching inside the decorator, based on the runtime data that the decorator retrieves at the time it is invoked.
This might look as follows:
public class LineageIdDecorator : IDataReader
{
public LineageIdDecorator(
IDataReader decoratee, IRuntimeConfigProvider configProvider) { .. }
// IDataReader methods
public object DoSomething()
{
if (configProvider.Config.IncludeLineage)
{
// run decorated behavior
}
return decoratee.DoSomething();
}
}
Here a new abstraction IRuntimeConfigProvider is introduced that allows retrieving the runtime configuration at runtime, oppose to injecting it into the constructor.
Another approach would be to split the runtime selection behavior and the actual behavior of the decorator. This can be important when the decorator contains a lot of logic. Splitting them would into two decorators would make each decorator have a single responsibility. This would reduce the LineageIdDecorator back to your original implementation, and the second implementation could look much like this:
public class RuntimeDecoratorSelector : IDataReader
{
private readonly IDataReader decoratedDecoratee;
private readonly IDataReader originalDecoratee;
private readonly IRuntimeConfigProvider configProvider;
public RuntimeDecoratorSelector(
IDataReader decoratedDecoratee, IDataReader originalDecoratee,
IRuntimeConfigProvider configProvider)
{
this.decoratedDecoratee = decoratedDecoratee;
this.originalDecoratee = originalDecoratee;
this.configProvider = configProvider;
}
private IDataReader Decoratee =>
configProvider.Config.IncludeLineage ? decoratedDecoratee : originalDecoratee;
// IDataReader methods
public object DoSomething()
{
return Decoratee.DoSomething();
}
}
Both the decorated service as the original service are injected into this selector class, together with the IRuntimeConfigProvider.
Registering this new RuntimeDecoratorSelector, together with the original LineageIdDecorator and implementation becomes now a bit more complex, since it involves making conditional registrations, compared to decorators. Here’s how to make these registrations:
container.RegisterConditional<IDataReader, DataReaderImpl>(
c => c.Consumer?.ImplementationType == typeof(LineageIdDecorator)
|| c.Consumer?.Target.Name.StartsWith("original") == true);
container.RegisterConditional<IDataReader, LineageIdDecorator>(
c => c.Consumer?.Target.Name.StartsWith("decorated") == true);
container.RegisterConditional<IDataReader, RuntimeDecoratorSelector>(c => !c.Handled);
What we’re doing here is registering the DataReaderImpl conditionally and telling it to be injected into the LineageIdDecorator or into any constructor argument (of type IDataReader) where the argument name starts with original. This will be one of the parameters of the RuntimeDecoratorSelector.
The LineageIdDecorator is registered conditionally, but it is instructed to be injected into any constructor argument (of type IDataReader) where the argument name starts with decorated. This will obviously be the second argument of the RuntimeDecoratorSelector.
Last but not least, we’re registering the RuntimeDecoratorSelector. Perhaps surprisingly, it has to be registered conditionally as well. That’s because Simple Injector is very strict, and will detect when multiple registrations overlap. It forces you to very explicit of what it is you want. Not making this registration conditional, would cause it to be applicable to its own constructor arguments, which would cause a cyclic dependency. By stating that it should be injected into any consumer, when there isn’t already a registration that was handled, we make this registration a fallback and prevent the object graph from becoming cyclic or ambiguous.
So long story short, in case you wish to prevent building object graphs based on runtime conditions, you should either add the selection logic to the decorator or create a separate selector ‘decorator’. If you no matter what, which to apply the decorator during object graph construction, you can use the runtime decorator examples of the CodeSamples project.

SimpleInjector ctor injection mix registered types and simple values

How do I register types which take another registered type as a parameter and also simple types (like an integer)?
public interface IDeviceManager
{
// implementation omitted.
}
public class DeviceManager : IDeviceManager
{
public DeviceManager(IDeviceConfigRepository configRepo, int cacheTimeout)
{
// implementation omitted
}
}
I do have a container registration for the IDeviceConfigRepository. That's ok. But how do I create an instance of DeviceManager with the configured dependency and passing along an integer of my choice in composition root?
I thought about creating a factory.
public class DeviceManagerFactory : IDeviceManagerFactory
{
private readonly Container _container;
public DeviceManagerFactory(Container container)
{
_container = container;
}
public DeviceManager Create(int minutes)
{
var configRepo = _container.GetInstance<IDeviceConfigurationRepository>();
return new DeviceManager(configRepo, minutes);
}
}
This is pretty simple.
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
public class ExampleClassUsingDeviceManager
{
private readonly DeviceManager _deviceManager;
public ExampleClassUsingDeviceManager(DeviceManager deviceManager, ...)
{
_deviceManage = deviceManager;
}
// actions...
}
For this to work and to avoid circular dependencies I would probably have to move the factory from the "application" project (as opposed to class libraries) where the composition root is to the project where the DeviceManager is implemented.
Is that OK? It would of course mean passing around the container.
Any other solutions to this?
EDIT
In the same project for other types I am using parameter objects to inject configuration into my object graph. This works OK since I only have one class instance per parameter object type. If I had to inject different parameter object instances (for example MongoDbRepositoryOptions) into different class instances (for example MongoDbRepository) I would have to use some kind of named registration - which SimpleInjector doesn't support. Even though I only have one integer the parameter object pattern would solve my problem. But I'm not too happy about this pattern knowing it will break as soon as I have multiple instances of the consuming class (i.e. MongoDbRepository).
Example:
MongoDbRepositoryOptions options = new MongoDbRepositoryOptions();
MongoDbRepositoryOptions.CollectionName = "config";
MongoDbRepositoryOptions.ConnectionString = "mongodb://localhost:27017";
MongoDbRepositoryOptions.DatabaseName = "dev";
container.RegisterSingleton<MongoDbRepositoryOptions>(options);
container.RegisterSingleton<IDeviceConfigurationRepository, MongoDbRepository>();
I am excited to hear how you deal best with configurations done at composition root.
Letting your DeviceManagerFactory depend on Container is okay, as long as that factory implementation is part of your Composition Root.
Another option is to inject the IDeviceConfigRepository into the DeviceManagerFactory, this way you can construct a DeviceManager without the need to access the container:
public class DeviceManagerFactory : IDeviceManagerFactory {
private readonly IDeviceConfigurationRepository _repository;
public DeviceManagerFactory(IDeviceConfigurationRepository repository) {
_repository = repository;
}
public DeviceManager Create(int minutes) {
return new DeviceManager(_repository, minutes);
}
}
However now I do not have a registration for DeviceManager which is the type I ultimately need. Should I change these dependencies to the factory instead?
In general I would say that factories are usually the wrong abstraction, since they complicate the consumer instead of simplifying them. So you should typically depend on the service abstraction itself (instead of depending on a factory abstraction that can produces service abstraction implementations), or you should inject some sort of proxy or mediator that completely hides the existence of the service abstraction from point of view of the consumer.
#DavidL points at my blog post about runtime data. I'm unsure though whether the cacheTimeout is runtime data, although you seem to be using it as such, since you are passing it in into the Create method of the factory. But we're missing some context here, to determine what's going on. My blog post still stands though, if it is runtime data, it's an anti-pattern and in that case you should
pass runtime data through method calls of the API
or
retrieve runtime data from specific abstractions that allow resolving runtime data.
UPDATE
In case the value you are using is an application constant, that is read through the configuration file, and doesn't change during lifetime of the application, it is perfectly fine to inject it through the constructor. In that case it is not a runtime value. There is also no need for a factory.
There are multiple ways to register this in Simple Injector, for instance you can use a delegate to register the DeviceManager class:
container.Register<DeviceManager>(() => new DeviceManager(
container.GetInstance<IDeviceConfigRepository>(),
cacheTimeout: 15));
Downside of this approach is that you lose the ability of Simple Injector to auto-wire the type for you, and you disable Simple Injector's ability to verify, diagnose and visualize the object graph for you. Sometimes this is fine, while other times it is not.
The problem here is that Simple Injector blocks the registration of primitive types (because they cause ambiguity) while not presenting you with a clean way to make the registration. We are considering (finally) adding such feature in v4, but that doesn't really address your current needs.
Simple Injector doesn't easily allow you to specify a primitive dependency, while letting the container auto-wire the rest. Simple Injector's IDependencyInjectionBehavior abstraction allows you to override the default behavior (which is to disallow doing this). This is described here, but I usually advice against doing this, because it is usually requires quite a lot of code.
There are basically two options here:
Abstract the specific logic that deals with this caching out of the class and wrap it in a new class. This class will have just the cacheTimeout as its dependency. This is of course only useful when there actually is logical to abstract and is usually only logical when you are injecting that primitive value into multiple consumers. For instance, instead of injecting a connectionstring into multiple classes, you're probably better of injecting an IConnectionFactory into those classes instead.
Wrap the cacheTimeout value into a complex data container specific for the consuming class. This enables you to register that type, since it resolves the ambiguity issue. In fact, this is what you yourself are already suggesting and I think this is a really good thing to do. Since those values are constant at runtime, it is fine to register that DTO as singleton, but make sure to make it immutable. When you give each consumer its own data object, you won't have to register multiple instances of those, since they are unique. Btw, although named registations aren't supported, you can make conditional or contextual registrations using RegisterConditional and there are other ways to achieve named registrations with Simple Injector, but again, I don't think you really need that here.

Do I need to use synclock with objects managed by a DI container using singleton scope?

I have the following code:
public class DotLessFactory
{
private LessEngine lessEngine;
public virtual ILessEngine GetEngine()
{
return lessEngine ?? (lessEngine = CreateEngine());
}
private ILessEngine CreateEngine()
{
var configuration = new LessConfiguration();
return new LessFactory().CreateEngine(configuration);
}
}
Let's assume the following:
I always want the same instance of ILessEngine to be returned.
I use a DI container (I will use StructureMap for this example) to manage my objects.
The lifetime of my objects will be Singleton because of assumption number 1.
The code inside CreateEngine executes code that is referenced through a NuGet package.
DotLess is a mere example. This code could be applicable to any similar NuGet package.
Approach 1
I register my objects with my DI container using:
For<DotLessFactory>().Singleton().Use<DotLessFactory>();
For<ILessEngine>().Singleton().Use(container => container.GetInstance<DotLessFactory>().GetEngine());
For<ISomeClass>().Singleton().Use<SomeClass>();
Now I can add ILessEngine to a constructor and have my container inject an instance of it as per the code below.
public class SomeClass : ISomeClass
{
private ILessEngine lessEngine;
public SomeClass(ILessEngine lessEngine)
{
this.lessEngine = lessEngine;
}
}
Approach 2
Introduce an IDotLessFactory interface which exposes the GetEngine method. I register my objects with my DI container using:
For<IDotLessFactory>().Singleton().Use<DotLessFactory>();
For<ISomeClass>().Singleton().Use<SomeClass>();
Now my factory will create an instance of ILessEngine as per the code below.
public class SomeClass : ISomeClass
{
private ILessEngine lessEngine;
public SomeClass(IDotLessFactory factory)
{
Factory = factory;
}
public IDotLessFactory Factory { get; private set; }
public ILessEngine LessEngine
{
get
{
return lessEngine ?? (lessEngine = Factory.GetEngine());
}
}
}
My questions are:
What is the fundamental difference between Approach 1 and 2 when it comes to ILessEngine? In approach 1 the ILessEngine is managed by the container and in approach 2 it is not. What are the upside/downside to each approach? Is one approach better than the other?
Do I need to use a synclock inside the CreateEngine method to ensure thread safety for any of the approaches? When should/shouldn't I use synclock in a scenario like this?
I have seen examples where Activator.CreateInstance is used inside the CreateEngine method as opposed to newing up the object directly. Is there a reason one would use this approach? Has this something to do with not introducing direct dependencies in the factory object to objects inside the NuGet package?
Let's assume the referenced NuGet package works with HttpContext under the hood. Would registering my factory in singleton scope have any negative effect on HttpContext or does that not matter since I assume the NuGet package most likely manages the scope of HttpContext itself?
Finally, the DotLessFactory will eventually be used with Bundles (Microsoft.AspNet.Web.Optimization NuGet package) and the Bundle is only instantiated (not managed by container) on Application Start. The Bundle will depend on an injected instance of DotLessFactory. Does this fact make any difference to the questions above?
Any feedback would be extremely helpful.
It's non-trivial to answer these questions specifically, but allow me to provide some non-exhaustive comments:
As far as I can tell, none of the approaches guarantee requirement #1 (singleton). This is because two threads could perform a look-up at the same time and both evaluate lessEngine to null and trigger the creation of a new instance. The first approach may end up being thread safe if StructureMap lookups are thread safe, but I'd be surprised if this was the case (and regardless, you do not want your code to depend on an implementation "detail" in a 3rd party library).
Both solutions make the same mistake, which is essentially checking whether an instance has already been created without protecting the entire code region. To solve the problem, introduce a private object variable to lock on, and protect the code region creating the instance:
private object engineLock = new object();
public virtual ILessEngine GetEngine()
{
lock( engineLock ) { return lessEngine ?? (lessEngine = CreateEngine()); }
}
As an aside, this would not be necessary if you could make StructureMap handle construction of the entire object chain, as it would then be up to StructureMap to ensure the singleton requirement as per your configuration of the container.
You can only new objects if you know they have a default constructor (e.g. through a generic constraint in the code for a type parameter) or you have a compile-time reference to them. Since an IoC mostly creates things it didn't know about at compile time, and it often needs to pass parameters when doing so, Activator.CreateInstance is used istead. As far as I know, using "new" generates IL to invoke Activator.CreateInstance, so the end result is all the same.
The lifetime of HttpContext is managed outside of your application (by ASP.NET) and so there is no scoping issue. HttpContext.Current will either be set or not, and if it isn't then you're doing work too early for it to be available (or executing in a context where it is never going to be available, e.g. outside ASP.NET).
Uh, not sure what potential problem you're considering here, but my best guess is that it shouldn't have any effect on your code.
Hope this helps!

How do you make a Generic Generic Factory?

I am working on a client (Silverlight) interface to a collection of webmethod. And I am trying to avoid writing any custom code for every webmethod. So I have created a ServiceCall<TResult> to handle each call, TResult specifies the return type of the service (I use XmlSerializer to create the returned instance). The client class exposes a function matching each webmethod, and all that function has to do is to create a new instance of ServiceCall<TResult>, with the TResult specified as the expected return type of the method.
And that works just fine.
I am also using Ninject (dependency injector) to try and keep everything independent. Ninject supports open generics, whichs works out great with my ServiceCall<TResult>.
But it also means that I'm injecting a reference to the Ninject container. Which hides the dependency on ServiceCall<TResult> being bound to the container. So I would like to instead inject a factory for creating my ServiceCall<TResult> instances. Which is not tricky, but I would like to make it a generic generic factory. Meaning I would like to have something like Factory<T<>> which would have a method public T<TU> Createinstance<TU>().
But I have no idea how I could create generic class with a type parameter that is itself an open genric.
Is it event posible in .Net? - Or do I have to create a specific ServiceCallFactory?
Edit:
I am using interfaces for the dependencies, but there's no need to mix them into the question here, so I edited that out of the question.
In responce to Timwi:
The common way to use dependency injection (DI) is to bind an interface to your implementation, only the container knows of these bindings. You then code up against the interfaces instead. This brings a ton of advantages. More than I can mention here.
Anyway it also rules out the static classes (since that would be a dependency on a specific class). Instead I'll instruct the container (Ninject in this case) to always hand me the same instance for the factory interface, in a singleton like behavior.
This rules out the public static class Factory<T> option, because it is static, and if it is not static I would need to now every type of T I'm gonna use, somewhat defeating the purpose of having a generic class.
The suggestion of having a non-generic class with a "totally generic" method (as in I pass in ServiceCall<MyResult> instead of just MyResult), is what more or less what I am doing now (minus the static class part). The Ninject container has an Get method that work like your second suggestion.
The problem with this is two part; firstly it makes my code directly dependent on one container (Ninject), but this is not really that big a problem to me. What does annoy me is that if you look at me Client from the outside, you'll only see a dependency on Ninject. You wont know until you run try to make a call that client needs an implementation of ServiceCall registered with Ninject to work.
But if the Client contructor took a parameter of type Factory>, then it would much clearer.
In any case I would think this would be a common issue, so either there a common solution, or it is not a common issue and I am trying to do something stupid ;)
I am still not that into dependency injection, so that may very well be the case.
Is this what you are looking for: Generic Factory Pattern
namespace GenericFactoryPatternTestApp
{
public class Factory< T >
{
private readonly Dictionary< string, Type > _factoryDictionary = new Dictionary< string, Type >();
public Factory()
{
Type[] types = Assembly.GetAssembly(typeof (T)).GetTypes();
foreach (Type type in types)
{
if (!typeof (T).IsAssignableFrom(type) || type == typeof (T))
{
// Incorrect type
continue;
}
// Add the type
_factoryDictionary.Add(type.Name, type);
}
}
public T Create< V >(params object[] args)
{
return (T) Activator.CreateInstance(_factoryDictionary[typeof (V).Name], args);
}
}
}
So if I understand you right, you’d have a class looking a bit like this:
public static class Factory<T<>>
{
public static T<TU> CreateInstance<TU>() { /* ... */ }
}
and then you’d call it how? Like this?
var myServiceCall = Factory<ServiceCall<>>.CreateInstance<MyResult>();
What stops you from simply declaring the factory like this...
public static class Factory<T>
{
public static T CreateInstance() { /* ... */ }
}
... or this ...
public static class Factory
{
public static T CreateInstance<T>() { /* ... */ }
}
... and then generating your instance like this?
var myServiceCall = Factory<ServiceCall<MyResult>>.CreateInstance();
var myServiceCall = Factory.CreateInstance<ServiceCall<MyResult>>();
I’m sorry if I’m being dumb, but I’d probably need to know how Ninject works and how it allows you to pass in a factory.

Categories

Resources