Real world example of Dependency Injection based on run-time values

Synopsis: This is a  real world example from my work in which I solved a Dependency Injection problem, where the dependencies are based on run-time values, with an Abstract Factory. Get the example from my GitHub: https://github.com/DannyvanderKraan/EntityActionAbstractFactory

Intro

Last time I introduced Dependency Injection with my blogpost Real World Example of Dependency Injection. It showed how 3rd party libraries, which checked if a smartcard  was still present in a  card reader, could be swapped. Even without recompiling eventually by using Unity’s ability to resolve dependencies from the configuration file. But what if your dependency depends itself on a run-time value and you can’t tell until the application is running which dependency to inject?

Case

I want to enable the end user to assemble their start screen themselves. One of these aspects of the start screen that an end user is able to adjust is that they can choose to see and operate certain Actions (like “Add”, “Remove”) on certain Entities (like “Patient”, “Contact”). To accommodate this, if you are not careful with your architecture, your application could be riddled with code like this:


switch (entityAction.EntityID)
{
case 1: //Patient
switch (entityAction.ActionID)
{
case 1: //Add
return new PatientAdd();
case 2: //Remove
return new PatientRemove();
default:
return null;
}
case 2: //Contact
switch (entityAction.ActionID)
{
case 1: //Add
return new ContactAdd();
case 2: //Remove
return new ContactRemove();
default:
return null;
}
default:
return null;
}

Listing 1

And as we know, switches are often code smells (Clean Code p37-39 by Robert C. Martin). In this case this logic will have to be written in classes which are also responsible for a lot of other things, breaking the Single Responsibility Principle. In addition whenever another Entity or another Action has to be added a developer needs to add new cases to these switches, violating the Open/closed principle. So what  can we do about this? How about some Dependency Injection in conjuction with the Abstract Factory pattern? Please observe the model below:
2015-06-30 12_47_23-Realworld DI based on runtime values.docx - Microsoft Word
Figure 1

In the figure above you see the  abstracted factory in the form of an interface called IEntityActionViewModelFactory with its concrete implementation called (surprisingly) EntityActionViewModelFactory. The CreatEntityActionViewModel method actually contains the code at Listing 1. It expects any class that implements IEntityAction, which our concrete implementation called EntityAction does. And the factory method returns any class which implements IEntityActionViewModel. This allows calling classes which use this factory to call the method Operate on the returned class, despite which concrete implementation it really is and what it does exactly. For the sake of simplicity there are four concrete implementations in this example: PatientAdd, PatientRemove, ContactAdd, ContactRemove. Their Operate method has the following code to test if it works (change class in section nameof accordingly): Console.WriteLine("Class: {0}, Method: {1}", nameof(PatientAdd), nameof(Operate))

In the Main method of the Program class of a  Console Application for example you could now write the following code:

IEntityAction patientAdd = new EntityAction()
{
EntityID = 1,
EntityName = "Patient",
ActionID = 1,
ActionName = "Add"
};
IEntityAction patientRemove = new EntityAction()
{
EntityID = 1,
EntityName = "Patient",
ActionID = 2,
ActionName = "Remove"
};
IEntityAction contactAdd = new EntityAction()
{
EntityID = 2,
EntityName = "Contact",
ActionID = 1,
ActionName = "Add"
};
IEntityAction contactRemove = new EntityAction()
{
EntityID = 2,
EntityName = "Contact",
ActionID = 2,
ActionName = "Remove"
};
IEntityActionViewModel entityActionViewModel;
Factory = new EntityActionViewModelFactory();
Console.WriteLine("---{0}---", nameof(EntityActionViewModelFactory));
entityActionViewModel = Factory.CreateEntityActionViewModel(patientAdd);
entityActionViewModel?.Operate();
entityActionViewModel = Factory.CreateEntityActionViewModel(patientRemove);
entityActionViewModel?.Operate();
entityActionViewModel = Factory.CreateEntityActionViewModel(contactAdd);
entityActionViewModel?.Operate();
entityActionViewModel = Factory.CreateEntityActionViewModel(contactRemove);
entityActionViewModel?.Operate();

Listing 2

Note: Don’t forget the following static property in class Program: static IEntityActionViewModelFactory Factory { get; set; }

This will produce the following result:

2015-06-30 13_25_33-file____D__Research_EntityActionAbstractFactory_EntityActionAbstractFactory_bin_

Are we done now?

Let’s Get Rid of the Switch!

As mentioned before switches are (potential) code smells. Hiding them deep down at one central place somewhere in a factory is often the right way to go, but the Open/closed principle was still at risk here. The observant reader might’ve spotted the EntityName and ActionName properties in Figure 1. It isn’t used up until now, is it? So what gives? Take the following steps (and bear with me cause I am just using this as a bridge to the solution with Unity):

  1. Add a class named ConcatEntityActionViewModelFactory.
  2. Have ConcatEntityActionViewModelFactory implement IEntityActionViewModelFactory.
  3. Add the following code in the method CreatEntityActionViewModel:

    return (IEntityActionViewModel)Activator.CreateInstance(
    Type.GetType(
    String.Format("{0}.{1}",
    this.GetType().Namespace,
    entityAction.EntityName + entityAction.ActionName)));

    Listing 3

I utilize reflection by using the CreateInstance method from the Activator class. This method wants a Type. How do I know which Type to throw in there? We all agree we name the classes with the following convention [Entity][Action] and that is why the class is called PatientAdd for instance. In the Domain model EntityAction we set these names (retrieved from a database or whatever), see listing 2.  The identifying part is a string now, so Type.GetType is used to get a Type by a string (for instance: “PatientAdd”).
Make agreements about the namespace as well, or provide it somehow, because GetType expects the full name (in this case: “EntityActionAbstractFactory.PatientAdd”).

Note: Naming conventions are inherently brittle. But I figured as long as it’s documented and communicated clearly, then I prefer this method over the switch case. But I’ll let that up to you to decide.

The output is about the  same, so I don’t need to include another screenshot here.

So are we done now?? Well, this is “poor man’s Dependency Injection” and it is  a  good idea to use IoC containers (like Castle Windsor, Spring.NET or Unity) in production applications because of various benefits (which is not part of this post’s focus). I choose Unity.

The final solution with Unity

To conclude this example I wanted to show you how I eventually implemented the solution the way I felt is best. By utilizing Unity’s capability to map concrete implementations to the same abstraction, by naming them. Having the naming convention in place I did the following steps:

  1. Add a static property to class Program like so: public static IUnityContainer Container { get; set; }
  2. Add the following code in the method Main of class Program:

    Container = new UnityContainer();
    Container.RegisterType<IEntityActionViewModelFactory, ContainerEntityActionViewModelFactory>();
    Container.RegisterType<IEntityAction, EntityAction>();
    Container.RegisterType<IEntityActionViewModel, PatientAdd>(nameof(PatientAdd));
    Container.RegisterType<IEntityActionViewModel, PatientRemove>(nameof(PatientRemove));
    Container.RegisterType<IEntityActionViewModel, ContactAdd>(nameof(ContactAdd));
    Container.RegisterType<IEntityActionViewModel, ContactRemove>(nameof(ContactRemove));
    Factory = Container.Resolve();
    Console.WriteLine("---{0}---", nameof(ContainerEntityActionViewModelFactory));
    IEntityAction resolvedPatientAdd = Container.Resolve();
    resolvedPatientAdd.EntityID = 1;
    resolvedPatientAdd.EntityName = "Patient";
    resolvedPatientAdd.ActionID = 1;
    resolvedPatientAdd.ActionName = "Add";
    IEntityAction resolvedPatientRemove = Container.Resolve();
    resolvedPatientRemove.EntityID = 1;
    resolvedPatientRemove.EntityName = "Patient";
    resolvedPatientRemove.ActionID = 2;
    resolvedPatientRemove.ActionName = "Remove";
    IEntityAction resolvedContactAdd = Container.Resolve();
    resolvedContactAdd.EntityID = 2;
    resolvedContactAdd.EntityName = "Contact";
    resolvedContactAdd.ActionID = 1;
    resolvedContactAdd.ActionName = "Add";
    IEntityAction resolvedContactRemove = Container.Resolve();
    resolvedContactRemove.EntityID = 2;
    resolvedContactRemove.EntityName = "Contact";
    resolvedContactRemove.ActionID = 2;
    resolvedContactRemove.ActionName = "Remove";
    entityActionViewModel = Factory.CreateEntityActionViewModel(resolvedPatientAdd);
    entityActionViewModel?.Operate();
    entityActionViewModel = Factory.CreateEntityActionViewModel(resolvedPatientRemove);
    entityActionViewModel?.Operate();
    entityActionViewModel = Factory.CreateEntityActionViewModel(resolvedContactAdd);
    entityActionViewModel?.Operate();
    entityActionViewModel = Factory.CreateEntityActionViewModel(resolvedContactRemove);
    entityActionViewModel?.Operate();

    Listing 4
  3. Add a class named ContainerEntityActionViewModelFactory.
  4. Have ContainerEntityActionViewModelFactory implement IEntityActionViewModelFactory.
  5. Add the following code in the method CreatEntityActionViewModel:

    return Program.Container.Resolve(
    entityAction.EntityName + entityAction.ActionName);

    Listing 5

At listen 4 you can see the creation of an instance of a new UnityContainer. Then all the necessary types are registered in the container (as the factory register ContainerEntityActionViewModelFactory this time). But as several different types for the interface IEntityActionViewModel are registered the overload of RegisterType which expects a string is used, naming the registration.

At listen 5 you can see eventually how the different registered types are resolved at runtime inside the factory. In my opinion that single line of code which I don’t have to change after every addition of an entity or an  action seems like a good trade off with having a  naming convention [Entity][Action]  in place. So the switch is  definably out. I also find this line of code better looking than the verbose code of having to create an instance via reflection.

The output looks about the same, so I don’t need to put another screenshot here.

Note: In “Dependency Injection in .NET” Mark Seemann warns  about the brittle nature of using the names of registrations directly and urges to take a good look at your design before using it.

Conclusion

As always thank you for reading. The Abstract Factory is the way to go with deciding dependencies based on run-time values. The switch case still itched me, so I decided to refactor it a  little bit further, but that is not absolutely necessary of course. Any questions, feedback, likes, dislikes, do not hesitate to comment!

Get the example from my GitHub (perhaps it’s fun to change the implementation of EntityActionViewModelFactory to use Unity): https://github.com/DannyvanderKraan/EntityActionAbstractFactory

* Sometimes certain characters disappear from the code blocks. The code is on my github, so please check there, while I sort this out.

Advertisements

About Danny

Bachelor in Commercial ICT MCTS Winforms .NET 2.0 MCTS ASP.NET 3.5 PSM I
This entry was posted in .NET programming, C# 6.0, Dependency Injection, Software design patterns and tagged , , , , , . Bookmark the permalink.

2 Responses to Real world example of Dependency Injection based on run-time values

  1. Pingback: Real World Example of Adding Auditing With Dependency Injection’s Interception | Danny van der Kraan's Blog

  2. Pingback: Unit Testing made easy with Dependency Injection | Danny van der Kraan's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s