Implement abstract factory pattern for different exception providers in c# - c#

I am planning to solve a particular problem by using abstract factory pattern. I was successful in implementing factory pattern but not able to extend factory pattern to Abstract factory
I have two different places where exception details can be stored
File system
Database
I have used factory pattern to abstract away object creation details from client
Interface
public interface ILogException
{
void LogException();
}
FileSystemLogger
public class FileExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("File Exception Logger");
}
}
DBSystemLogger
public class DBExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("DB Exception Logger");
}
}
Factory Implementation
public class ExceptionFactory
{
const int i = 1;
public static ILogException GetFactory()
{
if (i == 1)
{
return new FileExceptionLogger();
}
else if (i == 2)
{
return new DBExceptionLogger();
}
else
{
return new ServiceExcetionLogger();
}
}
}
I know this is not the best of implementation but i plan to change it.
Now FileSystemLogger and DatabaseLogger are in itself a factory, I want to group following implementation under FileSystemLogger and DatabaseLogger so that the client can have FileSystemLoggerFactory and DatabaseLoggerFactory
FileSystemLogger
FlatFileSystemLogger
XMLFileSystemLogger
DatabaseLogger
SQLSERVERLogger
OracleLogger
How should i proceed with defining FileSystemLoggerFactory and DatabaseLoggerFactory?

If you want, you could make the factory method a generic one:
public static ILogException GetFactory<T>() where T : ILogException
{
return (ILogException)Activator.CreateInstance<T>();
}
Call it like:
ILogException logger = ExceptionFactory.GetFactory<FileExceptionLogger>();
You also might want to take a look at a dependency injection library like NInject, Unity, etc. These can simplify this kind of problem, allowing you to centralize the logic for which interfaces get bound to which implementations. (Ie, you can bind an implementation in the application or request scope.)

Related

c# decorator pattern multiple properties wrapping multiple times [duplicate]

I just started to learn Decorator Design Pattern, unfortunately i had to go through various refrences to understand the Decorator pattern in a better manner which led me in great confusion. so, as far as my understanding is concern, i believe this is a decorator pattern
interface IComponent
{
void Operation();
}
class Component : IComponent
{
public void Operation()
{
Console.WriteLine("I am walking ");
}
}
class DecoratorA : IComponent
{
IComponent component;
public DecoratorA(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("in the rain");
}
}
class DecoratorB : IComponent
{
IComponent component;
public DecoratorB(IComponent c)
{
component = c;
}
public void Operation()
{
component.Operation();
Console.WriteLine("with an umbrella");
}
}
class Client
{
static void Main()
{
IComponent component = new Component();
component.Operation();
DecoratorA decoratorA = new DecoratorA(new Component());
component.Operation();
DecoratorB decoratorB = new DecoratorB(new Component());
component.Operation();
Console.Read();
}
}
But can the below code also be Decorator Pattern?
class Photo
{
public void Draw()
{
Console.WriteLine("draw a photo");
}
}
class BorderedPhoto : Photo
{
public void drawBorder()
{
Console.WriteLine("draw a border photo");
}
}
class FramePhoto : BorderedPhoto
{
public void frame()
{
Console.WriteLine("frame the photo");
}
}
class Client
{
static void Main()
{
Photo p = new Photo();
p.Draw();
BorderedPhoto b = new BorderedPhoto();
b.Draw();
b.drawBorder();
FramePhoto f = new FramePhoto();
f.Draw();
f.drawBorder();
f.frame();
}
}
My Understanding
From the second example given by me, we can call all the three methods, but from the first example i wont be able to get access to all the three methods by creating a single object.
It should be a comment, but I have too many words.
For example, you have an object and interface, like Repository : IRepository.
public interface IRepository
{
void SaveStuff();
}
public class Repository : IRepository
{
public void SaveStuff()
{
// save stuff
}
}
and client, which probably was written by someone else
class RepoClient
{
public void DoSomething(IRepository repo)
{
//...
repo.SaveStuff();
}
}
And once you decided, that ALL calls to repository should be logged. But you have a problem: the Repository class is from an external library and you don't want to change that code. So you need to extend the Repository's behavior that you use. You write RepositoryLogDecorator : IRepository, and inside on each method do the logging, like
public class RepositoryLogDecorator : IRepository
{
public IRepository _inner;
public RepositoryLogDecorator(IRepository inner)
{
_inner = inner;
}
public void SaveStuff()
{
// log enter to method
try
{
_inner.SaveStuff();
}
catch(Exception ex)
{
// log exception
}
// log exit to method
}
}
So, before you could use client as
var client = new RepoClient();
client.DoSomething(new Repository());
but now you can use
var client = new RepoClient();
client.DoSomething(new RepositoryLogDecorator(new Repository()));
Note, that this is a very simple example. In real projects, where object created primary with DI container, you will be able to use decorator by changing some config.
So, decorator is used to extend functionality of object without changing object or client.
Another benefit of decorator: your decorator does not depend on Repository implementation. Only depends from an interface IRepository. Why this is an advantage? If somehow you decide to write you own implementation of IRepository
public class MyAwesomeRepository : IRepository
{
public void SaveStuff()
{
// save stuff, but AWESOME!
}
}
you will be able to automatically decorate this with decorator, which already exist
var client = new RepoClient();
client.DoSomethig(new RepositoryLogDecorator(new MyAwesomeRepository()));
Want to see example from real software? (just as sample, code is ugly, I know) => go here
There is this PatternCraft series on Youtube that explains Design Patterns with Starcraft, you should check the video about Decorators here.
In the video above the author gives an example with a Marine and WeaponUpgrade.
In the game you will have a Marine and then you can upgrade its weapon:
marine = new WeaponUpgrade(marine);
Note that you still have a marine there, it is not a new unit, it is the same unit with things that modifies its attributes.
public class MarineWeaponUpgrade : IMarine
{
private IMarine marine;
public MarineWeaponUpgrade(IMarine marine)
{
this.marine = marine;
}
public int Damage
{
get { return this.marine.Damage + 1; } // here
set { this.marine.Damage = value; }
}
}
You do that by creating a class that implements the same interface as your unit and access your unit properties to modify values.
There is a Kata on CodeWars challenging you to complete the Weapon and Armor decorators for a marine.
Per GOF page Decorator desing pattern:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
In your second example you are using inheritance to extend behaviour of a class, I believe this is technically not a Decorator design pattern.
The decorator pattern allows you to add a specific behavior to an individual object of a given type without affecting other instances of that same type.
In your second example, which is normal inheritance, all instances of the class inherit the modified behavior.
The second example is not a decorate pattern, since an essential ingredient to decorator pattern is that the object accepts one of its kind and possibly enhance it.
An instances of this in the first example is
public DecoratorA(IComponent c)
{
component = c;
}
Also, the goal of the decorator pattern is to create "one" object, then decorate it by passing it through different filters or decorators.
Hence the line
DecoratorA decoratorA = new DecoratorA(new Component());
Should be
DecoratorA decoratorA = new DecoratorA(component );

How to implement the client code for an Abstract Factory?

I'm having a hard time understanding the implementation of client code with the factory method. I understand the overall use of Abstract Factories but my issue is I want the Factory to figure out the correct object to instantiate at runtime, but every implementation I see involves passing an enum or some other value to the constructor.
This is my current design
using System;
namespace FactoryTest.Jobs
{
public class ExchangeProvider1 : IExchangeProvider
{
public void Buy()
{
Console.WriteLine("Buying on Exchange1!");
}
}
}
using System;
namespace FactoryTest.Jobs
{
public class ExchangeProvider2 : IExchangeProvider
{
public void Buy()
{
Console.WriteLine("Buying on Exchange2");
}
}
}
public interface IExchangeFactory
{
}
public interface IExchangeProvider
{
void Buy();
}
public class ExchangeFactory : IExchangeFactory
{
public static IExchangeProvider CreateExchange<T>() where T : IExchangeProvider
{
return Activator.CreateInstance<T>();
}
public static IExchangeProvider CreateExchange(string exchangeName)
{
return (IExchangeProvider) Activator.CreateInstance<IExchangeProvider>();
}
}
The problem is that I'm trying to have the factory build the correct provider based on details the user fills out in a web form. On hitting create I want to the factory to instantiate the correct provider and run the correct logic. But with this implementation Im forced to do something like
var provider = ExchangeFactory.CreateExchange<Exchange1>();
When I really want to be able to get the Exchange Type from the user at runtime from the web form and pass it to the factory
//Receive IExchangeType from user submitting web form
var provider = ExchangeFactory.CreateExchange<IExchangeType>();
Is this possible? I'm wondering (or the correct solution), or if I'm on the right track but am definitely hindered by a gap in knowledge.
Generally you shouldn't tell the factory which concrete type to create. You should give it the information it needs to make that decision by itself. Now, I'm not saying that this can't be a 1:1 relationship, just that the caller shouldn't tell the factory to make a specific concrete type.
Imagine you have a Student object with a Grade property. You also have a factory which produces ISchool, and concrete implementations ElementarySchool, MiddleSchool, and HighSchool. Now you could have 3 methods: CreateElementarySchool(), CreateMiddleSchool() and CreateHighSchool(), but then the caller has to decide which one it wants.
A better approach is to have a method which uses some information to create the the school. For example: CreateSchoolForGrade(grade). Internally, the factory will have logic which works out which concrete type matches the grade.
In your case, if you have a set of 2 types to choose from on a webform, you could accept the type (let's say the options are Empire or Rebels). You could have an enum:
public enum Faction
{
Empire,
Rebels
}
and then a factory method:
public IFaction CreateFaction(Faction faction)
{
switch (faction)
{
case Faction.Empire:
return new EmpireFaction();
case Faction.Rebels:
return new RebelsFaction();
default:
throw new NotImplementedException();
}
}
Now, imagine that you retire EmpireFaction, replacing it with EmpireFactionV2. You only need to modify your factory, and the caller doesn't care:
public IFaction CreateFaction(Faction faction)
{
switch (faction)
{
case Faction.Empire:
return new EmpireFactionV2();
case Faction.Rebels:
return new RebelsFaction();
default:
throw new NotImplementedException();
}
}
As noted in the comments the other answer is a violation of O/C Principle (and a bit of Single Responsibility Principle (SRP)) of SOLID.
A more dynamic approach is to inject all instances of the exchange and pick the correct one. Bellow example is based on the class name (not full-qualifed name, but that cane easily be changed).
public interface IExchange
{
void Buy();
}
public class Exchange1 : IExchange
{
public void Buy() => Console.WriteLine("Buying on Exchange1");
}
public class Exchange2 : IExchange
{
public void Buy() => Console.WriteLine("Buying on Exchange2");
}
public interface IExchangeFactory
{
IExchange CreateExchange(string exchangeName);
}
// All exchanges are instantiated and injected
public class ExchangeFactory : IExchangeFactory
{
private readonly IEnumerable<IExchange> exchanges;
public ExchangeFactory(IEnumerable<IExchange> exchanges)
{
this.exchanges = exchanges ?? throw new ArgumentNullException(nameof(exchanges));
}
public IExchange CreateExchange(string exchangeName)
{
var exchange = exchanges.FirstOrDefault(e => e.GetType().Name == exchangeName);
if(exchange==null)
throw new ArgumentException($"No Exchange found for '{exchangeName}'.");
return exchange;
}
}
It can easily be extended by registering further implementation with the DI, w/o any code changes on the factory
service.AddScoped<IExchange, Exchange3>();
service.AddScoped<IExchange, Exchange4>();
In high performance scenarios (a couple of 1000 requests per second) where the injected services are scoped/transient or the memory/GC pressure on creating this extra instances is high, you can use the provider pattern to only create the exchange that's really required:
public interface IExchangeProvider
{
IExchange CreateExchange(string exchangeName);
}
public class Exchange1Provider : IExchangeProvider
{
public IExchange CreateExchange(string exchangeName)
{
if(exchangeName == nameof(Exchange1))
{
// new it, resolve it from DI, use activation whatever suits your need
return new Exchange1();
}
return null;
}
}
public class Exchange2Provider : IExchangeProvider
{
public IExchange CreateExchange(string exchangeName)
{
if (exchangeName == nameof(Exchange2))
{
// new it, resolve it from DI, use activation whatever suits your need
return new Exchange1();
}
return null;
}
}
public class LazyExchangeFactory : IExchangeFactory
{
private readonly IEnumerable<IExchangeProvider> exchangeProviders;
public LazyExchangeFactory(IEnumerable<IExchangeProvider> exchangeProviders)
{
this.exchangeProviders = exchangeProviders ?? throw new ArgumentNullException(nameof(exchangeProviders));
}
public IExchange CreateExchange(string exchangeName)
{
// This approach is lazy. The providers could be singletons etc. (avoids allocations)
// and new instance will only be created if the parameters are matching
foreach (IExchangeProvider provider in exchangeProviders)
{
IExchange exchange = provider.CreateExchange(exchangeName);
// if the provider couldn't find a matcing exchange, try next provider
if (exchange != null)
{
return exchange;
}
}
throw new ArgumentException($"No Exchange found for '{exchangeName}'.");
}
}
This approach is similar to the first, with the exception that you are extending it by adding new IExchangeProviders. Both approaches allow you to extend the exchanges w/o a change on ExchangeFactory (or in high performance scenarios LazyExchangeFactory)

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

Factory Interface Create Method with object Argument

I have a question about creating a factory interface with a create method that can cater for accepting different argument types depending on the implementation.
To give you a bit more background, I am using dependency in injection in a project, and require stateful objects to be generated at runtime - therefore I am injecting factories (rather than the objects themselves) to create these stateful objects. The problem I have come across is that, for some interfaces, the concrete implementations simply cannot have the same constructor argument types, and so the factories that create an instance of these interfaces require almost 'dynamic' arguments to be passed to the create method.
I have been going over this for a couple of days, and the following is the best solution I could come up with (namely, passing an object to the factory create method and casting it in the concrete implementation of the factory). I am really looking for feedback from people who have come across this scenario before, to hear what they came up with, and whether or not the solution I am proposing below is acceptable.
Apologies if this is missing any information, and many thanks in advance!
//
// Types...
//
interface IDataStore
{
List<string> GetItems();
}
public class XmlDataStore : IDataStore
{
public XmlDataStore(XmlDocument xmlDoc)
{
// Initialise from XML Document...
}
public List<string> GetItems()
{
// Get Items from XML Doc...
}
}
public class SQLDataStore : IDataStore
{
public SQLDataStore(SqlConnection conn)
{
// Initialise from SqlConnection...
}
public List<string> GetItems()
{
// Get Items from Database Doc...
}
}
//
// Factories...
//
interface IDataStoreFactory
{
IDataStore Create(object obj);
}
class XmlDataStoreFactory : IDataStore
{
IDataStore Create(object obj)
{
// Cast to XmlDocument
return new XmlDataStore((XmlDocument)obj);
}
}
class SQLDataStoreFactory : IDataStore
{
IDataStore Create(object obj)
{
// Cast to SqlConnection
return new SQLDataStore((SqlConnection)obj);
}
}
Based on this comment you need one factory which produces several types of IDataStore. You could accomplish by creating a open generic factory method in the singleton factory instance.
interface IDataStore<TStoreType>
{
void SetBaseType(TStoreType obj);
List<string> GetItems();
}
interface IDataStoreFactory
{
IDataStore<TStoreType> Create<TStoreType>(TStoreType obj)
}
class DataStoreFactory : IDataStoreFactory
{
public IDataStore<TStoreType> Create<TStoreType>(TStoreType obj)
{
if (obj.GetType() == typeof(SqlConnection))
{
var store = new SQLDataStore((SqlConnection)(Object)obj);
return (IDataStore<TStoreType>)store;
}
if (obj.GetType() == typeof(XmlDocument))
{ //... and so on }
}
}
class SQLDataStore : IDataStore<SqlConnection>
{
private readonly SqlConnection connection;
public SQLDataStore(SqlConnection connection)
{
this.connection = connection;
}
public List<string> GetItems() { return new List<string>(); }
}
You can use this factory like this:
var factory = new DataStoreFactory();
var sqlDatastore = factory.Create(new SqlConnection());
var xmlDatastore = factory.Create(new XmlDocument());
Your datastore factory would become a lot less complex if you would use a DI container. You could inject the container in the factory and retrieve your instances directly from the container, which would typically build your instances from bottom to top, including there own dependencies, lifetime management and so on. But be very carefull with this approach, it is the first step to using the service locator pattern which is an anti pattern
Not really sure if I understand your question correctly but to me it sounds a little odd to have factory instances which you use for the creation of your statefull objects as you call them.
To directly answer your question: generics are your solution. You rinterface becomes an open generic abstraction:
interface IDataStore<TStoreType>
{
List<string> GetItems();
}
interface IDataStoreFactory<TStoreType>
{
IDataStore<TStoreType> Create(TStoreType obj);
}
and your factory classes will look like this:
class XmlDataStoreFactory : IDataStoreFactory<XmlDocument>
{
IDataStore<XmlDocument> Create(XmlDocument document)
{
return new XmlDataStore(document);
}
}
class SQLDataStoreFactory : IDataStoreFactory<SqlConnection>
{
IDataStore<SqlConnection> Create(SqlConnection connection)
{
return new SQLDataStore(connection);
}
}
This will work, but from the examples you give I got the impression you're using factories throughout your codebase. Maybe I'm wrong on this point, but look at your design and minimize the number of factories. Needing a factory means mixing data with behaviour and this will always, eventually, get you into trouble.
For example, let's say you have some kind of service which adds the current user to a audit log when he logs in. This service offcourse needs the current user which is a typical example of runtime data (or contextual data). But instead of:
public class AuditLogService
{
public void AddApplicationSignIn(User user)
{
//... add user to some log
}
}
I know this is not a good example because you actually wouldn't need a factory for this class, but with the next code example you'll get the point:
public class AuditLogService
{
private readonly IUserContext userContext;
public AuditLogService(IUserContext userContext)
{
this.userContext = userContext;
}
public void AddApplicationSignIn()
{
var user = this.userContext.GetCurrentUser();
//... add user to some log
}
}
So by splitting data from behaviour you rule out the need for factories. And admitted there are cases where a factory is the best solution. I do think an IDataStore is not something you need a factory for.
For a good blog on splitting data and behaviour read here

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

Categories

Resources