Condition Decorator with Runtime Data - c#

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.

Related

.NET Core - Apply Multiple Constructor Discovery Rules in Implementation Factory

I am working with c# and .NET Core 3.1, and I have a class that looks like this.
public class MyClass : IMyClass
{
public MyClass()
{
…
}
public MyClass(IDependency dependency)
{
…
}
public MyClass(string appSettings)
{
…
}
…
}
So I know that with Dependency Injection, you can add services like this:
services
.AddScoped<IDependency, Dependency>()
.AddScoped<IMyClass, MyClass>();
and the Service Provider has rules (See https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#multiple-constructor-discovery-rules) to select the constructor based on which has the most arguments registered (In this case, MyClass(IDependency dependency)).
I have a specific case though, where, if a setting is found in configuration and valid, I want to use the third constructor. I planned to do that with something like this
services
.AddScoped<IDependency, Dependency>()
.AddScoped<IMyClass>(s =>
{
if(<insert config read and validation here>)
{
return new MyClass(appSetting);
}
else
{
//apply default rules to get MyClass
}
}
The problem is I can’t figure out a clean way to apply the default rules within an implementation factory. Does anyone know of a clean way to do this?
I've tried using ActivatorUtilities.CreateInstance, passing in just the ServiceProviders, but that seems to prioritize the first matching constructor, regardless of available registered dependencies (In this case MyClass()).
I also tried using services.AddScoped<IMyClass, MyClass>(); and the implementation factory combined, calling s.GetRequiredService<IMyClass>() in the else block, but that just results in an infinite loop of the implementation factory trying to resolve itself.

Using constructor injection when caller expects a specific constructor signature

I'm new to DI in .NET C# & autofac and having problems to understand how to use DI when I can't fully control the caller side.
There are two scenarios I have problems to understand.
Scenario 1: Caller expects a default constructor (without any parameters)
How to handle this scenario when I still want to inject some Service Interfaces when the class is constructed? I was thinking of constructor chaining, but that would mean I have to know the concrete type and it works around the idea of DI. (at least I think).
public class ServiceWorker
{
IService _service;
public ServiceWorker(IService service)
{
_service = service
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorker();
}
Scneario 2: Caller expects a specific constructor signature (e.g.
Same question here. How can I inject additional dependencies when the caller expects an exact match for the constructor signature?
I think my main issue in understanding the concept is, that I don't see how to do DI only partially when not everything is constructed by DI (caller)
public class ServiceWorker
{
IService _service;
public ServiceWorker(string name, string id, IService service)
{
_service = service
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorker(name, id);
}
I know, this is pretty basic, but I believe I need to understand this first before moving on. Are there alternatives?
As Steven correctly points out in his comment, being restricted to a specific constructor signature is an instance of the Constrained Construction anti-pattern. Sometimes, however, that can be outside your control.
An example is the so-called 'Provider pattern', which isn't a pattern at all. In such an example, you may have to play by the rules of a third-party framework, so there isn't much you can do about it. Such frameworks should be considered unfriendly to Dependency Injection.
Consider scenario 2 in the OP, since scenario 1 is just a special case of scenario 2. If you must supply a class with a certain constructor, you could create a Facade that has the required constructor signature. This enables you to avoid polluting your well-designed classes that use Dependency Injection with the constraints imposed by the third-party framework. It could look like this:
public class ServiceWorker
{
IService _service;
public ServiceWorker(string name, string id, IService service)
{
_service = service
}
}
public class ServiceWorkerFacade
{
ServiceWorker imp;
public ServiceWorkerFacade(string name, string id)
{
imp =
new ServiceWorker(
name,
id,
new FooService(
new BarService(),
new BazService());
}
}
public class Caller
{
// No way to change this.
var serviceWorker = new ServiceWorkerFacade(name, id);
}
FooService implements IService. Just to make things interesting, I've assumed that FooService has dependencies of its own, and that those dependencies are satisfied by BarService and BazService.
As Steven suggests, then, you can (from necessity) consider the Facade's constructor the Composition Root.
If you have any opportunity to influence the design of the framework in question, you could point the developers to my guidance on designing DI-friendly frameworks.

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.

Dependency Injection and 3rd Party APIs - Extension Methods w/ PI or Wrapper w/ CI

I am working on a C# project that sits on top of a 3rd party CMS. The team is leveraging Dependency Injection to promote loose coupling between classes.
I have the need to "extend" the apis of the CMS with common functions that are used in several pages.
What makes it interesting is these common functions have multiple dependencies.
In this case, is it more appropriate to extend this functionality using static extension methods or by creating new interfaces?
Context
Let's say the 3rd Party has two interfaces IContentLoader and IPageSecurity that work with Page objects:
namespace 3rdParty.Api
{
public class Page{}
public interface IContentLoader{
T LoadItem<T>(Guid id) where T : Page;
}
public interface IPageSecurity
{
bool CurrentUserCanReadPage(Page p);
}
}
And I want to write a common method like:
public IEnumerable<T> LoadAllChildPagesTheUserCanRead(Guid id) where T:Page
{
//load page, recursively collect children, then
//filter on permissions
}
(I admit this example is a bit trite)
Extension Methods
I could create a static extension method using Property Injection:
public static class IContentLoaderExtensions
{
public static Injected<IPageSecurity> PageSecurity {get;set;}
public static IEnumerable<T> LoadAllChildItems(
this IContentLoader contentLoader, Guid id){}
}
This method is then very discoverable, we use IContentLoader often so it's easier for a team member to find it. However, I have read that Property Injection is generally less beneficial than Constructor Injection and should be avoided if possible.
Wrapper
On the other hand, I could create a Wrapper:
public class AdvancedContentLoader
{
public AdvancedContentLoader(IContentLoader c, IPageSecurity p){
//save to backing fields
}
IEnumerable<T> LoadAllChildItems(Guid id){}
}
This approach allows for Constructor Injection, which avoids the potential hazards of Property Injection, but makes the method less discoverable. The consumer would need to know to depend on AdvancedContentLoader instead of using the IContentLoader they are use to.
Summary
In this case where a method has multiple dependencies, is it better to promote discoverability by using an extension method and take whatever brittleness may come from using Property Injection? Or is Construction Injection so favorable that I should create a wrapper class at the cost of making the method harder to find?
I would lean more towards the wrapper class but I would create another interface for it. I would name it similar so developers can find it.
public interface IContentLoaderWithPageSecurity : IContentLoader
{
IEnumerable<T> LoadAllChildItems<T>(IContentLoader contentLoader, Guid id) { }
}
New interface but same starting name so intellisense can help developers. Also this interface has to implement the 3rd party interface.
I would change your AdvancedContentLoader class to implement this interface and chain all calls to IContextLoader to 3rd party implementation and handle just the specific methods it needs to handle.
public class AdvancedContentLoader : IContentLoaderWithPageSecurity
{
private readonly IContentLoader _internalContentLoader;
private IPageSecurity _pageSecurity;
public AdvancedContentLoader(IContentLoader contentLoader, IPageSecurity pageSecurity)
{
_internalContentLoader = contentLoader;
_pageSecurity = pageSecurity;
}
// Chain calls on the interface to internal content loader
public T LoadItem<T>(Guid id) where T : Page
{
return _internalContentLoader.LoadItem<T>(id);
}
public IEnumerable<T> LoadAllChildItems<T>(IContentLoader contentLoader, Guid id)
{
// do whatever you need to do here
yield break;
}
}
The benefits of this is if you are using DI Container you can just register IContentLoaderWithPageSecurity interface to the class and you are still coding to an interface.
The naming convention helps the developers find it with intellisense, if the namespace of the class is in the using directive.
The new interface implements the old one so existing code base that needs IContentLoader you can still pass down IContentLoaderWithPageSecurity into those methods.
I would only lean towards extension methods if I didn't require a new dependency and could just just what is already there - otherwise you have to get "smart" and do property injection or something like the ConditionalWeakTable to hold extra state for the class.
I agree with Wiktor Zychla that this starts to become peoples subjective opinions.
I suggest a decorated content loader. This approach follows SRP principle, where you don't mix responsiblities - I still have a content loader and when I want to implemenet loading multiple elements, I delegate this to another class.
public class DecoratedContentLoader : IContentLoader
{
IContentLoader c;
IPageSecurity p;
public DecoratedContentLoader(IContentLoader c, IPageSecurity p)
{
this.c = c;
this.p = p;
}
public T LoadItem<T>(Guid id) where T : Page
{
var page = c.LoadItem<T>( id );
if ( p.CanUserReadPage( p ) )
return p;
// throw or return null
}
}
As you can see, this uses the security provider but still implements a single item provider interface.
Thus, another class responsible for loading multiple items can just take IContentProvider as an argument and use either the bare one or the decorated one without distinguishing between the two.
public class AdvancedContentLoader
{
// no need for additionak parameters, works
// with any loader, including the decorated one
public AdvancedContentLoader( IContentLoader c )
{
//save to backing fields
}
IEnumerable<T> LoadAllChildItems(Guid id){}
}
So, my initial reaction to this is that there might be a bit of over-thinking going on here. If I understand your question correctly, you are trying to figure out the easiest way to extend a third party API. In this case, the API has an interface that you like, IContentLoader, and your goal is to add another method to this interface which enables it:
in addition to loading a given page (defined by Guid),
to recursively load all child pages as well,
so long as the user has permission (which is in the responsibility of IPageSecurity).
According to Microsoft,
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
Which, if I understand, is exactly what you are trying to do here. I will admit that the structure and function for IPageSecurity does not make much sense to me, and that could be the reason behind the confusion. Bottom line, is there any reason why you would choose not to go this route? Perhaps your purpose is complicated by your example.

Dependency Injection and initialization methods

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>();

Categories

Resources