I currently writing a project that need to generate different type of object, base on XML configuration file.
Each object that generated is instance of an IProvidor interface and and needs to contain several pre-processing, and handling methods that defined by the XML configuration file.
I generated different factories classes for:
creating the Provider (which implement the IProvider interface)
creating the Pre-Processing operation (I have IPreProcessor interface that all preProcessor class need to implement.
the same thing for handling methods (IHandler interface being implemented by several classes).
Question
How can I combine all of this into one object in runtime?
Olivier Jacot-Desc is absolutely on the right track (+1 for that). The only thing missing from his answer is loading the correct implementations from the configuration.
There are a lot of ways of doing this, for instance by storing the type name in the configuration, but you can also go for a simpler approach, such as storing a simple boolean in the configuration.
IProvider providerX = GetProviderFromConfig();
IHandler handlerZ = GetHandlerFromConfig();
IPreProcessor preProcessorY = GetProcessorFromConfig();
var provider =
new ProviderWrapper(providerX, preProcessorY, handlerZ);
private static IProvider GetProviderFromConfig()
{
if (ConfigurationManager.AppSettings["provider"] == "mail")
{
return new MailProvider();
}
else
{
return new FtpProvider();
}
}
// implement GetHandlerFromConfig just like
// the GetProvider.
UPDATE
When you have many types to switch between, storing the name of the type might be a better choice:
private static IProvider GetProviderFromConfig()
{
string typeName =
ConfigurationManager.AppSettings["provider"];
Type providerType = Type.GetType(typeName);
return (IProvider)
Activator.CreateInstance(providerType);
}
UPDATE 2
Here is an example of how to configure this with a DI Container. I'm using Simple Injector (with extensions), but any container will do (although the way to configure it will differ per container):
Registration:
using SimpleInjector;
using SimpleInjector.Extensions;
Type providerType = Type.GetType(
ConfigurationManager.AppSettings["provider"]);
Type handlerType = Type.GetType(
ConfigurationManager.AppSettings["handler"]);
Type processorType = Type.GetType(
ConfigurationManager.AppSettings["preProcessor"]);
var container = new Container();
container.Register(typeof(IProvider), providerType);
container.Register(typeof(IHandler), handlerType);
container.Register(typeof(IPreProcessor), processorType);
Resolving a provider:
var provider = container.GetInstance<IPovider>();
Tip: If you use constructor injection, you don't have to wire the types by hand, the container will do this for you. For instance, when your MailProvider looks like this, the container is able to inject the needed dependencies (IHandler, and IPreProcessor) through the constructor:
public class MailProvider : IProvider
{
private readonly IHandler handler;
private readonly IPreProcessor preProcessor;
public MailProvider(IHandler handler,
IPreProcessor preProcessor)
{
this.handler = handler;
this.preProcessor = preProcessor;
}
public void SomeAction() { ... }
}
I would create a wrapper class which implements these interfaces and inject the functionality.
Example interfaces
public interface IProvider
{
string ProvideSomething(int id);
}
public interface IPreProcessor
{
void PreProcess(string parameter);
}
public interface IHandler
{
void HandleSomething();
}
The wrapper would implement all of these interfaces
public class ProviderWrapper : IProvider, IPreProcessor, IHandler
{
private IProvider _provider;
private IPreProcessor _preProcessor;
private IHandler _handler;
public ProviderWrapper(IProvider provider, IPreProcessor preProcessor, IHandler handler)
{
_provider = provider;
_preProcessor = preProcessor;
_handler = handler;
}
#region IProvider Members
public string ProvideSomething(int id)
{
return _provider.ProvideSomething(id);
}
#endregion
#region IPreProcessor Members
public void PreProcess(string parameter)
{
_preProcessor.PreProcess(parameter);
}
#endregion
#region IHandler Members
public void HandleSomething()
{
_handler.HandleSomething();
}
#endregion
}
Now, you can instantiate a ProviderWrapper with the required functionality according to the configuration file and combine different the interface implementations.
var provider = new ProviderWrapper(providerX, preProcessorY, handlerZ);
Perhaps you could create instances of all of these classes as you would normally at runtime, then serialize them to xml. Then when you want to load your "configuration" you just need to de-serialize.
See here for serialization.
Related
I'm using Microsoft Unity as my IoC container. I have a number of extension classes which adds useful methods to my business objects
This is the sort of code I use today:
public static class BusinessObjectExtensions
{
public static bool CanDoStuff(this BusinessObject obj)
{
var repository = BusinessHost.Resolver.Resolve<IRepository>();
var args = new EArgument { Name = obj.Name };
return repository.AMethod(obj.UserName, args);
}
}
Is there a better way to manage dependency injection for extension classes?
The de facto default way of Dependency Injection by Constructor Injection is not possible for static classes. It would be possible to use Parameter Injection like below, however that is not a very clean way.
public static class BusinessObjectExtensions
{
public static bool CanDoStuff(this BusinessObject obj, IRepository repository)
{
var args = new EArgument { Name = obj.Name };
return repository.AMethod(obj.UserName, args);
}
}
You should actually try to avoid extensionmethods unless they only work on internal data (properties in the class itself), or simple datatypes provided in the method. You should not talk to other dependencies in your extension methods. If you follow this rule, you should not need to inject extension-classes with your IoC at all.
Why would you do that?
This raises the coupling in your application to the roof and can be very confusing for your teammates to use the extension method (they'll have to keep in mind to inject the repository each time the method is used).
Instead, create a separate class and use constructor injection to inject the IRepository instance:
public class StuffExecuter
{
private readonly IRepository _repository;
public StuffExecuter(IRepository repository)
{
_repository = repository;
}
public bool CanExecute(BusinessObject obj)
{
_repository.Add(obj.UserName, new EArgument
{
Name = obj.Name
});
}
}
I have a class that returns a repository (read only) using a generic method this is to reduce the number of repository classes I need to inject into classes in my business layer. It also allows me to add and use a new repo anywhere I have this wrapper class simply by adding a repo which implements IGenericReadRepo<T> as this will be registered in unity using the line Container.RegisterType(typeof(IGenericReadRepository<>), typeof(GenericReadRepository<>), new TransientLifetimeManager());. However this has is dependent on unity being the DI container. This smells to me.
public class ReadRepositoryWrapper : IReadRepositoryWrapper
{
private IUnityContainer _unityContainer;
public ReadRepositoryWrapper(IUnityContainer container)
{
_unityContainer = container;
}
public IGenericReadRepository<T> GetReadRepository<T>() where T : class
{
return _unityContainer.Resolve<IGenericReadRepository<T>>();
}
}
Can anyone think of a way to implement the GetReadRepository<T> without a the dependency on unity while not introducing any new dependencies. Or can someone think of another way to get repositories without having bloated constructors or a dependency on my context.
You can create generic factory interfaces/classes for dynamic object creation. Many DI containers support object creation using lambda expressions.
public interface IFactory<T>
{
T Create();
}
public class Factory<T> : IFactory<T>
{
private readonly Func<T> _creator;
public Factory(Func<T> creator)
{
if(creator == null)
throw new ArgumentNullException("creator");
_creator = creator;
}
public T Create()
{
return _creator();
}
}
The generic factory interface than can be injected into the consuming classes.
public class ReadRepositoryWrapper<T> : IReadRepositoryWrapper<T> where T : class
{
private readonly IFactory<IGenericReadRepository<T>> _factory;
public ReadRepositoryWrapper(IFactory<IGenericReadRepository<T>> factory)
{
if(factory == null)
throw new ArgumentNullException("factory");
_factory = factory;
}
public IGenericReadRepository<T> GetReadRepository()
{
return _factory.Create();
}
}
Or something like that.
Ok this is driving me crazy! I have a generic method in a generic class.
public interface IHandler<T> where T : class
{
T[] parseCSV(string InputFileName)
}
public class Handler<T> : IHandler<T> where T : class
{
public T[] parseCSV(string InputFileName)
{
if (File.Exists(InputFileName))
{
_inputFileName = InputFileName;
var Engine = new FileHelperEngine<T>();
return Engine.ReadFile(_inputFileName);
}
else
{
throw new IOException($"{InputFileName} not found!");
}
}
}
I have registered the generic in a IoC container as such:
container.RegisterType(typeof(IHandler<>), typeof(Handler<>));
Along with several mappers to parse files with the FileHelpers package
container.RegisterType<IMapper1, Mapper1>();
container.RegisterType<IMapper2, Mapper2>();
container.RegisterType<IMapper3, Mapper3>();
My container is legit for the majority of my app, and I can instate the IHandler object.
IHandler<IMapper1> Handler1 = container.Resolve<IHandler<IMapper1>>();
However, I cannot figure out how to pass the IMapper1 object into the generic parseCSV method so it will resolve in FileHelperEngine.
Does anyone know how to pass the Mapper object to FileHelperEngine using Unity? I would like to get that dependency off of the client code.
You have a dependency in your parseCSV method. Therefore, you should inject that into your class as well. There are many ways to do that but I prefer, and I have seen many other devs also prefer, constructor injection.
Thus all you need is an interface and then inject an instance of a class which implements the interface into your constructor like this:
public interface IFileHelperEngine<T> where T : class
{
T[] ReadFile(string inputFileName);
}
public class Handler<T> : IHandler<T> where T : class
{
private IFileHelperEngine<T> fileHelperEngine;
public Handler(IFileHelperEngine<T> fileHelperEngine) //<----See this.
{
this.fileHelperEngine = fileHelperEngine;
}
public T[] parseCSV(string InputFileName)
{
if (File.Exists(InputFileName))
{
_inputFileName = InputFileName;
return this.fileHelperEngine.ReadFile(_inputFileName); //<--and this
}
throw new IOException($"{InputFileName} not found!");
}
}
This is actually good because now you can mock the IFileHelperEngine when you are unit testing the Handler<T> class.
FYI, you are not using .NET naming conventions; Locals should use camel case notation and method names should use Pascal Notation.
I am humbling with a problem related to AutoFac and the the abstract factory pattern. My Example is a a service to use an IRepositoryFactory to create a Repository based on JSON or InMemory related to the user input.
// Abstract Factory
public interface IRepositoryFactory{
IRepository Create(string databaseIdentifier);
}
// JSON
public class JsonRepositoryFactory{
public IRepository Create(string databaseIdentifier){
return new JsonRepository(databaseIdentifier);
}
}
// InMemory
public class MemoryRepository{
public IRepository Create(string databaseIdentifier){
return new MemoryRepository(databaseIdentifier);
}
}
The Service should pull the Factory by Constructor Injection.
public interface IShopService{
public string Name {get;}
}
public class BeerShop : IShopService {
public string Name {get; private set;}
private readonly IRepository _repository;
public BeerShop(IRepositoryFactory repositoryFactory){
Name = "beershop";
_repository = repositoryFactory.Create(Name);
}
}
So far I am good with this. But the initialization is not my favorite.
var builder = new ContainerBuilder();
var userInput = ReadInput();
if(userInput = "json")
builder.RegisterType<IRepositoryFactory>().As<JsonRepositoryFactory>();
else
builder.RegisterType<IRepositoryFactory>().As<MemoryRepositoryFactory>();
builder.RegisterType<IShopService>.As<BeerShop>();
var container = builder.build();
[...]
var service = container.Resolve<IShoptService>();
// and so on ...
Is this the right approach to solve it? I am not convinced by my own design because it forces the user input before the initialization of the container. What if the user has to change the Repository while runtime? Is the abstract factory pattern the right tool to solve this problem?
Since the type of repository is known at the time the container is configured, you should register the specific repository directly. There is no need to introduce a factory, as there hardly ever is a reason to introduce a factory abstraction.
Example:
var builder = new ContainerBuilder();
var userInput = ReadInput();
if(userInput = "json")
builder.Register<IRepository>(c => new JsonRepository("dbidentifier"));
else
builder.Register<IRepository>(c => new MemoryRepository());
builder.RegisterType<BeerShop>.As<IShopService>();
var container = builder.build();
[...]
var service = container.Resolve<IShopService>();
This code allows the BeerShop to be simplified, because its constructor would be simple and it now it only depends on IRepository instead of IRepositoryFactory and IRepository. This simplifies testing and makes it easier to reason about this class. Furthermore, it removes the unneeded abstraction.
If you want to change the behaviour of the factory during runtime, then you have to move the logic of deciding the type of IRepository being created to the factory itself. You can adapt the pattern and tweak it to fit your requirements rather than conforming to the specific way of doing it.
The following is a way to do it, if you think about it, you can find different ways of adapting it.
public interface IRepository
{
//repository contracts
}
public interface IRepositoryFactory
{
IRepository Create(string arguments);
}
public interface IRepositoryBuilder
{
RepositoryType Type { get; }
IRepository Create(string args);
}
public class ApplicationSettings
{
public RepositoryType RepositoryType { get; set; }
}
public enum RepositoryType { Json, Text }
// Default implementation of repository factory based on applicationsettings.
public class ConfigurableRepositoryBuilder:IRepositoryFactory
{
private readonly ApplicationSettings _settings;
private readonly IEnumerable<IRepositoryBuilder> _repositoryBuilders;
public ConfigurableRepositoryBuilder(ApplicationSettings settings, IEnumerable<IRepositoryBuilder> repositoryBuilders)
{
_settings = settings;
_repositoryBuilders = repositoryBuilders;
}
public IRepository Create(string arguments)
{
var builder = _repositoryBuilders.First(x => x.Type == _settings.RepositoryType);
//configure builder settings and then call create
return builder.Create(arguments);
}
}
Now you can change the global settings anytime and you will get new type of repository from the next call onwards. Instead of a global singleton, you can read from app.config or other settings file also.
You now want to implement the IRepositoryBuilder for each type of supported IRepository Type
If I have the following code:
public class RobotNavigationService : IRobotNavigationService {
public RobotNavigationService(IRobotFactory robotFactory) {
//...
}
}
public class RobotFactory : IRobotFactory {
public IRobot Create(string nameOfRobot) {
if (name == "Maximilian") {
return new KillerRobot();
} else {
return new StandardRobot();
}
}
}
My question is what is the proper way to do Inversion of Control here? I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I? And I don't want to bring them in via a IoC.Get<> right? bc that would be Service Location not true IoC right? Is there a better way to approach the problem of switching the concrete at runtime?
For your sample, you have a perfectly fine factory implementation and I wouldn't change anything.
However, I suspect that your KillerRobot and StandardRobot classes actually have dependencies of their own. I agree that you don't want to expose your IoC container to the RobotFactory.
One option is to use the ninject factory extension:
https://github.com/ninject/ninject.extensions.factory/wiki
It gives you two ways to inject factories - by interface, and by injecting a Func which returns an IRobot (or whatever).
Sample for interface based factory creation: https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface
Sample for func based: https://github.com/ninject/ninject.extensions.factory/wiki/Func
If you wanted, you could also do it by binding a func in your IoC Initialization code. Something like:
var factoryMethod = new Func<string, IRobot>(nameOfRobot =>
{
if (nameOfRobot == "Maximilian")
{
return _ninjectKernel.Get<KillerRobot>();
}
else
{
return _ninjectKernel.Get<StandardRobot>();
}
});
_ninjectKernel.Bind<Func<string, IRobot>>().ToConstant(factoryMethod);
Your navigation service could then look like:
public class RobotNavigationService
{
public RobotNavigationService(Func<string, IRobot> robotFactory)
{
var killer = robotFactory("Maximilian");
var standard = robotFactory("");
}
}
Of course, the problem with this approach is that you're writing factory methods right inside your IoC Initialization - perhaps not the best tradeoff...
The factory extension attempts to solve this by giving you several convention-based approaches - thus allowing you to retain normal DI chaining with the addition of context-sensitive dependencies.
The way you should do:
kernel.Bind<IRobot>().To<KillingRobot>("maximilliam");
kernel.Bind<IRobot>().To<StandardRobot>("standard");
kernel.Bind<IRobotFactory>().ToFactory();
public interface IRobotFactory
{
IRobot Create(string name);
}
But this way I think you lose the null name, so when calling IRobotFactory.Create you must ensure the correct name is sent via parameter.
When using ToFactory() in interface binding, all it does is create a proxy using Castle (or dynamic proxy) that receives an IResolutionRoot and calls the Get().
I don't want to add the KillerRobot and StandardRobot concretes to the Factory class do I?
I would suggest that you probably do. What would the purpose of a factory be if not to instantiate concrete objects? I think I can see where you're coming from - if IRobot describes a contract, shouldn't the injection container be responsible for creating it? Isn't that what containers are for?
Perhaps. However, returning concrete factories responsible for newing objects seems to be a pretty standard pattern in the IoC world. I don't think it's against the principle to have a concrete factory doing some actual work.
I was looking for a way to clean up a massive switch statement that returned a C# class to do some work (code smell here).
I didn't want to explicitly map each interface to its concrete implementation in the ninject module (essentially a mimic of lengthy switch case, but in a diff file) so I setup the module to bind all the interfaces automatically:
public class FactoryModule: NinjectModule
{
public override void Load()
{
Kernel.Bind(x => x.FromThisAssembly()
.IncludingNonPublicTypes()
.SelectAllClasses()
.InNamespaceOf<FactoryModule>()
.BindAllInterfaces()
.Configure(b => b.InSingletonScope()));
}
}
Then create the factory class, implementing the StandardKernal which will Get the specified interfaces and their implementations via a singleton instance using an IKernal:
public class CarFactoryKernel : StandardKernel, ICarFactoryKernel{
public static readonly ICarFactoryKernel _instance = new CarFactoryKernel();
public static ICarFactoryKernel Instance { get => _instance; }
private CarFactoryKernel()
{
var carFactoryModeule = new List<INinjectModule> { new FactoryModule() };
Load(carFactoryModeule);
}
public ICar GetCarFromFactory(string name)
{
var cars = this.GetAll<ICar>();
foreach (var car in cars)
{
if (car.CarModel == name)
{
return car;
}
}
return null;
}
}
public interface ICarFactoryKernel : IKernel
{
ICar GetCarFromFactory(string name);
}
Then your StandardKernel implementation can get at any interface by the identifier of you choice on the interface decorating your class.
e.g.:
public interface ICar
{
string CarModel { get; }
string Drive { get; }
string Reverse { get; }
}
public class Lamborghini : ICar
{
private string _carmodel;
public string CarModel { get => _carmodel; }
public string Drive => "Drive the Lamborghini forward!";
public string Reverse => "Drive the Lamborghini backward!";
public Lamborghini()
{
_carmodel = "Lamborghini";
}
}
Usage:
[Test]
public void TestDependencyInjection()
{
var ferrari = CarFactoryKernel.Instance.GetCarFromFactory("Ferrari");
Assert.That(ferrari, Is.Not.Null);
Assert.That(ferrari, Is.Not.Null.And.InstanceOf(typeof(Ferrari)));
Assert.AreEqual("Drive the Ferrari forward!", ferrari.Drive);
Assert.AreEqual("Drive the Ferrari backward!", ferrari.Reverse);
var lambo = CarFactoryKernel.Instance.GetCarFromFactory("Lamborghini");
Assert.That(lambo, Is.Not.Null);
Assert.That(lambo, Is.Not.Null.And.InstanceOf(typeof(Lamborghini)));
Assert.AreEqual("Drive the Lamborghini forward!", lambo.Drive);
Assert.AreEqual("Drive the Lamborghini backward!", lambo.Reverse);
}