Create instance by enum value + dependency injection - c#

I have some handler classes in my application which are created in runtime according to passed enum value. It looks like this:
public interface IMyHandler
{
void Handle();
}
public class SimpleHandler : IMyHandler
{
public void Handle()
{
//logic here...
}
}
public class ComplexHandler : IMyHandler
{
public void Handle()
{
//logic here...
}
}
public enum HandlerTypes
{
Simple,
Complex
}
public class Hanlderfactory
{
public IMyHandler CreateHandler(HandlerTypes type)
{
switch(type)
{
case HandlerTypes.Simple:
return new SimpleHandler();
case HandlerTypes.Complex:
return new ComplexHandler();
default:
throw new NotSupportedException();
}
}
}
It's ok for me. But there is a problem here if I want to inject some components in my handlers like this:
public class SimpleHandler : IMyHandler
{
public SimpleHandler(IComponentOne c1, IComponentTwo c2, IComponentThree c3)
{
//...
}
public void Handle()
{
//logic here...
}
}
I use Unity IoC container and of course I want to use it here. But it looks ugly to call Resolve method here manually. Am I on wrong path? How to use both of this patterns together gracefully? Is it a single option here to call IoC container inside facotry?
UPDATE: I tried to use injection of delegate with InjectionFactory class. It works fine. But in this case if I need such factory logic in two applications I need to register this delegate and mapping between enums and classes in both applications startup:
var container = new UnityContainer();
container.RegisterType<IMyHandler, SimpleHandler>(HandlerTypes.Simple.ToString());
container.RegisterType<IMyHandler, ComplexHandler>(HandlerTypes.Complex.ToString());
container.RegisterType<Func<HandlerTypes, IMyHandler>>(new InjectionFactory(c => new Func<HandlerTypes, IMyHandler>(type => c.Resolve<IMyHandler>(type.ToString()))));

Using Enum with a factory is a code smell that indicates you need to do more refactoring.
An alternative is to use the strategy pattern as in this example. Note the use of Type instead of an Enum ensures you only have to change one piece of code when the design changes (you could alternatively use a string datatype).
Another alternative would be to inject a Func into the factory so your DI container can resolve instances.
Injecting the container into an abstract factory is a way of making a framework extension point. As long as the factory is part of your composition root, this is okay.

Related

How to create complex objects using factory design pattern

Hello i have to create a complex object , and i wanted to use the factory pattern for it.However i do not know what to do with the additional dependencies that the object needs in order to be created.
Dependencies
public class SomeService
{
}
public class SomeOtherService
{
}
Hierarchy
public abstract class NeededObjectBase
{
public readonly int Type {get;set;} //id selected by the factory
public abstract void DoSomething();
}
public class A:NeededObjectBase
{
private SomeService service;
A(SomeService service){ this.service=service;}
public override void DoSomething(){}
}
public class B:NeededObjectBase
{
public B(SomeService service,SomeOtherService otherService){
this.service=service;
this.otherService=otherService
}
public SomeOtherService service;
public SomeOtherService otherService;
public override void DoSomething(){}
}
Factory
public class Factory
{
public static NeededObjectBase CreateInstance(int type)
{
switch(type)
{
case 0:return new A(); //this would need SomeService => new A(someService)
case 1:return new B(); // this would need SomeService & SomeOtherService => new B(someService,someOtherService);
default: return new A();
}
}
}
Usage
public class Aggregate
{
private SomeService s1;
private SomeOtherService s2;
public void UseNeededObject(int type)
{
NeededObjectBase neededObject=Factory.CreateInstance(type);
neededObject.DoSomething();
}
}
If you look in the code things happen like this:
I have an Aggregate class where i keep my dependencies.Inside its method i use the Factory based on the type parameter in order to create the right object.However i do not know what to do with the dependencies.Should the factory get all the required dependencies in order to create the objects ?
So basically i do not know who should keep the dependencies for object creation.The factory makes the selection but how does it provide the right dependencies in order to instantiate the selection ?
P.S I would need somehow to first make the selection based on the parameter and retrieve something from the factory and then that something to get its dependencies in order to create the final object.
One good way of doing this is to use a DI library and to then inject whatever container it provides into the factory; the factory is then only deciding based on the passed parameters what type it should return, and then delegating to the container to construct that object for return.
This has some benefits
It lets you separate the lifecycle of these dependent objects (and indeed, the constructed objects) from the factory
It decouples the factory from having to know how to construct all the possible object graphs it provides and lets it focus on making the decision on what to build, not how to build it
e.g.
public class SimpleFoo: Foo
{
public SimpleFoo(IServiceA a){...}
}
public class ComplexFoo: Foo
{
public ComplexFoo(IServiceA a, IServiceB b){...}
}
public class DegenerateFoo: Foo
{
public DegenerateFoo(){..does nothing...}
}
public class FooFactory
{
readonly IContainer _container;
public void FooFactory(IContainer container){_container=container;}
public Foo GetAFoo(int type)
{
switch (type)
{
case 0:
return _container.Get<SimpleFoo>();
case 1:
return _container.Get<ComplexFoo>();
default:
//unknown case, return some kind of Foo that does nothing
return _container.get<DegenerateFoo>();
}
}
}
Your container, meanwhile, would have been separately configured somewhere else in the application's "Composition Root" to know how to resolve the object graphs (the following is pseudocode only)
container.RegisterTransient<IServiceA, ServiceAImplementation>();
container.RegisterSingleton<IServiceB, ServiceBImplementation>();
In this case we're configuring that any IServiceA injection is a new object instance each time it is requested; whereas IServiceB injections will be a single shared instance that the container takes care of creating once and doling out on request. Of course this is just an example of how you might configure these, ultimately you know best how you need to configure the lifetimes of these dependencies.
Hope you get the idea.

Ninject Contextual Binding at runtime depending on a specific value [duplicate]

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

Ways to setup a Ninject singleton

I have a class (MyFacade) that I injected parameter(s) with Ninject:
class MyFacade
{
IDemoInterface demo;
public MyFacade(IDemoInterface demo)
{
this.demo = demo;
}
public void MyMethod()
{
Console.WriteLine(demo.GetInfo());
}
}
Of course, I have to setup the Ninject to inject the appropiate implementation of my parameter (IDemoInterface)
I know, I can instantiate MyFacade object by doing kernel.Get<MyFacade>(); without setting anything else. Currently my facade doesn't have an interface (because it is my only implementation, maybe I will add its interface for standard proposes)
if I want to make this facade singlenton, I know two ways: create a empty constructor and pass a parameter by doing this kernel.Get<IDemoInterface>(); or by setup Ninject like: kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
The second one look a better approach, but do you know any other way to setup it in a singleton way?
When setting up your bindings, you need to bind your dependencies. It is always better to setup your dependencies in your bindings, as opposed to doing a kernel.Get<T>() in a constructor. You are using IOC, so leverage the framework you are using to do the injection for you.
In your second example binding, what you are missing is binding in your IDemoInterface. Your bindings should look like this:
//bind the dependency to the implementation.
kernel.Bind<IDemoInterface>().To<DemoInterface>();
//since you bound your dependency, ninject should now have
// all the dependencies required to instantiate your `MyFacade` object.
kernel.Bind<MyFacade>().To<MyFacade>().InSingletonScope();
If you do not want the container to manage the lifecycle of your singleton by using InSingletonScope(), but still wants it to get injected, I can think of 2 ways to go about it. Choose which one suits better to your needs. Consider the following ISingleton (name your interface) implementation:
public class ConcreteSingleton : ISingleton
{
private static readonly Lazy<ConcreteSingleton> _instance = new Lazy<ConcreteSingleton>(() => new ConcreteSingleton());
private ConcreteSingleton() { }
public static ConcreteSingleton Instance
{
get
{
return _instance.Value;
}
}
}
Alter the singleton class to have a GetInstance(...) method
In this method (my preferred approach), you won't be calling kernel.Inject(instance) each time, only for the first time the singleton is initialized. Adding the following method to your ConcreteSingleton class:
public static ConcreteSingleton GetInstance(IKernel kernelForInjection)
{
if (_instance.IsValueCreated == false)
{
kernelForInjection.Inject(_instance.Value);
}
return _instance.Value;
}
And using this binding:
kernel.Bind<ISingleton>().ToMethod(c => ConcreteSingleton.GetInstance(c.Kernel));
Will achieve the desired behavior of not having a public constructor but enabling your facade to be efficiently injected.
Perform injection each time the ISingleton instance is requested
If by any reason you are not allowed to modify your ConcreteSingleton: This approach will wrap the singleton creation in a provider to efficiently inject the instance only for the first time it is created. It is important to note that the provider itself must be registered as a singleton.
internal class ConcreteSingletonProvider : Provider<ISingleton>
{
public IKernel Kernel { get; set; }
//Just a wrapper
private readonly Lazy<ISingleton> _lazy = new Lazy<ISingleton>(() => ConcreteSingleton.Instance);
public ConcreteSingletonProvider(IKernel kernel)
{
Kernel = kernel;
}
protected override ISingleton CreateInstance(IContext context)
{
if (_lazy.IsValueCreated == false)
{
Kernel.Inject(ConcreteSingleton.Instance);
}
return _lazy.Value;
}
}
And your bindings should be like this:
kernel.Bind<ISingleton>().ToProvider<ConcreteSingletonProvider>();
kernel.Bind<ConcreteSingletonProvider>().ToSelf().InSingletonScope();
This gist has a complete working sample for the above approach.
Hope that helps!

Multiple implementations for one interface with DI

Right now I'm trying to teach myself the Dependency Injection pattern with the IOC-container from Autofac. I've come up with a very simple example, which is presented below. Although the example is simple, I fail to get it working properly.
Here are my classes/interfaces:
Two monsters, both implementing the IMonster interface:
interface IMonster
{
void IntroduceYourself();
}
class Vampire : IMonster
{
public delegate Vampire Factory(int age);
int mAge;
public Vampire(int age)
{
mAge = age;
}
public void IntroduceYourself()
{
Console.WriteLine("Hi, I'm a " + mAge + " years old vampire!");
}
}
class Zombie : IMonster
{
public delegate Zombie Factory(string name);
string mName;
public Zombie(string name)
{
mName = name;
}
public void IntroduceYourself()
{
Console.WriteLine("Hi, I'm " + mName + " the zombie!");
}
}
Then there's my graveyard:
interface ILocation
{
void PresentLocalCreeps();
}
class Graveyard : ILocation
{
Func<int, IMonster> mVampireFactory;
Func<string, IMonster> mZombieFactory;
public Graveyard(Func<int, IMonster> vampireFactory, Func<string, IMonster> zombieFactory)
{
mVampireFactory = vampireFactory;
mZombieFactory = zombieFactory;
}
public void PresentLocalCreeps()
{
var vampire = mVampireFactory.Invoke(300);
vampire.IntroduceYourself();
var zombie = mZombieFactory.Invoke("Rob");
zombie.IntroduceYourself();
}
}
And finally my main:
static void Main(string[] args)
{
// Setup Autofac
var builder = new ContainerBuilder();
builder.RegisterType<Graveyard>().As<ILocation>();
builder.RegisterType<Vampire>().As<IMonster>();
builder.RegisterType<Zombie>().As<IMonster>();
var container = builder.Build();
// It's midnight!
var location = container.Resolve<ILocation>();
location.PresentLocalCreeps();
// Waiting for dawn to break...
Console.ReadLine();
container.Dispose();
}
And this is my problem:
During runtime, Autofac throws an exception on this line:
var vampire = mVampireFactory.Invoke(300);
It seems that the mVampireFactory is actually trying to instantiate a zombie. Of course this won't work since the zombie's constructor won't take an int.
Is there a simple way to fix this?
Or did I get the way Autofac works completely wrong?
How would you solve this problem?
Your inversion of control container is not a factory per se. Your case is a perfect fit for the factory pattern.
Create a new abstract factory which is used to create your monsters:
public interface IMonsterFactory
{
Zombie CreateZombie(string name);
Vampire CreateVampire(int age);
}
And then register its implementation in Autofac.
Finally use the factory in your class:
class Graveyard : ILocation
{
IMonsterFactory _monsterFactory;
public Graveyard(IMonsterFactory factory)
{
_monsterFactory = factory;
}
public void PresentLocalCreeps()
{
var vampire = _monsterFactory.CreateVampire(300);
vampire.IntroduceYourself();
var zombie = _monsterFactory.CreateZombie("Rob");
zombie.IntroduceYourself();
}
}
You can of course use specific monster factories too if you want. None the less, using interfaces will imho make your code a lot more readable.
Update
But how would I implement the factory? On the one hand the factory should not use the IOC container to create the monsters, because that's considered evil (degrades the DI pattern to the service locator anti-pattern).
I'm getting so tired of hearing that SL is an anti-pattern. It's not. As with all patterns, if you use it incorrectly it will give you a disadvantage. That applies for ALL patterns. http://blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern/
But in this case I don't see why you can't create the implementations directly in your factory? That's what the factory is for:
public class PreferZombiesMonsterFactory : IMonsterFactory
{
public Zombie CreateZombie(string name)
{
return new SuperAwesomeZombie(name);
}
public Vampire CreateVampire(int age)
{
return new BooringVampire(age);
}
}
It's not more complicated than that.
On the other hand the factory should not create the monsters itself, because that would bypass the IOC-container and tightly couple the factory and the monsters. Or am I on the wrong track again? ;-)
It doesn't matter that the factory is tighly coupled to the monster implementations. Because that's the purpose of the factory: To abstract away the object creation, so that nothing else in your code is aware of the concretes.
You could create SuperDeluxeMonsterFactory, MonstersForCheapNonPayingUsersFactory etc. All other code in your application wouldn't be aware of that you are using different monsters (by using different factories).
Each time you have to change concretes you either switch factory or you just modify the existing factory. No other code will be affected as long as your monster implementations do not violate Liskovs Substitution Principle.
Factory vs IoC container
So what's the difference between a factory and a IoC container then? The IoC is great at resolving dependencies for your classes and maintain the lifetimes (the container can for instance dispose all disposables automatically when a HTTP request ends)..
The factory on the other hand excels at creating objects for you. It does that and nothing else.
Summary
So if you somewhere in your code need to get a specific type of an implementation you typically should use a factory. The factory itself CAN use the IoC as a service locator internally (to resolve dependencies). That is OK since it's a implementation detail in the factory which do not affect anything else in your application.
Use the IoC container (through dependency injection) if you want to resolve a service (and do not care which implementation you get, or if you get a previously created instance).
Multiple implementations with Func<>
I am using the same logic as before, interface IMovement, three implementations, Cat, Dog, and Human.
I add an Enum, the MovementEnum. Because this approach uses DI to register a Func<> which returns and interface implementation depending on a specific key, you can use another type to represent the Enum.
public enum MovementEnum
{
Cat = 1,
Dog = 2,
Human = 3
}
public class Cat : IMovement
{
public string Walk()
{
return “Im a Cat, walking!”;
}
}
public class Dog : IMovement
{
public string Walk()
{
return “Im a Dog, walking!”;
}
}
public class Human : IMovement
{
public string Walk()
{
return “Im a human, walking!”;
}
}
To register first, you need to register the classes like this.
builder.Services.AddScoped<Dog>();
builder.Services.AddScoped<Human>();
builder.Services.AddScoped<Cat>();
And then register the Func<> with the Enum and the Interface. To choose between each class, I use a switch with the Enum.
builder.Services.AddTransient<Func<MovementEnum, IMovement>>(movementProvider => key =>
{
switch (key)
{
case MovimentEnum.Cat:
return movementProvider.GetService<Cat>();
case MovimentEnum.Dog:
return movementProvider.GetService<Dog>();
case MovimentEnum.Human:
return movementProvider.GetService<Human>();
default:
return null;
}
});
To use this in your controller, inject the Func<> like this.
[ApiController]
[Route("[controller]/[action]")]
public class MovementController : ControllerBase
{
private readonly IMovement _dogMovement;
private readonly IMovement _catMovement;
private readonly IMovement _humanMovement;
public MovementController(Func<MovementEnum, IMovement> serviceResolver)
{
_dogMovement = serviceResolver(MovementEnum.Dog);
_catMovement = serviceResolver(MovementEnum.Cat);
_humanMovement = serviceResolver(MovementEnum.Human);
}
[HttpGet]
public string GetCat()
{
return _catMovement.Walk();
}
[HttpGet]
public string GetDog()
{
return _dogMovement.Walk();
}
[HttpGet]
public string GetHuman()
{
return _humanMovement.Walk();
}
}

How do I apply dependency injection to an abstract factory

I've just finished Mark Seemann's book Dependency Injection in .NET and I'm now trying to refactor some legacy code. (I am not, at this stage, relying on any particular DI container, rather just trying to move all the dependencies to one place).
I'm looking at the following factory class which determines the ArchiveType by reading the first few bytes of the archive with archiveReader.GetArchiveType() and then returns an instance of an ArchiveRestorer based on the ArchiveType enum.
public class ArchiveRestorerFactory : IArchiveRestorerFactory
{
public ArchiveRestorer Create(ArchiveReader archiveReader)
{
ArchiveType type = archiveReader.GetArchiveType();
switch (type)
{
case ArchiveType.CurrentData:
return new CurrentDataArchiveRestorer(archiveReader);
break;
case ArchiveType.HistoricalData:
return new HistoricalDataArchiveRestorer(archiveReader);
break;
case ArchiveType.AuditTrail:
return new AuditTrailArchiveRestorer(archiveReader);
break;
default:
throw new Exception("ArchiveRestorerFactory error: Unknown value for ArchiveType.");
}
}
}
How do I refactor this so that the class does not depend on the concrete types CurrentDataArchiveRestorer, HistoricalDataArchiveRestorer and AuditTrailArchiveRestorer?
Should I move the three concrete restorers into the factory's constructor?
public ArchiveRestorer Create(ArchiveReader archiveReader,
ArchiveRestorer currentDataArchiveRestorer,
ArchiveRestorer historicalDataArchiveRestorer,
ArchiveRestorer auditTrailDataArchiveRestorer)
{
// guard clauses...
// assign to readonly fields
}
That seems to be the approach suggested here, but then it will instantiate all three restorers when only one is needed? What if I had 20 different possible concrete implementations instead?
I feel like I should be implementing a concrete factory for each type of restorer and returning that instead but then I would just be replacing one new with another.
What is the best way to refactor this?
The way I'd do this, given the code you've already got, would be to create a factory for each of these objects which has a Create() method.
I'd have an interface for these factories also and have them inherit from a general factory interface.
You can then use the interfaces as a point for injection into your constructor.
Which would be called similar to this:
case ArchiveType.CurrentData:
return _currentDateArchiveRestorerFactory.Create(archiveReader);
break;
Alternatively, it might be better to have a single factory that creates an instance of a given type. Since all of these objects are restorers you could just create the instance based on the enum rather than a switch.
_restorerFactory.Create(ArchiveType.CurrentData);
Why not make the ArchiveReader responsible for creating the appropriate ArchiveRestorer? Then the first iteration of the code would look like this:
public class ArchiveRestorerFactory : IArchiveRestorerFactory
{
public ArchiveRestorer Create(ArchiveReader archiveReader)
{
ArchiveRestorer restorer = archiveReader.GetArchiveRestorer();
return restorer;
}
}
By then, it should be pretty obvious that the factory is redundant, so in the second iteration of the code you can throw it away let the consumers invoke the ArchiveReader directly.
Make one interface with one method with returns type of that interface and let three archiver classes implement that interface and then in the create method the parameter type would be just the interface and it will return the required object by calling the method of interface you just created. So you don't need concrete type in create method.
interface ILogger
{
void Log(string data);
}
class Logger : ILogger
{
.
.
.
}
At this point, you use an intermediate factory object to return the logger to be used within the component:
class MyComponent
{
void DoSomeWork()
{
// Get an instance of the logger
ILogger logger = Helpers.GetLogger();
// Get data to log
string data = GetData();
// Log
logger.Log(data);
}
}
class Helpers
{
public static ILogger GetLogger()
{
// Here, use any sophisticated logic you like
// to determine the right logger to instantiate.
ILogger logger = null;
if (UseDatabaseLogger)
{
logger = new DatabaseLogger();
}
else
{
logger = new FileLogger();
}
return logger;
}
}
class FileLogger : ILogger
{
.
.
.
}
class DatabaseLogger : ILogger
{
.
.
.
}
I would solve this problem by agreeing on a naming convention and utilizing Unity's ability to name registrations. Example of this here: https://dannyvanderkraan.wordpress.com/2015/06/29/real-world-example-of-dependency-injection-based-on-run-time-values/

Categories

Resources