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/
Related
Here's what I want to be able to do in my application:
public void BusinessLogic (IFactory workerFactory)
{
string specificObjectType = ... // not known in advance
IWorkerObject workerObject = workerFactory.CreateByType(specificObjectType);
workerObject.DoActualWork();
}
In other words, I want an actual Factory that generates various kinds of IWorkerObject implementations on demand, and I want that Factory to be injectable. And ideally that Factory itself would be able to get those implementation object from the service container too:
public class WorkerFactory
{
public WorkerFactory (IServiceContainer ...)
{ ... }
public IWorker CreateByType (string type)
{
return ...; // a thing that can be provided by the service container
}
}
The reason is that I want to be able to create (for example) a SteelWorker or a CopperWorker or an AluminumWorker depending on what type of metal is represented by that specificObjectType value. This seems like a normal Factory pattern to me, but I don't know how to make a class injectable and give it parameters that aren't resolved until creation time.
If this can be done with Unity, great. If I need to work around it or use another DI framework, that is okay too.
You could inject an IServiceScopeFactory into the IFactory
using (var scope = _serviceScopeFactory.CreateScope())
{
if(criteriaA)
{
return scope.ServiceProvider.GetRequiredService<WorkerA>();
}
}
I am trying to get IoC working with Unity in C# with the idea of a passing a wrapper/composite class into the children.
The top level class that composes multiple classes provides some common functionality that the composed classes require access to.
To illustrate:
// The top composite class
public class Context : IContext {
public ISomething SomethingProcessor { get; }
public IAnother AnotherProcessor { get; }
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.AnotherProcessor = processor;
}
// A function that individual classes need access to, which itself calls one of the children.
public string GetCommonData() {
return this.AnotherProcessor.GetMyData();
}
}
public class Something : ISomething {
private _wrapper;
public Something(IContext context) {
this._wrapper = context;
}
// This class has no knowledge of IAnother, and requests data from the master/top class, which knows where to look for whatever.
public void Do() {
Console.WriteLine(_wrapper.GetCommonData());
}
}
public class Another : IAnother {
public string GetMyData() {
return "Foo";
}
}
If you didn't use IoC, it's easy, as the constructor for the Context class becomes:
public Context() {
this.SomethingProcessor = new Processor(this);
this.AnotherProcessor = new Another();
}
But when you're using IoC, the idea of "this" doesn't exist yet because it is yet to be constructed by the injector. Instead what you have a is a circular dependency.
container.RegisterType<ISomething, Something>();
container.RegisterType<IAnother, Another>();
container.RegisterType<IContext, Context>();
var cxt = container.Resolve<IContext>(); // StackOverflowException
The above example has been greatly simplified to illustrate the concept. I'm struggling to find the "best practice" way of dealing with this kind of structure to enable IOC.
Factory pattern is a way construct an object based on other dependencies or logical choices.
Factory Method: "Define an interface for creating an object, but let
the classes which implement the interface decide which class to
instantiate. The Factory method lets a class defer instantiation to
subclasses" (c) GoF.
Lots of construction.. hence the name Factory Pattern
A crude code sample that could be used with DI
public class ContextFactory : IContextFactory {
_anotherProcessor = anotherProcessor;
public ContextFactory(IAnotherProcessor anotherProcessor) {
//you can leverage DI here to get dependancies
}
public IContext Create(){
Context factoryCreatedContext = new Context();
factoryCreatedContext.SomethingProcessor = new SomethingProcessor(factoryCreatedContext )
factoryCreatedContext.AnotherProcessor = _anotherProcessor;
//You can even decide here to use other implementation based on some dependencies. Useful for things like feature flags.. etc.
return context;
}
}
You can get away with this, maybe? - but there is still the cyclic reference issue here and I would never commit this kind of code.
The problem here you need to concentrate on Inversion Of Control of that GetCommonData
Your SomethingProcessor should not rely on methods in another class. This is where In Inheritance could be used but Inheritance can become very complicated very quickly.
The best way forward is to Identify the ONE thing that is needed by both or many other places and break that out into a new Dependency. That is how you Invert Control.
TIP:
Don't overdo Interfaces- Use Interfaces where you think you will be working with Polymorphism, such as a collection of different objects that must promise you they have implemented a specific method/property. Otherwise you are over using Interfaces and increasing complexity. DI doesn't have to use Interfaces it can be a concrete implementation. Interfaces on Repositories are a good use since you can switch Databases out easily but Interfaces a factory like this is not really needed.
I don't know the name of this pattern, or even if it is a bad or good practice, but you can solve your problem of "double-binding" by creating a method to bind the "IContext", instead of doing it in the constructor.
For instance,
1) ISomething has a void BindContext(IContext context) method
2) You implement it as such :
class Something : ISomething
{
IContext _wrapper;
// ... nothing in constructor
public void BindContext(IContext context)
{
_wrapper = context;
}
}
3) Remove the IContext dependency injection in Something constructor.
And you call it from the context constructor :
public Context(ISomething something, IAnother another) {
this.SomethingProcessor = something;
this.SomethingProcessor.BindContext(this);
// same for IAnother
}
And you do the same for IAnother. You could even extract some common interface "IBindContext" to make things a beat more "DRY" (Don't Repeat yourself) and make IAnother and ISomething inherit from it.
Not tested, and again : not sure it's the best way to do such dependency design. I'll be glad if there is another answer which gives a state-of-the-art insight about this.
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.
I have the IRespository registered twice (with names) in the following code:
// Setup the Client Repository
IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Client", new InjectionConstructor(typeof(ClientEntities)));
// Setup the Customer Repository
IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor());
IOC.Container.RegisterType<IRepository, GenericRepository>
("Customer", new InjectionConstructor(typeof(CustomerEntities)));
IOC.Container.RegisterType<IClientModel, ClientModel>();
IOC.Container.RegisterType<ICustomerModel, CustomerModel>();
But then when I want to resolve this (to use the IRepository) I have to do a manual resolve like this:
public ClientModel(IUnityContainer container)
{
this.dataAccess = container.Resolve<IRepository>(Client);
.....
}
What I would like to do is to have it resolved in the constructor (just like IUnityContainer). I need some way to say which named type to resolve to.
Something like this: (NOTE: Not real code)
public ClientModel([NamedDependancy("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
Is there a way to make my fake code work?
You can configure dependencies with or without names in the API, attributes, or via the config file. You didn't mention XML above, so I'll assume you're using the API.
To tell the container to resolve a named dependency, you'll need to use an InjectionParameter object. For your ClientModel example, do this:
container.RegisterType<IClientModel, ClientModel>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client"
)
);
This tells the container "When resolving ClientModel, call the constructor that takes a single IRepository parameter. When resolving that parameter, resolve with the name 'Client' in addition to the type."
If you wanted to use attributes, your example almost works, you just need to change the attribute name:
public ClientModel([Dependency("Client")] IRepository dataAccess)
{
this.dataAccess = dataAccess;
.....
}
This is a very late response but the question still shows up in Google.
So anyways, 5 years later...
I have a pretty simple approach. Usually when you need to use "named dependency" it's because you're trying to implement some kind of strategy pattern. In that case, I simply create a level of indirection between Unity and the rest of my code called the StrategyResolver to not be directly depending on Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Usage:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Registration:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Now, the nice thing about this is that I will never have to touch the StrategyResolver ever again when adding new strategies in the future.
It's very simple. Very clean and I kept the dependency on Unity to a strict minimum. The only time I would have touch the StrategyResolver is if I decide to change container technology which is very unlikely to happen.
Hope this helps!
Edit: I don't really like the accepted answer because when you use the Dependency attribute in your service's constructor you actually have a hard dependency on Unity. The Dependency attribute is part of the Unity library. At that point you might as well pass an IUnityContainer dependency everywhere.
I prefer having my service classes depend on objects that I completely own instead of having a hard dependency on an external library all over the place. Also using Dependency attribute makes the constructors signatures less clean and simple.
Furthermore, this technique allows to resolve named dependencies at runtime without having to hardcode the named dependencies in the constructor, in the application configuration file or use InjectionParameter which are all methods that require to know what named dependency to use at design time.
Edit (2016-09-19):
For those that might wonder, the container will know to pass itself when you are requesting IUnityContainer as dependency, as shown in the StrategyResolver constructor signature.
Edit (2018-10-20):
Here's another way, simply using a factory:
public class SomeStrategyFactory : ISomeStrategyFactory
{
private IStrategy _stratA;
private IStrategy _stratB;
public SomeFactory(IStrategyA stratA, IStrategyB stratB)
{
_stratA = stratA;
_stratB = stratB;
}
public IStrategy GetStrategy(string namedStrategy){
if (namedStrategy == "A") return _stratA;
if (namedStrategy == "B") return _stratB;
}
}
public interface IStrategy {
void Execute();
}
public interface IStrategyA : IStrategy {}
public interface IStrategyB : IStrategy {}
public class StrategyA : IStrategyA {
public void Execute(){}
}
public class StrategyB : IStrategyB {
public void Execute() {}
}
Usage:
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
Registration:
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
This 2nd suggestion is the same thing but using the factory design pattern.
Hope this helps!
You should be able to use ParameterOverrides
var repository = IOC.Container.Resolve<IRepository>("Client");
var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } );
edit:
I'm not sure why you're passing around the UnityContainer - personally, we inject our dependencies into the constructor themselves (which is "normal" from what I've seen). But regardless, you can specify a name in your RegisterType and Resolve methods.
IOC.Container.RegisterType<IRepository, GenericRepository>("Client");
IOC.Container.Resolve<IRepository>("Client");
and it will give you the type you registered for that name.
Don't do this - just create a class ClientRepository : GenericRepository { } and utilise the Type system.
I have a requirement to create some objects that implement a given interface, where the type of concrete implementation being created is based on an Enum value.
I run into trouble when the different concrete implementations require different parameters at runtime.
This example (C#) is fine:
public enum ProductCategory
{
Modem,
Keyboard,
Monitor
}
public class SerialNumberValidatorFactory()
{
public ISerialNumberValidator CreateValidator(ProductCategory productCategory)
{
switch (productCategory)
{
case ProductCategory.Modem:
return new ModemSerialNumberValidator();
case ProductCategory.Keyboard:
return new KeyboardSerialNumberValidator();
case ProductCategory.Monitor:
return new MonitorSerialNumberValidator();
default:
throw new ArgumentException("productType", string.Format("Product category not supported for serial number validation: {0}", productCategory))
}
}
}
However, what happens if the concrete implementations have different constructor arguments? I can't pass in all the values to the SerialNumberValidatorFactory.CreateValidator() method, so how do I proceed?
I've heard the Abstract Factory pattern is supposed to solve this, but I'm not sure how to implement it properly.
You can always create a Settings container to pass to the CreateValidator method. Start with a base IValidatorSettings, then create IModemSerialNumberValidatorSettings etc, your CreateValidator could then take ProductType and IValidatorSettings arguments.
Your concrete classes for the validators would then take their IXXXValidatorSettings interface as the sole constructor argument.
Further to this you could then create an IValidatorSettings factory.
I think abstract factory is a factory that creates a factory to handle a given set of types - not sure if it would apply in your scenario.
What you are using is a Factory Method pattern, what you should use is an Abstract Factory
In abstract factory, you provide a factory class for each concrete implementation:
So your code becomes: (forgive the code, but the rationale is same)
public class SerialNumberValidatorFactory
{
public static SerialNumberValidatorFactory newInstance(
ProductCategory productCategory)
{
switch (productCategory)
{
case ProductCategory.Modem:
return new ModemValidatorFactory();
....
}
}
public abstract ISerialNumberValidator createValidator();
}
public class ModemValidatorFactory extends SerialNumberValidatorFactory
{
public ISerialNumberValidator createValidator()
{
return new ModemSerialNumberValidator("model", "number");
}
}
ISerialNumberValidator = SerialNumberValidatorFactory.newInstance(productCategory).createValidator()