Should I use Constructor Injection or IoC.Resolve? - c#

I'm building very simple board game (just to learn some new stuff). It will be cross-platform (written using Xamarin). I've already written the core of the game, but I'm not sure (still) whether should I use constructor injection or IoC resolve. Right now I use IoC.Resolve and then pass through parameter.
Here is my code. I have Game that has 2 dependencies and type. I have factories to create Games and Players:
Abc.MyGame.Domain
Interfaces
public interface IGame
{
GameType GameType { get; }
IGameBoard GameBoard { get; }
List<IPlayer> Players { get; }
// Other stuff...
}
public interface IGameBoard
{
//board stuff...
}
public interface IPlayer
{
int PlayerId { get; set; }
PlayerType PlayerType { get; set; }
}
Factory interfaces
public interface IGameFactory
{
IGame CreateGame(GameType type, IGameBoard board);
}
public interface IPlayerFactory
{
IPlayer CreatePlayer(PlayerType type, int id);
}
Factories
public class GameFactory : IGameFactory
{
public IGame CreateGame(GameType type, IGameBoard board)
{
switch (type)
{
case GameType.SinglePlayer:
return new MyGame(type, board,
new List<IPlayer> { CreateHuman(1), CreateBot(2) });
case GameType.TwoPlayers:
return new MyGame(type, board,
new List<IPlayer> { CreateHuman(1), CreateHuman(2) });
case GameType.Online:
return new MyGame(type, board,
new List<IPlayer> { CreateHuman(1), CreateOnlinePlayer(2) });
}
return null;
}
}
Then, there is an API. Used by UI:
Abc.MyGame.API
public class GameAPI
{
public IGame CurrentGame { get; set; }
public IGame CreateGame(IGameFactory gameFactory, GameType type, IBoard board)
{
CurrentGame = gameFactory.CreateGame(type, board);
return CurrentGame;
}
// Other stuff, like make move etc...
}
... and my UI:
Abc.MyGame.UI.WinForms
public partial class Form1 : Form
{
private GameAPI api = new GameAPI();
IKernel kernel = new StandardKernel();
public Form1()
{
InitializeComponent();
// Load all dependencies
var modules = new List<INinjectModule> { new GameModule() };
kernel.Load(modules);
}
private void buttonStartGame(object sender, EventArgs e)
{
IGameBoard board = kernel.Get<IGameBoard>(
new ConstructorArgument("width", 7),
new ConstructorArgument("height", 6)
);
api.CreateGame(kernel.Get<IGameFactory>(), GameType.TwoPlayers, board);
}
}
I need to IGameBoard in my IGame. ONLY there. I need to inject board and players to IGame.
Here is my problem/question:
Do I really need to resolve IGameBoard at the very "front" of my program? I resolve it in UI, when somebody click "Start Game" button. And then I pass this board through API, then I pass it to GameFactory, then I pass it to Game constructor (finally!). Is it a bad practice to create (or resolve) IPlayerFactory and IGameBoard inside GameFactory? API.CreateGame will have only type parameter in that case? I mean for specific GameFactory there is only one board (evey time the same), so I'm not sure I need to create board at the very beginning...
EDIT:
MyGame constructor:
public class MyGame : IGame
{
public IBoard Board { get; }
public GameType Type { get; }
public List<IPlayer> Players { get; }
public MyGame(GameType type, IBoard board, List<IPlayer> players)
{
Type = type;
Board = board;
Players = players;
}
//...
}

Do I really need to resolve IGameBoard at the very "front" of my program?
Yes, dependencies need to be resolved at entry points and at the start of lifetime scopes (if any) in your application. Often, this is abstracted (like in ASP.NET MVC), so you never have to call kernel.Get<> (or any other container.Resolve<>) yourself. In WinForms there is no such mechanism, so you have to resolve the dependencies yourself, preferably only the root dependency like this:
public static class Program
{
private static void Main()
{
var kernel = new StandardKernel();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(kernel.Get<Form1>());
}
}
By putting the right dependencies on your main form (probably including a factory in your case for the games), you should not need any more kernel.Get<> in your application.

Related

How to implement Inversion of Control using Pure DI on a Console Application? (Without using IoC containers)

I have an example application where I would like to use the concepts of Inversion of Control to inject dependencies into lower level classes. My example application is a gummy bear factory. The gummy bear factory is responsible for creating each individual Gummy Bear, Adding it to a "Mini-Travel Size" bag, then adding the correct number of mini-bags to the larger package.
The Gummy Bear factory is provided a configuration that could change each time the factory project is run. In my example, it is a static class but just imagine this was loaded from say a configuration text file or XML file instead of being hard coded. Therefore, I have no idea of knowing at compile time what the user is going request for the number of gummy bears in a bag and the number of mini travel sized bags in a package.
Therefore, I am confused about how to decouple the Gummy Factory's AssembleProducts() method from the concrete implementation of GummyPackage, GummyBag, and GummyBear classes.
I can't necessarily use constructor injection because I don't know exactly how many GummyBears will be required. How would one decouple this code using the notion of "Pure DI". Is there any way to do this without the use of an IoC container? In my real world application, I am unable to use any third party packages (i.e. - IoC containers such as Autofac).
This is what the Configuration looks like (remember, this could have been from a file):
public enum GummyFlavor { Cherry, Lemon, Orange, Pinapple, Apple, Strawberry }
public static class GummyBearPackageConfiguration
{
// Number of travel size gummy "mini-bags" per package
public static int NumberOfGummieBagsPerPackage { get; set; }
// Number of gummies in each travel size bag
public static int NumberOfGummiesPerBags { get; set; }
}
Here is the code:
class Program
{
static void Main(string[] args)
{
// Load the "Configuration"
GummyBearPackageConfiguration.NumberOfGummieBagsPerPackage = 24;
GummyBearPackageConfiguration.NumberOfGummiesPerBags = 7;
GummyFactory gummyFactory = new GummyFactory();
IGummyPackage gummyPackage = gummyFactory.AssembleProducts();
OpenPackage(gummyPackage);
Console.ReadLine();
}
public static void OpenPackage(IGummyPackage package)
{
// Iterate over the Gummies
Console.WriteLine($"Opening Gummy Package: \n");
foreach (GummyBag bag in package.GummyBags)
{
Console.WriteLine($"Opening Gummy Bag #{bag.BagNumber}");
foreach (GummyBear bear in bag.GummyBears)
{
Console.WriteLine(
$"Gummy Number {bear.GummyID} is {bear.flavor.ToString()} flavor");
}
}
}
}
Generic Factory Class:
public interface IFactory<T>
{
T AssembleProducts();
}
public abstract class Factory<T> : IFactory<T>
{
public abstract T AssembleProducts();
}
Gummy Factory:
public class GummyFactory : Factory<IGummyPackage>
{
public override IGummyPackage AssembleProducts()
{
IGummyPackage gummyPackage = new GummyPackage();
Random rnd = new Random();
for (int i=1;i<=GummyBearPackageConfiguration.NumberOfGummieBagsPerPackage;i++)
{
IGummyBag gummyBag = new GummyBag();
gummyBag.BagNumber = i;
for (int b =1; b <= GummyBearPackageConfiguration.NumberOfGummiesPerBags;b++)
{
IGummyBear gummyBear = new GummyBear();
gummyBear.GummyID = b;
int flvr = rnd.Next(0, 5);
gummyBear.flavor = (GummyFlavor)flvr; // Pick a random flavor
gummyBag.GummyBears.Add(gummyBear); // Add Bear to the bag
}
gummyPackage.GummyBags.Add(gummyBag); // Add Bag to the Package
}
return gummyPackage;
}
}
Gummy Package:
public interface IGummyPackage
{
List<IGummyBag> GummyBags { get; set; }
}
public class GummyPackage : IGummyPackage
{
public GummyPackage()
{
GummyBags = new List<IGummyBag>();
}
public List<IGummyBag> GummyBags { get; set; }
}
Gummy Bag:
public interface IGummyBag
{
List<IGummyBear> GummyBears { get; set; }
int BagNumber { get; set; }
}
public class GummyBag : IGummyBag
{
public GummyBag()
{
GummyBears = new List<IGummyBear>();
}
public List<IGummyBear> GummyBears { get; set; }
public int BagNumber { get; set; }
}
Last but not least, the Gummy Bear:
public interface IGummyBear
{
GummyFlavor flavor { get; set; }
int GummyID { get; set; }
}
public class GummyBear : IGummyBear
{
public GummyFlavor flavor { get; set; }
public int GummyID { get; set; }
}
The AssembleProducts() class depends on the concrete implementations of a GummyPackage, GummyBag, and GummyBear. Say in the future, management wants to change over from using GummyBags to mini Gummy cardboard "Boxes" because of new environmental rules. In the above scenario, I would need to crack open the GummyFactory.AssembleProducts() logic and re-wire the class to use boxes instead of Bags.
Is there a way to move this dependency linking up a level in the object graph?
The package, bag and gummy bear behave more like data models and do not really need backing abstractions.
As you described in your example
Say in the future, management wants to change over from using GummyBags to mini Gummy cardboard "Boxes" because of new environmental rules.
Then design the model to reflect that possibility.
For example here are my refactored models for this example application
public class GummyPackage {
public GummyPackage() {
Containers = new List<GummyBearContainer>();
}
public List<GummyBearContainer> Containers { get; set; }
}
public class GummyBearContainer {
public GummyBearContainer() {
GummyBears = new List<GummyBear>();
}
public List<GummyBear> GummyBears { get; set; }
public string ContainerType { get; set; }
public int ContainerNumber { get; set; }
}
public class GummyBear {
public GummyFlavor flavor { get; set; }
public int GummyID { get; set; }
}
the configuration does not need to be static. It can be a simple data class instance as well that reflects the required configuration for the application.
public class PackageConfiguration { //run-time data
public int NumberOfContainersPerPackage { get; set; }
public int NumberOfUnitsPerContainer { get; set; }
public string ContainerType { get; set; }
}
Where it is populated from is an implementation detail/concern that can be handled by the user/developer of the application.
The factory can now explicitly depend on what it needs to perform its function at run time.
public interface IFactory<TProduct, TConfiguration>
{
TProduct AssembleProducts(TConfiguration configuration);
}
public abstract class Factory<TProduct, TConfiguration> : IFactory<TProduct, TConfiguration>
{
public abstract TProduct AssembleProducts(TConfiguration configuration);
}
public interface IGummyFactory : IFactory<GummyPackage, PackageConfiguration> {
}
public class GummyFactory : Factory<GummyPackage, PackageConfiguration>, IGummyFactory {
public override GummyPackage AssembleProducts(PackageConfiguration configuration) {
GummyPackage gummyPackage = new GummyPackage();
Random rnd = new Random();
for (int i = 1; i <= configuration.NumberOfContainersPerPackage; i++) {
GummyBearContainer container = new GummyBearContainer();
container.ContainerNumber = i;
container.ContainerType = configuration.ContainerType;
for (int b = 1; b <= configuration.NumberOfUnitsPerContainer; b++) {
GummyBear gummyBear = new GummyBear();
gummyBear.GummyID = b;
int flvr = rnd.Next(0, 5);
gummyBear.flavor = (GummyFlavor)flvr; // Pick a random flavor
container.GummyBears.Add(gummyBear); // Add Bear to the container
}
gummyPackage.Containers.Add(container); // Add container to the Package
}
return gummyPackage;
}
}
The fact that the package, container and gummy bears are created within the factory is an implementation concern and not really tight coupling since that relates to coupling to concrete dependencies (services) that apply functionality or behavior instead of simply storing run-time data.
This results in following Program after refactoring
class Program {
static void Main(string[] args) {
// Load the "Configuration" ...
PackageConfiguration configuration = new PackageConfiguration {
NumberOfContainersPerPackage = 24,
NumberOfUnitsPerContainer = 7,
ContainerType = "Bag",
};
IGummyFactory gummyFactory = new GummyFactory();
GummyPackage gummyPackage = gummyFactory.AssembleProducts(configuration);
OpenPackage(gummyPackage);
Console.ReadLine();
}
public static void OpenPackage(GummyPackage package) {
// Iterate over the Gummies
Console.WriteLine($"Opening Gummy Package: \n");
foreach (GummyBearContainer item in package.Containers) {
Console.WriteLine($"Opening Gummy {item.ContainerType} #{item.ContainerNumber}");
foreach (GummyBear bear in item.GummyBears) {
Console.WriteLine($"Gummy Number {bear.GummyID} is {bear.flavor.ToString()} flavor");
}
}
}
}
and changing to boxes is simply a matter of updating the configuration data source.
If you really can't use constructor injection then you could simply use Setter Injection this way :
var configuration = new GummyBearPackageConfiguration
{
NumberOfGummieBagsPerPackage = 24,
NumberOfGummiesPerBags = 7
};
GummyFactory gummyFactory = new GummyFactory();
gummyFactory.GummyBearPackageConfiguration = configuration;
IGummyPackage gummyPackage = gummyFactory.AssembleProducts();
GummyFactory could contain the following setter :
public GummyBearPackageConfiguration GummyBearPackageConfiguration { private get; set; }
The AssembleProducts() class depends on the concrete implementations of a GummyPackage, GummyBag, and GummyBear. Say in the future, management wants to change over from using GummyBags to mini Gummy cardboard "Boxes" because of new environmental rules. In the above scenario, I would need to crack open the GummyFactory.AssembleProducts() logic and re-wire the class to use boxes instead of Bags.
I'm not sure that this is a problem in which dependency injection could help. You could create a new factory MiniGummyFactory for this case so that would not require to change the AssembleProducts() function.

C# restricting use of a class

The below code does what I would like it to do. The code in the Main method looks and behaves exactly as desired. However, it would be preferable if the class UserMenu, Home and DropdownMenu2 could only be used by the HeaderNavigationMenu to protect other developers from trying to used them outside of the HeaderNavigationMenu class. Additionally most articles frown upon making everything public.
Question:
Is the design patter being used below appropriate or is there something better and more acceptable to use in this scenario?
Edit: The reason for this design.
I wanted the end user of HeaderNavigationMenu to just be able to use the dot notation to get a list of available options. This Architecture accomplishes this goal (ex: navigationMenu.DropdownMenu2.SelectOption3())
Wanted anyone else who eventually might need to edit the code to understand that the classes UserMenu, Home and DropDownMenu2 where very specifically designed to be implemented by HeaderNavigationMenu class.
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenu();
Home = new Home();
DropdownMenu2 = new DropdownMenu2();
}
public UsersMenu UsersMenu { get; set; }
public Home Home { get; set; }
public DropdownMenu2 DropdownMenu2 { get; set; }
}
public class UsersMenu
{
...
}
public class Home
{
...
}
public class DropdownMenu2
{
public void SelectOption3()
{
...
}
...
}
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
Home home = new Home();
}
Restrict access to the class constructors. If they are declared as "internal" then the classes may only be created by your code.
If you're looking to protect against the instantiation of UsersMenu, DropdownMenu2, and Home from outside HeaderNavigationMenu but still within the same project as HeaderNavigationMenu then there is a neat trick that can achieve this behavior. You can use public nested classes with private constructors which statically initialize their own factory methods. The basic template for this would be:
public class Outer{
private static Func<Inner> _innerFactory;
public Inner ExposedInner {get; private set;}
public Outer(){
// Force the static initializer to run.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);
// Call the newly created factory method instead of a regular constructor.
ExposedInner = _innerFactory();
}
public class Inner {
static Inner(){
// Initialize Outer's static factory method.
_innerFactory = () => new Inner();
}
// Inner cannot be instantiated (without reflection) because its constructor is private.
private Inner(){}
// This method is now exposed for anyone to use.
public void DoStuff(){ Console.WriteLine("Did stuff"); }
}
}
Here's this concept implemented in your example:
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// This line will no longer work because the constructors
// for the inner classes are private.
HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();
Console.ReadKey();
}
}
public class HeaderNavigationMenu
{
//Private factory methods that are statically initialized
private static Func<UsersMenuImpl> _createUsers;
private static Func<DropdownMenu2Impl> _createDropdown;
private static Func<HomeImpl> _createHome;
public HeaderNavigationMenu()
{
//Force the static constructors to run
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);
UsersMenu = _createUsers();
Home = _createHome();
DropdownMenu2 = _createDropdown();
}
public UsersMenuImpl UsersMenu { get; set; }
public HomeImpl Home { get; set; }
public DropdownMenu2Impl DropdownMenu2 { get; set; }
public class UsersMenuImpl
{
//Static constructor to make the class factory method
static UsersMenuImpl()
{
_createUsers = () => new UsersMenuImpl();
}
private UsersMenuImpl() { }
}
public class HomeImpl
{
//Static constructor to make the class factory method
static HomeImpl()
{
_createHome = () => new HomeImpl();
}
private HomeImpl() { }
}
public class DropdownMenu2Impl
{
//Static constructor to make the class factory method
static DropdownMenu2Impl()
{
_createDropdown = () => new DropdownMenu2Impl();
}
private DropdownMenu2Impl() { }
public void SelectOption3()
{
}
}
}
With this, you will still be able to use all the public properties of the inner classes however no one will be able to instantiate the inner classes from outside HeaderNavigationMenu and only HeaderNavigationMenu has access to the factory methods.
I don't really understand what your use case is and I've never coded like this but one way of only exposing the required behaviour of HeaderNavigationMenu would be to make the classes internal and the variables private and then expose only the SelectOption3() method, as below.
If you uncomment the line
//Home home = new Home();
you will get a compiler error.
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
//Home home = new Home();
}
}
public class HeaderNavigationMenu
{
UsersMenu usersMenu;
Home home;
DropdownMenu2 dropdownMenu2;
public HeaderNavigationMenu()
{
usersMenu = new UsersMenu();
home = new Home();
dropdownMenu2 = new DropdownMenu2();
}
public void DropdownMenu2SelectOption3()
{
dropdownMenu2.SelectOption3();
}
class UsersMenu
{
}
class Home
{
}
class DropdownMenu2
{
public void SelectOption3()
{
}
}
}
You could make UsersMenu, Home, and DropdownMenu2 public abstract classes. Then have private classes nested inside of HeaderNavigationMenu which extend the public abstract versions.
public abstract class UsersMenu
{
}
public abstract class Home
{
}
public abstract class DropdownMenu2
{
public void SelectOption3()
{
// Code for SelectOption3...
}
}
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenuImpl();
Home = new HomeImpl();
DropdownMenu2 = new DropdownMenu2Impl();
}
public UsersMenu UsersMenu { get; }
public Home Home { get; }
public DropdownMenu2 DropdownMenu2 { get; }
private class UsersMenuImpl : UsersMenu
{
}
private class HomeImpl : Home
{
}
private class DropdownMenu2Impl : DropdownMenu2
{
}
}
Fellow developers can see and use the UsersMenu, Home, and DropdownMenu2 abstract classes, but cannot create instances of them. Only HeaderNavigationMenu can.
Of course, another developer could always create their own classes deriving from the public abstract ones, but there is only so much you can do. UsersMenu, Home, and DropdownMenu2 have to be public in order to be public properties.

Inversion of Control and IoC Containers

I understand the whole concept behind inversion of control, but struggle to figure out where an IoC container comes in and how it may help.
Here's an example. Let's say we have the following interfaces ...
public interface IWarrior
{
string Name { get; }
IWeapon Weapon { get; }
void EquipWeapon(IWeapon weapon);
void Attack(ITarget target);
void DoVictoryDance();
}
public interface IWeapon
{
int AttackPower { get; }
}
public interface ITarget
{
int Health { get; }
int ArmorValue { get; }
int ReceiveAttack(int damage);
}
A IWarrior base class ...
public abstract class BaseWarrior : IWarrior
{
private static readonly Random Random = new Random();
protected BaseWarrior(string name, IWeapon weapon)
{
Name = name;
Weapon = weapon;
}
public string Name { get; }
public IWeapon Weapon { get; private set; }
public virtual void Attack(ITarget target)
{
var attackValue = Random.Next(0, Weapon.AttackPower + 1);
var damageDone = target.ReceiveAttack(attackValue);
Console.WriteLine($"{Name} did {damageDone} to {target.GetType().Name}");
if (target.Health <= 0)
DoVictoryDance();
}
public virtual void EquipWeapon(IWeapon weapon)
{
Weapon = weapon;
Console.WriteLine($"{Name} equips {weapon.GetType().Name}");
}
public abstract void DoVictoryDance();
}
The concrete warriors types ...
public class Samurai : BaseWarrior
{
public Samurai(string name, IWeapon weapon) : base(name, weapon)
{
}
public override void DoVictoryDance()
{
Console.WriteLine($"{Name} dances on top of the corpses of his foes.");
}
}
public class ChuckNorris : BaseWarrior
{
public ChuckNorris() : base("Chuck Norris", null)
{
}
public override void Attack(ITarget target)
{
var targetName = target.GetType().Name;
Console.WriteLine($"Chuck Norris stares at {targetName}. {targetName} collapses on the floor, dead. {targetName} never saw Chuck Norris.");
DoVictoryDance();
}
public override void EquipWeapon(IWeapon weapon)
{
Console.WriteLine("Chuck Norris needs no weapons you fool!");
}
public override void DoVictoryDance()
{
Console.WriteLine("Chuck Norris doesn't dance. He stares at you until you do it for him.");
}
}
The following weapons...
public class Sword : IWeapon
{
public int AttackPower => 10;
}
public class CrossBow : IWeapon
{
public int AttackPower => 15;
}
And finally a basic enemy:
public class Bear : ITarget
{
public int Health { get; private set; } = 100;
public int ArmorValue => 2;
public int ReceiveAttack(int damage)
{
var damageTaken = damage - ArmorValue;
if (damageTaken > 0)
Health -= damageTaken;
return damageTaken;
}
}
It's clear to me what inversion of control here is. My main class needs not know the concrete type of IWarrior, IWarrior never knows the concrete type of IWeapon or ITarget.
So this allows me to do something like ...
ITarget target = new Bear();
IWarrior warrior = new ChuckNorris();
warrior.Attack(target);
or ...
ITarget target = new Bear()
IWarrior warrior = new Samurai("Ben", new Sword());
warrior.Attack(target);
And I can see how it would be easier to have a container that just stores my objects so I don't "lose track of them" (don't want a lot of swords or weapons flying around for example, also those could be singletons).
Examples I've seen of IoC containers show something similar to this:
IocContainer container = new IocContainer();
container.Bind<IWarrior>().To<Samurai>();
container.Bind<IWeapon>().To<Sword>();
container.Bind<ITarget>().To<Bear>();
and then doing something like...
ITarget target = container.Get<ITarget>();
IWarrior warrior = container.Get<IWarrior>();
warrior.Attack(target);
But now I'm basically saying that my IWarrior is always a Samurai, that my IWeapon is always a Sword and that my ITarget is always a Bear.
That's not really what I wanted! I want to be able to create different IWarrior types with different IWeapon combinations and attacking a multitude of ITargets!
Maybe I'm misunderstanding something basic about how an IoC container works, but I have seen a few videos about them (using multiple libraries) and they all appear to basically say when I want "something" implementing interface XX, find in your container an object of concrete type YY. If you don't have one there yet, create one, save it, and send it back to me.
Can someone explain what the advantages of an IoC container are, give real examples of how it works and how one can preserve choice (by not limiting a IWarrior to Samurai as above for example)?

How I can to avoid IoC locator in next case?

In brief: I want resolve interface by prop in entity.
I have self hosted wcf and use ninject for DI.
My working code for example:
//program.cs
...
private static StandardKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<IDbConnectionFactory>().ToMethod(c =>
new OrmLiteConnectionFactory(
conString,
SqlServerDialect.Provider))
.InSingletonScope();
kernel.Bind<IControllerProccessor>().To<ControllerProccessor>()
.WhenInjectedInto<HelloWorldService>().WithConstructorArgument(kernel);
kernel.Bind<IControllerProccessor>().To<Vendor1Proccessor>()
.Named("vendor1");
kernel.Bind<IControllerProccessor>().To<Vendor2Proccessor>()
.Named("vendor2");
return kernel;
}
...
//IControllerProccessor.cs
public interface IControllerProccessor
{
SimpleController Ctr { get; set; }
bool sendMsg(string msg);
}
//Vendor1Proccessor.cs
public class Vendor1Proccessor : IControllerProccessor
{
public SimpleController Ctr {get; set;}
public bool sendMsg(string msg)
{
//specific to vendor code, for example calls to vendor1 SDK
Console.WriteLine("Controller id: {0} vendor:{1} recivied msg: {2}",
Ctr.Id,
"Vendor1Class",
msg);
return true;
}
}
//Vendor2Proccessor.cs
public class Vendor2Proccessor : IControllerProccessor
{
public SimpleController Ctr { get; set; }
public bool sendMsg(string msg)
{
//specific to vendor code, for example calls to vendor1 SDK
Console.WriteLine("Controller id: {0} vendor:{1} recivied msg: {2}",
Ctr.Id,
"Vendor2Class",
msg);
return true;
}
}
//ControllerProccessor.cs
public class ControllerProccessor : IControllerProccessor
{
public SimpleController Ctr {get; set;}
private readonly IKernel kernel;
public ControllerProccessor(IKernel _kernel)
{
kernel = _kernel;
}
public bool sendMsg(string msg)
{
var param = new Ninject.Parameters.PropertyValue("Ctr", Ctr);
return kernel.Get<IControllerProccessor>(Ctr.Vendor, param).sendMsg(msg);
}
}
//HelloWorldService.cs
public class HelloWorldService : IHelloWorldService
{
private readonly IDbConnectionFactory dbFactory;
private readonly IControllerProccessor ctrProccessor;
public HelloWorldService(IDbConnectionFactory _dbFactory, IControllerProccessor _ctrProccesor)
{
dbFactory = _dbFactory;
ctrProccessor = _ctrProccesor;
}
public bool sendMsgToAllControllers(string msg)
{
var db = dbFactory.Open();
var controllers = db.Select<SimpleController>();
foreach(var ctr in controllers)
{
ctrProccessor.Ctr = ctr;
ctrProccessor.sendMsg(msg);
}
db.Close();
return true;
}
}
//SimpleController.cs
[DataContract]
[Alias("SimpleController")]
public class SimpleController
{
[AutoIncrement]
[DataMember]
public int? Id { get; set; }
[DataMember]
public string Vendor { get; set; }
}
When I call sendMsgToAllControllers("TEST_MESSAGE") console output:
Controller id: 2 vendor:Vendor1Class recivied msg: TEST MESSAGE
Controller id: 3 vendor:Vendor2Class recivied msg: TEST MESSAGE
Controller id: 4 vendor:Vendor2Class recivied msg: TEST MESSAGE
How I can refactor above implementation so that it was in DI style, and dont use IoC locator anti-pattern (or in my case this is not anti-pattern) ?
In future I will move implementations (vendor1, vendor2, etc..) in separate assembly and do runtime binding. (Here I want to plugin system)
I also would appreciate any suggestions to improve my code. Very thanks.
Modification of implementation
After thinking process I came to the following:
I remove ControllerProccessor class instead I create ControllerProcessorFactory:
public class ControllerProcessorFactory : IControllerProcessorFactory
{
private readonly IResolutionRoot resolutionRoot;
public ControllerProcessorFactory(IResolutionRoot _resolutionRoot)
{
resolutionRoot = _resolutionRoot;
}
public IControllerProcessor Create(SimpleController ctr)
{
IControllerProcessor processor = resolutionRoot.Get<IControllerProcessor>(ctr.Vendor);
processor.Ctr = ctr;
return processor;
}
}
In Bindings:
kernel.Bind<IControllerProcessorFactory>().To<ControllerProcessorFactory>();
kernel.Bind<IControllerProcessor>().To<Vendor1Processor>()
.Named("vendor1");
kernel.Bind<IControllerProcessor>().To<Vendor2Processor>()
.Named("vendor2");
Usage (wcf class):
public class HelloWorldService : IHelloWorldService
{
private readonly IDbConnectionFactory dbFactory;
private readonly IControllerProcessorFactory ctrProcessorFactory;
public HelloWorldService(IDbConnectionFactory _dbFactory, IControllerProcessorFactory _ctrProcFactory)
{
dbFactory = _dbFactory;
ctrProcessorFactory = _ctrProcFactory;
}
public bool sendMsgToAllControllers(string msg)
{
var db = dbFactory.Open();
var controllers = db.Select<SimpleController>();
foreach(var ctr in controllers)
{
var ctrProcessor = ctrProcessorFactory.Create(ctr);
ctrProcessor.sendMsg(msg);
}
db.Close();
return true;
}
}
kernel.Get<IControllerProccessor>(Ctr.Vendor, param) is service locator,
but then again that doesn't always mean "it" is a problem. If it's easily interchangable, then it's not a big deal (well at least that's the opinion of some). Easily interchangeable? Create a specific factory interface whose only responsibility is to return all the processors.
The implementation then would consist of exactly return kernel.Get<IControllerProccessor>(Ctr.Vendor, param);. As long as the implementation is part of the composition root this specfici dependency on ninject is ok.
Shorter Alternative
Now, to be honest, your design looks superfluosly complicated to me, but then again, i don't know all the details. So for now i'm just using the name parameter, but you can easily add parameters (almost) as you like, it'll still work:
Just inject a Func<string, IControllerProcessor> instead of the kernel:
public ControllerProccessor(
Func<string,IControllerProcessor>> controllerProcessorFactory)
You can then specfiy a binding as follows:
private static IControllerProcessor CreateSpecificControllerProcessor(
IResolutionRoot resolutionRoot, string vendorName)
{
return resolutionRoot.Get<IControllerProcessor>(vendorName);
}
Bind<Func<IControllerProcessor>()
.ToConstant(vendorName => CreateSpecficiControllerProcessor(this.Kernel, vendorName));
Instead of specifying the Binding for the Func it might be possible to use Ninject.Extensions.Factory. Note however, that when you use this extension it won't be possible to Bind any Func manually anymore (the binding will be overriden by the extensions generation mechanism).
Look at Dynamic module loading in their documentation.
i.e.
kernel.Load("*.dll");
But make sure you do this at startup so you don't overwhelm your system at runtime.
As far as your pattern, I would recommend using the GetAll() method on the kernel as that will give you more flexibility and control
IEnumerable<IControllerProccessor> processors = kernel.GetAll<IControllerProccessor>();
foreach(var processor in processors)
processor.sendMsg(....);

Unity.AutoRegistration ?? Convention Based Registration Unity

My code is as follows
IUnityContainer container = new UnityContainer();
container
.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.ApplyAutoRegistration();
This is my first question.
I'm not sure whether I have used the LoadAssemblyFrom method correctly here:
ITest test = container.Resolve<ITest>();
When I try to compile I get the exception "ResolutionFailedException".
What am I doing wrong?
Thanks for your time in advance.
It appears that what you are looking for is this:
container.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.Include(If.ImplementsITypeName, Then.Register())
.ApplyAutoRegistration();
This will tell Unity.AutoRegistration to register all types where there is an interface with the same name, prefixed with I.
Here is a complete working console example showing how to set Unity up for registration by convention, then transfer control into the dependency injection world. You will have to add the Unity NuGet package for this to work.
Tested with Unity v3.5 and VS 2012.
#region
using System;
using Microsoft.Practices.Unity;
#endregion
namespace Demo___Unity
{
internal class Program
{
private static void Main(string[] args)
{
using (var container = new UnityContainer())
{
// Manual method.
//container.RegisterType<IEntryPoint, EntryPoint>();
//container.RegisterType<IInjected, Injected>();
// Set up registration by convention.
// http://blogs.msdn.com/b/agile/archive/2013/03/12/unity-configuration-registration-by-convention.aspx
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var controller = container.Resolve<IEntryPoint>();
controller.Main();
}
}
}
public interface IEntryPoint
{
string Name { get; set; }
void Main();
}
public class EntryPoint : IEntryPoint
{
private readonly IInjected Injected;
public EntryPoint(IInjected injected)
{
Injected = injected;
}
public void Main()
{
Console.Write("Hello, world!\n");
Injected.SubMain();
Injected2.SubMain();
Console.Write("[any key to continue]");
Console.ReadKey();
}
// Demonstrates property injection.
[Dependency]
public IInjected Injected2 { get; set; }
public string Name { get; set; }
}
public interface IInjected
{
void SubMain();
}
public class Injected : IInjected
{
public void SubMain()
{
Console.Write("Hello, sub world!\n");
}
public string Name { get; set; }
}
}

Categories