How to use DI container to resolve dependencies in Strategy Pattern? - c#

I currently working on an application that will act differently based on userInput. So I think about the Strategy Pattern. Below is my implementation:
I have some business logic:
interface IBusinessLogic
{
void DoBusinessLogic();
}
class TypeABusinessLogic : IBusinessLogic
{
public void DoBusinessLogic()
{
Console.WriteLine("Do Business Logic for Type A");
}
}
class TypeBBusinessLogic : IBusinessLogic
{
public void DoBusinessLogic()
{
Console.WriteLine("Do Business Logic for Type B");
}
}
And, also some application logic:
interface IApplicationLogic
{
void DoApplicationLogic();
}
class TypeAApplicationLogic : IApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("Do Application Logic for Type A");
}
}
class TypeBApplicationLogic : IApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("Do Application Logic for Type B");
}
}
Now, my strategies need to do both business logic and application logic
interface IStrategy
{
void DoWork();
}
abstract class StrategyBase : IStrategy
{
private IBusinessLogic _businessLogic;
private IApplicationLogic _applicationLogic;
protected StrategyBase(IBusinessLogic businessLogic, IApplicationLogic applicationLogic)
{
_businessLogic = businessLogic;
_applicationLogic = applicationLogic;
}
public void DoWork()
{
_businessLogic.DoBusinessLogic();
_applicationLogic.DoApplicationLogic();
}
}
class TypeAStrategy : IStrategy
{
public TypeAStrategy(TypeABussinessLogic businessLogic, TypeAApplicationLogic applicationLogic) : base(businessLogic, applicationLogic)
{}
}
class TypeBStrategy : IStrategy
{
public TypeBStrategy(TypeBBussinessLogic businessLogic, TypeBApplicationLogic applicationLogic) : base(businessLogic, applicationLogic)
{}
}
Now is my Context class
class Context
{
private Func<string, IStrategy> _strategyFactory;
public Context(Func<string, IStrategy> strategyFactory)
{
_strategyFactory = strategyFactory;
}
public void Run()
{
string userInput = GetUserInput(); //"TypeA" or "TypeB"
IStrategy strategy = _strategyFactory(userInput);
strategy.DoWork();
}
}
Here is my DI builder code:
var builder = new ContainerBuilder();
builder.RegisterType<TypeAStrategy>().As<IStrategy>().Keyed<IStrategy>("TypeA");
var builder = new ContainerBuilder();
builder.RegisterType<TypeBStrategy>().As<IStrategy>().Keyed<IStrategy>("TypeB");
builder.Register<Func<string, IStrategy>>( c =>
{
var componentContext = c.Resolve<IComponentContext>();
return (key) =>
{
IStrategy stategy = componentContext.ResolveKeyed<IStrategy >(key);
return stategy;
};
});
The problem I can see here is my strategies (TypeAStrategy, TypeBStrategy) depend directly on concrete class (TypeABusinessLogic,TypeAApplicationLogic,TypeBBusinessLogic, TypeBApplicationLogic), which is not good. I can't mock these dependencies in unit test.
If I let my strategies depend on interfaces, I dont know how to implement DI container to resolve dependencies (Notes: I currently using Autofac, but I can use any other DI containers )
Please advise.

So I thought of a few ways to approach this, but I think the cleanest way is to just introduce some token interfaces. A token interface is one which doesn't add any properties or functionality. For instance:
interface IBusinessLogic
{
void DoBusinessLogic();
}
interface ITypeABusinessLogic : IBusinessLogic { }
interface ITypeBBusinessLogic : IBusinessLogic { }
interface IApplicationLogic
{
void DoApplicationLogic();
}
interface ITypeAApplicationLogic : IApplicationLogic { }
interface ITypeBApplicationLogic : IApplicationLogic { }
Next we adjust the classes to implement the relevant token interface:
class TypeABusinessLogic : ITypeABusinessLogic
{
public virtual void DoBusinessLogic()
{
Console.WriteLine("Do Business Logic for Type A");
}
}
class TypeBBusinessLogic : ITypeBBusinessLogic
{
public virtual void DoBusinessLogic()
{
Console.WriteLine("Do Business Logic for Type B");
}
}
class TypeAApplicationLogic : ITypeAApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("Do Application Logic for Type A");
}
}
class TypeBApplicationLogic : ITypeBApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("Do Application Logic for Type B");
}
}
We can similarly create mock classes by implementing the relevant token interface:
class MockTypeABusinessLogic : ITypeABusinessLogic
{
public void DoBusinessLogic()
{
Console.WriteLine("[Mock] Do Business Logic for Type A");
}
}
class MockTypeBBusinessLogic : ITypeBBusinessLogic
{
public void DoBusinessLogic()
{
Console.WriteLine("[Mock] Do Business Logic for Type B");
}
}
class MockTypeAApplicationLogic : ITypeAApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("[Mock] Do Application Logic for Type A");
}
}
class MockTypeBApplicationLogic : ITypeBApplicationLogic
{
public void DoApplicationLogic()
{
Console.WriteLine("[Mock] Do Application Logic for Type B");
}
}
I also modified the IStrategy interface to make injection with Unity a little easier, giving each strategy a Name property (you don't need to do this):
interface IStrategy
{
string Name { get; }
void DoWork();
}
abstract class StrategyBase : IStrategy
{
private IBusinessLogic _businessLogic;
private IApplicationLogic _applicationLogic;
public string Name { get; private set; }
protected StrategyBase(String name, IBusinessLogic businessLogic, IApplicationLogic applicationLogic)
{
this.Name = name;
_businessLogic = businessLogic;
_applicationLogic = applicationLogic;
}
public void DoWork()
{
_businessLogic.DoBusinessLogic();
_applicationLogic.DoApplicationLogic();
}
}
class TypeAStrategy : StrategyBase
{
public TypeAStrategy(String name, ITypeABusinessLogic businessLogic, ITypeAApplicationLogic applicationLogic) : base(name, businessLogic, applicationLogic)
{ }
}
class TypeBStrategy : StrategyBase
{
public TypeBStrategy(String name, ITypeBBusinessLogic businessLogic, ITypeBApplicationLogic applicationLogic) : base(name, businessLogic, applicationLogic)
{ }
}
Using Unity I wrote the following program to test the registrations:
class Context
{
private Dictionary<string, IStrategy> _strategyFactory = new Dictionary<string, IStrategy>();
public Context(IStrategy[] strategies)
{
foreach (var s in strategies)
{
_strategyFactory.Add(s.Name, s);
}
}
public void Run()
{
string userInput = "TypeA";
IStrategy strategy = _strategyFactory[userInput];
strategy.DoWork();
userInput = "TypeB";
strategy = _strategyFactory[userInput];
strategy.DoWork();
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Mock DI Example: ");
UnityContainer ioc = new UnityContainer();
ioc.RegisterType<ITypeABusinessLogic, MockTypeABusinessLogic>();
ioc.RegisterType<ITypeAApplicationLogic, MockTypeAApplicationLogic>();
ioc.RegisterType<ITypeBBusinessLogic, MockTypeBBusinessLogic>();
ioc.RegisterType<ITypeBApplicationLogic, MockTypeBApplicationLogic>();
ioc.RegisterType<IStrategy, TypeAStrategy>("TypeA", new InjectionConstructor("TypeA", typeof(ITypeABusinessLogic), typeof(ITypeAApplicationLogic)));
ioc.RegisterType<IStrategy, TypeBStrategy>("TypeB", new InjectionConstructor("TypeB", typeof(ITypeBBusinessLogic), typeof(ITypeBApplicationLogic)));
Context c = ioc.Resolve<Context>();
c.Run();
Console.WriteLine("\nUnmocked DI Example: ");
ioc = new UnityContainer();
ioc.RegisterType<ITypeABusinessLogic, TypeABusinessLogic>();
ioc.RegisterType<ITypeAApplicationLogic, TypeAApplicationLogic>();
ioc.RegisterType<ITypeBBusinessLogic, TypeBBusinessLogic>();
ioc.RegisterType<ITypeBApplicationLogic, TypeBApplicationLogic>();
ioc.RegisterType<IStrategy, TypeAStrategy>("TypeA", new InjectionConstructor("TypeA", typeof(ITypeABusinessLogic), typeof(ITypeAApplicationLogic)));
ioc.RegisterType<IStrategy, TypeBStrategy>("TypeB", new InjectionConstructor("TypeB", typeof(ITypeBBusinessLogic), typeof(ITypeBApplicationLogic)));
c = ioc.Resolve<Context>();
c.Run();
Console.WriteLine("\nPress enter to exit...");
Console.ReadLine();
}
And here was my output:
Mock DI Example:
[Mock] Do Business Logic for Type A
[Mock] Do Application Logic for Type A
[Mock] Do Business Logic for Type B
[Mock] Do Application Logic for Type B
Unmocked DI Example:
Do Business Logic for Type A
Do Application Logic for Type A
Do Business Logic for Type B
Do Application Logic for Type B
Press enter to exit...
This isn't the only way to solve the problem, but I think this most directly matches how you have structured your code in the OP. Hope this helps :)
EDIT: Here is one alternative to the above which I think you should consider. It will cut down on your object and interface hierarchy quite a bit. NOTE: you'll need to make the StrategyBase class not abstract, and expose the constructor as public.
Console.WriteLine("\nAlternative DI Example: ");
ioc = new UnityContainer();
ioc.RegisterType<IBusinessLogic, TypeABusinessLogic>("TypeA");
ioc.RegisterType<IApplicationLogic, TypeAApplicationLogic>("TypeA");
ioc.RegisterType<IStrategy, StrategyBase>("TypeA", new InjectionConstructor("TypeA", new ResolvedParameter<IBusinessLogic>("TypeA"), new ResolvedParameter<IApplicationLogic>("TypeA") ));
ioc.RegisterType<IBusinessLogic, TypeBBusinessLogic>("TypeB");
ioc.RegisterType<IApplicationLogic, TypeBApplicationLogic>("TypeB");
ioc.RegisterType<IStrategy, StrategyBase>("TypeB", new InjectionConstructor("TypeB", new ResolvedParameter<IBusinessLogic>("TypeB"), new ResolvedParameter<IApplicationLogic>("TypeB")));
c = ioc.Resolve<Context>();
c.Run();
Since your classes and the token interfaces don't actually provide you any functionality, they only serve as a means of differentiating the specific implementations. But DI containers already have a simple means of doing this: strings. In Unity you can use the same string for different types, like above. You can use this to delineate which specific implementations go together. This is my recommendation :)

Related

How to point to underlying class of <T> in generic factory

Got some vegetables going on:
public interface IVegetable
{
}
public class Potato : IVegetable
{
}
public class Onion : IVegetable
{
}
We'd focus on the onion and process it: I have single generic interface for a generic vegetable processor and one onion-specific:
public interface IVegetableProcessor<T> where T : IVegetable
{
string GetColor(T vegetable);
}
public interface IOnionProcessor : IVegetableProcessor<Onion>
{
void MakeCry(Onion onion);
}
public class OnionProcessor : IOnionProcessor
{
public string GetColor(Onion onion)
{
return "Purple";
}
public void MakeCry(Onion onion)
{
Console.WriteLine($"{onion} made you cry!");
}
}
As well as a generic factory:
interface IVegetableProcessorFactory
{
IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable;
}
internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
public IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable
{
object processor = vegetable switch
{
Onion => new OnionProcessor(),
_ => throw new NotImplementedException($"Other vegetables not here yet")
};
return (IVegetableProcessor<T>)processor; //this will fail later
}
}
And finally this does not work:
static void Main(string[] args)
{
var onion = new Onion() as IVegetable;
var factory = new VegetableProcessorFactory();
var processor = factory.GetVegetableProcessor(onion);
Console.WriteLine(processor.GetColor(onion));
Console.ReadLine();
}
The error is:
System.InvalidCastException: 'Unable to cast object of type 'OnionProcessor' to type 'IVegetableProcessor`1[Vegetables.Program+IVegetable]'.'
How to make it understand the underlying class of IVegetable and cast the processor to it's corresponding type?
Your input is already contravariant, but by casting your Onion instance to IVegetable, it is no longer able to be cast back to IVetetableProcessor<T> in your factory, because at that point you need IVetetableProcessor<Onion>, but what you have is a IVegetableProcessor<IVegetable>, and your interface is not covariant.
By simply removing your initial cast of new Onion to IVegetable, your code works as is:
static void Main(string[] args)
{
var onion = new Onion();
var factory = new VegetableProcessorFactory();
var processor = factory.GetVegetableProcessor(onion);
Console.WriteLine(processor.GetColor(onion));
Console.ReadLine();
}
public interface IVegetable { }
public class Potato : IVegetable { }
public class Onion : IVegetable { }
public interface IVegetableProcessor<T> where T : IVegetable
{
string GetColor(T vegetable);
}
public interface IOnionProcessor : IVegetableProcessor<Onion>
{
void MakeCry();
}
public class OnionProcessor : IOnionProcessor
{
public string GetColor(Onion vegetable)
{
return "Purple";
}
public void MakeCry()
{
Console.WriteLine("You cry now!");
}
}
interface IVegetableProcessorFactory
{
IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable;
}
internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
public IVegetableProcessor<T> GetVegetableProcessor<T>(T vegetable) where T : IVegetable
{
var processor = vegetable switch
{
Onion => new OnionProcessor(),
_ => throw new NotImplementedException($"Other vegetables not here yet")
};
return (IVegetableProcessor<T>)processor;
}
}
The fact that you have to cast in the first place is your hint that something is broken in your composition. As Selvin mentioned in the comments, implementing IVegetableProcessor<Onion> is NOT the same thing as implementing IVegetableProcessor<IVegetable>.
Your processor interfaces should implement IVegetableProcessor<IVegetable> and take IVegetable instances, allowing contravariance for the input parameters:
public interface IVegetableProcessor<T> where T : IVegetable
{
string GetColor(T vegetable);
}
public interface IOnionProcessor : IVegetableProcessor<IVegetable>
{
void MakeCry();
}
public class OnionProcessor : IOnionProcessor
{
public string GetColor(IVegetable vegetable)
{
return "Purple";
}
public void MakeCry()
{
Console.WriteLine("You cry now!");
}
}
interface IVegetableProcessorFactory
{
IVegetableProcessor<IVegetable> GetVegetableProcessor(IVegetable vegetable);
}
internal class VegetableProcessorFactory : IVegetableProcessorFactory
{
public IVegetableProcessor<IVegetable> GetVegetableProcessor(IVegetable vegetable)
{
var processor = vegetable switch
{
Onion => new OnionProcessor(),
_ => throw new NotImplementedException($"Other vegetables not here yet")
};
return processor;
}
}
This correctly outputs "Purple" when run via:
static void Main(string[] args)
{
var onion = new Onion();
var factory = new VegetableProcessorFactory();
var processor = factory.GetVegetableProcessor(onion);
Console.WriteLine(processor.GetColor(onion));
Console.ReadLine();
}

dependency injection based on user input

Consider the code snippet (I used the strategy Pattern in the example) :
abstract class SortStrategy
{
public abstract void Sort(ArrayList list);
}
class QuickSort : SortStrategy
{
public override void Sort(ArrayList list)
{
//...
}
}
class ShellSort : SortStrategy
{
public override void Sort(ArrayList list)
{
// ....
}
}
and in Context :
class SortedList
{
private ArrayList list = new ArrayList();
private SortStrategy sortstrategy;
public void SetSortStrategy(SortStrategy sortstrategy)
{
this.sortstrategy = sortstrategy;
}
public void Add(string name)
{
list.Add(name);
}
public void Sort()
{
sortstrategy.Sort(list);
}
}
My question is that the end user through the UI and by selecting an option says to use the method for example QuickSort to sort, but what should I do, how to set SetSortStrategy (or how to dependency injection in this case)
I suggest using factory pattern with dependency injection:
public enum StrategyType
{
A,
B,
C
}
public interface IStrategyFactory {
IStrategy Create();
}
public class BasedOnUserSelStrategyFactory {
public IStrategy Create() {
StrategyType type = ReadUserSelectionFromFile(); // or any place stored
switch (type) {
case StrategyType.A:
return di.Resolve<AStrategy>(); // resolve using di container
case StrategyType.B:
return di.Resolve<BStrategy>(); // resolve using di container
case StrategyType.C:
return di.Resolve<CStrategy>(); // resolve using di container
default:
throw new ArgumentException("type");
}
}
}
Then, register factory in di:
di.Register<IStrategyFactory>().As<BasedOnUserSelStrategyFactory>();
Finally:
IStrategy s = di.Resolve<IStrategyFactory>().Create();
s.MyOperation();
The Castle.Windsor based DI of our MORYX-Framework allows users to configure a ModuleStrategy property in the config.
When a modules config looks like this:
public class ModuleConfig : ConfigBase
{
[DataMember, PluginStrategy(typeof(SortStrategy))]
[ModuleStrategy(typeof(SortStrategy))]
public string SortStrategy { get; set; }
}
The user can choose one of the found classes and every import of SortStragy is automatically filled with an instance. Using the graphic interface the user can select QuickSort and ShellSort, as well as any other implementation found at runtime from a drop-down box.
[Plugin(LifeCycle.Transient, typeof(SortStrategy))]
class QuickSort : SortStrategy
{
// ...
}
class SortedList
{
private ArrayList list = new ArrayList();
// injected with either QuickSort or ShellSort
public SortStrategy Sortstrategy { get; set; }
public void Add(string name)
{
list.Add(name);
}
public void Sort()
{
sortstrategy.Sort(list);
}
}
If you prefer to use the factory pattern, you can also declare a named factory. This can create any strategy registered as shown above.
[PluginFactory(typeof(INameBasedComponentSelector))]
public interface ISortStrategyFactory
{
SortStrategy Create(string name);
void Destroy(SortStrategy instance);
}
If you use Castle.Windsor, this is the code (Licensed under Apache2.0) we use to configure the override on all dependency declarations:
https://github.com/PHOENIXCONTACT/MORYX-Platform/blob/dev/src/Moryx.Container/LocalContainer/LocalRegistrator.cs#L34

Replace usage of production classes in compiled code with simulated classes

So I have production code, compiled against production dlls. They access the real architecture of the system.
I'm working on a simulator that will simulate this architecture. All the classes in the simulation are named the same and belong to the same namespaces as the production classes.
People can use my simulation dlls to do a rough draft test of their code.
However, if they call existing production business logic that was compiled against the production classes, it will load the existing production dlls and use the real architecture.
If people want to use my simulation, but call existing business logic, I'd have to use some kind of injection to overwrite the dll that loads the production classes.
Is this possible?
For an example:
I have a dll called Production.dll
In it there is a class like so.
namespace Production
{
public class A { public void Do(); }
}
Now, I have a dll called Simulation.dll with the same class and code.
Someone wrote a program called DoA.exe
public static class Program
{
public static Main()
{
var a = new Production.A();
a.Do();
}
}
I want to make DoA.exe load my simulation dll, but I may not be able to remove Production.dll from its search path. How can I force it to use Simulation.dll instead.
I think I understand better your problem. While I think my original solution is cleaner, this is how to do it "dirty".
Assuming your class schema is like this (simplified):
// assembly: Production.dll (no dependencies)
namespace Production {
public class Test {
public void Do() {
Console.Out.WriteLine("Production");
}
}
}
// assembly: Simulation.dll (no dependencies)
namespace Production {
public class Test {
public void Do() {
Console.Out.WriteLine("Simulation");
}
}
}
// assembly: Usage.dll (dependency on Production.dll)
namespace Usage {
public class TestUsage {
public void Do() {
new Production.Test().Do();
}
}
}
And finally code that will perform the override:
// Console application ConsoleApplication.exe
// dependency on Production.dll, Usage.dll and Simulation.dll
namespace ConsoleApplication {
internal class AssemblyResolver : MarshalByRefObject {
static internal void Register(AppDomain domain) {
var resolver = domain.CreateInstanceFromAndUnwrap(
Assembly.GetExecutingAssembly().Location,
typeof(AssemblyResolver).FullName) as AssemblyResolver;
resolver.RegisterDomain(domain);
}
private void RegisterDomain(AppDomain domain) {
domain.AssemblyResolve += ResolveAssembly;
}
private Assembly ResolveAssembly(object sender, ResolveEventArgs args) {
var assemblyName = new AssemblyName(args.Name);
string name = assemblyName.Name;
// comment out line below and you'll load "Production" instead
if (name == "Production") {
name = "Simulation";
}
var fileNames = new[] { name + ".dll", name + ".exe" };
foreach (string fileName in fileNames) {
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
if (File.Exists(path)) {
return Assembly.Load(File.ReadAllBytes(path));
}
}
return null;
}
}
class Program {
static void Main(string[] args) {
var domain = AppDomain.CreateDomain("Doable", null, new AppDomainSetup {
DisallowApplicationBaseProbing = true
});
AssemblyResolver.Register(domain);
domain.DoCallBack(() => {
// writes out "Simulation"
new Usage.TestUsage().Do();
});
}
}
}
I'm using Dependency Injection to handle problems like this:
Suppose you have interface like
public interface IDoable {
void Do();
}
in Interfaces.dll
and than you have Production.dll with class like:
namespace Production {
internal class Doable : IDoable {
public void Do() { Console.Out.WriteLine("Production"); }
}
public static class Bootstrapper {
static void Init(IServiceLocator locator) {
locator.AddSingleton<IDoable, Doable>();
}
}
}
and then you have Simulation.dll with class like
namespace Simulation {
internal class Doable : IDoable {
public void Do() { Console.Out.WriteLine("Simulation"); }
}
public static class Bootstrapper {
static void Init(IServiceLocator locator) {
locator.AddSingleton<IDoable, Doable>();
}
}
}
Then in your MainAssembly you can reference both, and resolve what implementation you want to use via configuration (naive example below). Except for the configuration line, you don't really have to care from which assembly the IDoable came from - you just use it.
public static Main()
{
Production.Bootstrapper.Init(ServiceLocator.Instance);
// or you can use
// Simulation.Bootstrapper.Init(ServiceLocator.Instance);
IDoable doable = ServiceLocator.Instance.Resolve<IDoable>();
doable.Do();
}
Utility classes (using Microsoft Unity Container from Enterprise Library):
public interface IServiceLocator {
void Add<TFrom, TTo>() where TTo : TFrom;
void BuildUp<T>(T instance);
void BuildUp(Type type, object instance);
void AddSingleton<TFrom, TTo>() where TTo : TFrom;
void AddSingleton<TFrom, TTo>(string name) where TTo : TFrom;
void AddSingleton(Type from, Type to, string name);
void AddInstance<T>(T instance);
T Resolve<T>();
T Resolve<T>(string name);
}
public class ServiceLocator : IServiceLocator {
private IUnityContainer m_Container = new UnityContainer();
public void Add<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>();
}
public void BuildUp<T>(T instance) {
m_Container.BuildUp<T>(instance);
}
public void BuildUp(Type type, object instance) {
m_Container.BuildUp(type, instance);
}
public void AddSingleton<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
}
public void AddSingleton<TFrom, TTo>(string name) where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(name, new ContainerControlledLifetimeManager());
}
public void AddSingleton(Type from, Type to, string name) {
m_Container.RegisterType(from, to, name, new ContainerControlledLifetimeManager());
}
public void AddInstance<T>(T instance) {
m_Container.RegisterInstance<T>(instance);
}
public T Resolve<T>() {
return m_Container.Resolve<T>();
}
public T Resolve<T>(string name) {
return m_Container.Resolve<T>(name);
}
private static IServiceLocator s_Instance;
public static IServiceLocator Instance {
get { return s_Instance; }
}
static ServiceLocator() {
var instance = new ServiceLocator();
instance.AddInstance<IServiceLocator>(instance);
s_Instance = instance;
}
}

Unit: Resolve generic service using object type at runtime

What i'm trying to accomplish is to have a single wcf service that has (for example) an Insert(ICommand command) method and can resolve a generic service that knows how to insert the underling object type.
Where's my (poor) attempt on a sandbox project.
Besides other flaws, this services allow to attempt to insert any ICommand.
I'm relative new Unit user and i was wondering if someone has a better way to accomplish this.
class Program
{
static void Main(string[] args)
{
var cmd = new SingleCommand();
var cmd2 = new DoubleCommand();
var s = new MyWcfService();
s.Insert(cmd);
s.Insert(cmd2);
Console.ReadKey();
}
}
public interface ICommand { }
public interface ICommandService
{
void Insert(ICommand command);
}
public interface ICommandService<in T> : ICommandService where T : ICommand
{
void Insert(T command);
}
public class SingleCommand : ICommand { }
public class DoubleCommand : ICommand { }
public class SingleCommandService : ICommandService<SingleCommand>
{
public void Insert(SingleCommand singleCommand)
{
Console.WriteLine("Inserted a SingleCommand");
}
void ICommandService.Insert(ICommand command)
{
Insert((SingleCommand)command);
}
}
public class DoubleCommandService : ICommandService<DoubleCommand>
{
public void Insert(DoubleCommand doubleCommand)
{
Console.WriteLine("Inserted a DoubleCommand");
}
void ICommandService.Insert(ICommand command)
{
Insert((DoubleCommand)command);
}
}
public static class Config
{
public static UnityContainer Container = new UnityContainer();
static Config()
{
Container.RegisterType<ICommandService, SingleCommandService>(typeof(SingleCommand).Name);
Container.RegisterType<ICommandService, DoubleCommandService>(typeof(DoubleCommand).Name);
}
}
public class MyWcfService
{
public void Insert(ICommand command)
{
var foo = Config.Container.Resolve<ICommandService>(command.GetType().Name);
foo.Insert(command);
}
}
If you really don't have a service that can be invoked for all ICommand, then you shouldn't offer that in its contract. An easy way around this is to extend the ICommand interface into something like IServiceCommand, and have those ICommand which are supported implement IServiceCommand instead, and tie your service contract instead to that interface. This allows your concrete classes to be used in any method which expects an ICommand, but your service still only service those ICommand which are also IServiceCommand.

Generic decorator with Windsor

I'm trying to figure out how to register the following decorator scenario with Castle Windsor. I have the following interface:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
And a couple of implementations where the last one is a decorator.
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T> : ICalculate<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}
This is my registration code
container.Register(Classes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
When i request one of the implementations by their generic interface I want Windsor to resolve the CalculatorDecorator with the requested implementation injected in the constructor.
// I would like calculator to be CalculatorDecorator<Foo> in
// this case but it is FooCalculator.
var calculator = container.Resolve<ICalculate<Foo>>();
// The same goes for this one...
var calculator = containr.Resolve<ICalculate<Bar>>();
Thanks in advance!
Edit:
It works if I do like this
container.Register(Component.For<ICalculate<Foo>>()
.ImplementedBy<CalculatorDecorator<Foo>>(),
Component.For<ICalculate<Foo>>()
.ImplementedBy<FooCalculator>());
container.Register(Component.For<ICalculate<Bar>>()
.ImplementedBy<CalculatorDecorator<Bar>>(),
Component.For<ICalculate<Bar>>()
.ImplementedBy<BarCalculator>());
But I would prefer to register all components if it's possible.
container.Register(AllTypes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
Did you try this? We had a similar situation and this worked for us.
UPDATE
I don't think this is possible because you'll create a circular dependency.
I did get it working like following:
Registration
var container = new WindsorContainer();
container.Register(Component.For(typeof(IDecorator<>)).ImplementedBy(typeof(CalculatorDecorator<>)));
container.Register(AllTypes.FromThisAssembly()
.BasedOn(typeof (ICalculate<>))
.WithService.Base());
var fc = container.Resolve<IDecorator<Foo>>();
var bc = container.Resolve<IDecorator<Bar>>();
Interfaces:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
public interface IDecorator<T> : ICalculate<T> where T : class
{
}
Implementation:
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T>: IDecorator<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}

Categories