How to use DI container to resolve dependencies in Strategy Pattern?











up vote
1
down vote

favorite












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.










share|improve this question




















  • 1




    You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
    – Ryan Pierce Williams
    Nov 8 at 21:48












  • @Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
    – TrBaPhong
    Nov 8 at 22:05












  • If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
    – Ryan Pierce Williams
    Nov 8 at 22:23










  • What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
    – TrBaPhong
    Nov 9 at 3:13










  • I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
    – Ryan Pierce Williams
    Nov 9 at 5:07

















up vote
1
down vote

favorite












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.










share|improve this question




















  • 1




    You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
    – Ryan Pierce Williams
    Nov 8 at 21:48












  • @Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
    – TrBaPhong
    Nov 8 at 22:05












  • If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
    – Ryan Pierce Williams
    Nov 8 at 22:23










  • What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
    – TrBaPhong
    Nov 9 at 3:13










  • I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
    – Ryan Pierce Williams
    Nov 9 at 5:07















up vote
1
down vote

favorite









up vote
1
down vote

favorite











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.










share|improve this question















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.







c# design-patterns dependency-injection autofac ioc-container






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 9 at 9:01









Steven

125k17211325




125k17211325










asked Nov 8 at 21:41









TrBaPhong

215




215








  • 1




    You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
    – Ryan Pierce Williams
    Nov 8 at 21:48












  • @Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
    – TrBaPhong
    Nov 8 at 22:05












  • If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
    – Ryan Pierce Williams
    Nov 8 at 22:23










  • What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
    – TrBaPhong
    Nov 9 at 3:13










  • I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
    – Ryan Pierce Williams
    Nov 9 at 5:07
















  • 1




    You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
    – Ryan Pierce Williams
    Nov 8 at 21:48












  • @Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
    – TrBaPhong
    Nov 8 at 22:05












  • If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
    – Ryan Pierce Williams
    Nov 8 at 22:23










  • What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
    – TrBaPhong
    Nov 9 at 3:13










  • I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
    – Ryan Pierce Williams
    Nov 9 at 5:07










1




1




You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
– Ryan Pierce Williams
Nov 8 at 21:48






You don't use the DI container to resolve dynamic input from the user (Any injection should be complete after bootstrapping). You could use factories. DI could be used to inject the available factories, along with the names to use for those factories. For example, using Unity you could pull the factory registrations out into a config file. You could then modify the factories that are registered from the config file without recompiling your program, and give each factory a unique name. You could supply any name you wanted for each individual factory, doesn't need to be the class name.
– Ryan Pierce Williams
Nov 8 at 21:48














@Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
– TrBaPhong
Nov 8 at 22:05






@Ryan: Can you provide more details on how to register dependencies for my strategy. Any example code (even in Unity) is really appreciated. I add my ContainerBuilder code to make it more clear.
– TrBaPhong
Nov 8 at 22:05














If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
– Ryan Pierce Williams
Nov 8 at 22:23




If someone else doesn't do it before I can, I'll put together an example tonight. At any rate, your current hierarchy doesn't require intermediate interfaces for each strategy. Your strategies aren't adding anything new in terms of functionality or in terms of properties, so your base IStrategy interface is all you need for mocking purposes.
– Ryan Pierce Williams
Nov 8 at 22:23












What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
– TrBaPhong
Nov 9 at 3:13




What do you mean "intermediate interfaces for each strategy"? Are you talking about IBusinessLogic, IApplicationLogic? I think it necessary because I wanna separate different logic categories into different classes (TypeABusinessLogic and TypeAApplicationLogic handle different logic). It helps my achieve Single Reponsibility.
– TrBaPhong
Nov 9 at 3:13












I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
– Ryan Pierce Williams
Nov 9 at 5:07






I mean that you don't need an ITypeAStrategy or ITypeBStrategy interface. The strategies don't add any functionality/properties so you can mock them both just using the base IStrategy interface.
– Ryan Pierce Williams
Nov 9 at 5:07














1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










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 :)






share|improve this answer



















  • 1




    Thanks Ryan for your help. The token interface idea help me solved the problem
    – TrBaPhong
    Nov 9 at 19:40











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53216558%2fhow-to-use-di-container-to-resolve-dependencies-in-strategy-pattern%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










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 :)






share|improve this answer



















  • 1




    Thanks Ryan for your help. The token interface idea help me solved the problem
    – TrBaPhong
    Nov 9 at 19:40















up vote
1
down vote



accepted










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 :)






share|improve this answer



















  • 1




    Thanks Ryan for your help. The token interface idea help me solved the problem
    – TrBaPhong
    Nov 9 at 19:40













up vote
1
down vote



accepted







up vote
1
down vote



accepted






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 :)






share|improve this answer














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 :)







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 9 at 10:18

























answered Nov 9 at 6:21









Ryan Pierce Williams

43719




43719








  • 1




    Thanks Ryan for your help. The token interface idea help me solved the problem
    – TrBaPhong
    Nov 9 at 19:40














  • 1




    Thanks Ryan for your help. The token interface idea help me solved the problem
    – TrBaPhong
    Nov 9 at 19:40








1




1




Thanks Ryan for your help. The token interface idea help me solved the problem
– TrBaPhong
Nov 9 at 19:40




Thanks Ryan for your help. The token interface idea help me solved the problem
– TrBaPhong
Nov 9 at 19:40


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53216558%2fhow-to-use-di-container-to-resolve-dependencies-in-strategy-pattern%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

how to define a CAPL function taking a sysvar argument

Schultheiß

Extract exact text in tags