Another developer and had this conversation today:
Me: Dependency Injection is cool, lol.
Dennis: What happens when I need an instance of the DoStuff class and the only constructor I have is DoStuff( ISomeInterface interface1, ISomeInterface interface2 ) where the concrete types are completely different?
Me: ...
We use Unity as our preferred container. How would I register that when I need to resolve ISomeInterface that the concrete type can be two different types?
Take a look at the ParameterOverride class. It allows you to specify parameters by name:
container.Resolve<IDoStuff>(new ParameterOverrides<DoStuff> { { "interface1", new SomeInterfaceImpl() }, { "interface2", AnotherSomeInterfaceImpl() } });
Related
I have been doing my first Test Driven Development project recently and have been learning Ninject and MOQ. This is my first attempt at all this. I've found the TDD approach has been thought provoking, and Ninject and MOQ have been great. The project I am working on has not particularly been the best fit for Ninject as it is a highly configurable C# program that is designed to test the use of a web service interface.
I have broken it up into modules and have interfaces all over the shop, but I am still finding that I am having to use lots of constructor arguments when getting an implementation of a service from the Ninject kernel. For example;
In my Ninject module;
Bind<IDirEnum>().To<DirEnum>()
My DirEnum class;
public class DirEnum : IDirEnum
{
public DirEnum(string filePath, string fileFilter,
bool includeSubDirs)
{
....
In my Configurator class (this is the main entry point) that hooks all the services together;
class Configurator
{
public ConfigureServices(string[] args)
{
ArgParser argParser = new ArgParser(args);
IDirEnum dirEnum = kernel.Get<IDirEnum>(
new ConstructorArgument("filePath", argParser.filePath),
new ConstructorArgument("fileFilter", argParser.fileFilter),
new ConstructorArgument("includeSubDirs", argParser.subDirs)
);
filePath, fileFilter and includeSubDirs are command line options to the program. So far so good. However, being a conscientious kind of guy, I have a test covering this bit of code. I'd like to use a MOQ object. I have created a Ninject module for my tests;
public class TestNinjectModule : NinjectModule
{
internal IDirEnum mockDirEnum {set;get};
Bind<IDirEnum>().ToConstant(mockDirEnum);
}
And in my test I use it like this;
[TestMethod]
public void Test()
{
// Arrange
TestNinjectModule testmodule = new TestNinjectModule();
Mock<IDirEnum> mockDirEnum = new Mock<IDirEnum>();
testModule.mockDirEnum = mockDirEnum;
// Act
Configurator configurator = new Configurator();
configurator.ConfigureServices();
// Assert
here lies my problem! How do I test what values were passed to the
constructor arguments???
So the above shows my problem. How can I test what arguments were passed to the ConstructorArguments of the mock object? My guess is that Ninject is dispensing of the ConstuctorArguments in this case as the Bind does not require them? Can I test this with a MOQ object or do I need to hand code a mock object that implements DirEnum and accepts and 'records' the constructor arguments?
n.b. this code is 'example' code, i.e. I have not reproduced my code verbatim, but I think I have expressed enough to hopefully convey the issues? If you need more context, please ask!
Thanks for looking. Be gentle, this is my first time ;-)
Jim
There are a few problems with the way you designed your application. First of all, you are calling the Ninject kernel directly from within your code. This is called the Service Locator pattern and it is considered an anti-pattern. It makes testing your application much harder and you are already experiencing this. You are trying to mock the Ninject container in your unit test, which complicates things tremendously.
Next, you are injecting primitive types (string, bool) in the constructor of your DirEnum type. I like how MNrydengren states it in the comments:
take "compile-time" dependencies
through constructor parameters and
"run-time" dependencies through method
parameters
It's hard for me to guess what that class should do, but since you are injecting these variables that change at run-time into the DirEnum constructor, you end up with a hard to test application.
There are multiple ways to fix this. Two that come in mind are the use of method injection and the use of a factory. Which one is feasible is up to you.
Using method injection, your Configurator class will look like this:
class Configurator
{
private readonly IDirEnum dirEnum;
// Injecting IDirEnum through the constructor
public Configurator(IDirEnum dirEnum)
{
this.dirEnum = dirEnum;
}
public ConfigureServices(string[] args)
{
var parser = new ArgParser(args);
// Inject the arguments into a method
this.dirEnum.SomeOperation(
argParser.filePath
argParser.fileFilter
argParser.subDirs);
}
}
Using a factory, you would need to define a factory that knows how to create new IDirEnum types:
interface IDirEnumFactory
{
IDirEnum CreateDirEnum(string filePath, string fileFilter,
bool includeSubDirs);
}
Your Configuration class can now depend on the IDirEnumFactory interface:
class Configurator
{
private readonly IDirEnumFactory dirFactory;
// Injecting the factory through the constructor
public Configurator(IDirEnumFactory dirFactory)
{
this.dirFactory = dirFactory;
}
public ConfigureServices(string[] args)
{
var parser = new ArgParser(args);
// Creating a new IDirEnum using the factory
var dirEnum = this.dirFactory.CreateDirEnum(
parser.filePath
parser.fileFilter
parser.subDirs);
}
}
See how in both examples the dependencies get injected into the Configurator class. This is called the Dependency Injection pattern, opposed to the Service Locator pattern, where the Configurator asks for its dependencies by calling into the Ninject kernel.
Now, since your Configurator is completely free from any IoC container what so ever, you can now easily test this class, by injecting a mocked version of the dependency it expects.
What is left is to configure the Ninject container in the top of your application (in DI terminology: the composition root). With the method injection example, your container configuration would stay the same, with the factory example, you will need to replace the Bind<IDirEnum>().To<DirEnum>() line with something as follows:
public static void Bootstrap()
{
kernel.Bind<IDirEnumFactory>().To<DirEnumFactory>();
}
Of course, you will need to create the DirEnumFactory:
class DirEnumFactory : IDirEnumFactory
{
IDirEnum CreateDirEnum(string filePath, string fileFilter,
bool includeSubDirs)
{
return new DirEnum(filePath, fileFilter, includeSubDirs);
}
}
WARNING: Do note that factory abstractions are in most cases not the best design, as explained here.
The last thing you need to do is to create a new Configurator instance. You can simply do this as follows:
public static Configurator CreateConfigurator()
{
return kernel.Get<Configurator>();
}
public static void Main(string[] args)
{
Bootstrap():
var configurator = CreateConfigurator();
configurator.ConfigureServices(args);
}
Here we call the kernel. Although calling the container directly should be prevented, there will always at least be one place in your application where you call the container, simply because it must wire everything up. However, we try to minimize the number of times the container is called directly, because it improves -among other things- the testability of our code.
See how I didn't really answer your question, but showed a way to work around the problem very effectively.
You might still want to test your DI configuration. That's very valid IMO. I do this in my applications. But for this, you often don't need the DI container, or even if your do, this doesn't mean that all your tests should have a dependency on the container. This relationship should only exist for the tests that test the DI configuration itself. Here is a test:
[TestMethod]
public void DependencyConfiguration_IsConfiguredCorrectly()
{
// Arrange
Program.Bootstrap();
// Act
var configurator = Program.CreateConfigurator();
// Assert
Assert.IsNotNull(configurator);
}
This test indirectly depends on Ninject and it will fail when Ninject is not able to construct a new Configurator instance. When you keep your constructors clean from any logic and only use it for storing the taken dependencies in private fields, you can run this, without the risk of calling out to a database, web service or what so ever.
I hope this helps.
i'm looking for a larger example of dependency injection and how it can be implemented. If class A depends on class B and passes a reference of class C to B's constructor, must not class A also take a reference to class C in it's constructor? This means that the main method in the application should create all classes really, which sounds wierd?
I understand that using DI frameworks we can have it in XML files somehow, but that sounds like it could be hard to quickly see what type that really is instanciated? Especially if it a very large application.
You are correct and each DI framework has a different way of managing it.
Some use attributes on the properties etc to denote dependency and then "automagically" supply an instance of the correct type, while others (say castle windsor for .net) allow xml configuration, fluent or other methods for "wiring up" the dependency graph.
Also no, class A takes a built reference to an instance of B which was built using an instance of C. A needs to know nothing about C unless exposed via B.
public class C { }
public class B { public B(C c) { ... }}
public class A { public A(B b) { ... }}
// manual wireup
C c = new C();
B b = new B(c);
A a = new A(b);
// DI framework
InversionOfControlContainer container = new InversionOfControlContainer(... some configuration);
A a = container.ResolveInstanceOf<A>();
// container dynamically resolves the dependencies of A.
// it doesnt matter if the dependency chain on A is 100 classes long or 3.
// you need an instance of A and it will give you one.
Hope that helps.
to answer your question about classes A,B,and C, A only needs a reference to B.
Most DI frameworks do not require you to use XML for configuration. In fact, many people prefer not to use it. You can explicitly set things up in code, or use some kind of conventions or attributes for the container to infer what objects should fulfil dependencies.
Most DI frameworks have a facility for "lazy loading" to avoid the creation of every single class up front. Or you could inject your own "factory or builder" objects to create things closer to the time when they will be used
You've not said what language you are using. My example below is in C# using the Unity container. (obviously normally you would use interfaces rather than concrete types):
container = new UnityContainer();
container.RegisterType<C>();
container.RegisterType<B>();
A a = container.Resolve<A>();
here's a few examples from the PHP Language, hope this helps you understand
class Users
{
var $Database;
public function __construct(Database $DB)
{
$this->Database = $DB;
}
}
$Database = Database::getInstance();
$Users = new Users($Database);
From this example the new keyword is used in the method getInstance(), you can also do
$Users = new Users(Database::getInstance());
Or another way to tackle this is
class Users
{
/*Dependencies*/
private $database,$fileWriter;
public function addDependency($Name,$Object)
{
$this->$Name = $Object;
return $this;
}
}
$Users = new Users();
$Users->addDependency('database',new Database)->addDependency('fileWriter',new FileWriter);
Update:
to be honest, I never use Dependency Injection as all its doing is passing objects into classes to create a local scope.
I tend to create a global entity, and store objects within that so there only ever stored in 1 variable.
Let me show you a small example:
abstract class Registry
{
static $objects = array();
public function get($name)
{
return isset(self::$objects[$name]) ? self::$objects[$name] : null;
}
public function set($name,$object)
{
self::$objects[$name] = $object;
}
}
Ok the beauty of this type of class is
its very lightweight
it has a global scope
you can store anything such as resources
When your system loads up and your including and initializing all your objects you can just store them in here like so:
Registry::add('Database',new Database());
Registry::add('Reporter',new Reporter());
Where ever you are within your runtime you can just use this like a global variable:
class Users
{
public function getUserById($id)
{
$query = "SELECT * FROM users WHERE user_id = :id";
$resource = Registry::get("Database")->prepare($query);
$resource->bindParam(':id',$id,PDO::PARAM_INT);
if($resource->execute())
{
//etc
}else
{
Registry::get('Reporter')->Add("Unable to select getUserById");
}
}
}
i see this way of object passing is much cleaner
If anybody is still looking for a good example which shows DI without IoC Containers (poor man's DI) and also with IoC Container (Unity in this example) and registering the types in code and also in XML you can check this out: https://dannyvanderkraan.wordpress.com/2015/06/15/real-world-example-of-dependeny-injection/
If I have a class like so:
public SomeClass : ISomeClass
{
public SomeClass(IInjectedDependency dependency, bool someArbitraryValue) {}
}
How can I set this up with SM to inject the dependency but specify the arbitrary value?
I've tried the following but it doesn't work (I get "There is no argument of type System.Boolean for concrete type IInjectedDependency"):
ObjectFactory.Initialize(x =>
{
x.For<IInjectedDependency>().Use<ConcreteDependency>();
x.For<ISomeClass>().Use<SomeClass>().Ctor<bool>("someArbitraryValue").Is(false);
});
I think this is only for a constructor with one parameter and thats why it doesn't work with multiple (I've used it for one param constructors and it works fine).
TIA!
m
Works like it should. Problem on my end.
I am using unity as my IoC container. I am trying to implement a type of IProviderRepository. The concrete implementation has a constructor that accepts a type of IRepository. When I remove the constructor parameter from the concrete implementation everything works fine. I am sure the container is wired correctly. When I try to create the concrete object with the constructor I receive the following error:
"The current build operation (build key Build Key[EMRGen.Infrastructure.Data.IRepository1[EMRGen.Model.Provider.Provider], null]) failed: The current type, EMRGen.Infrastructure.Data.IRepository1[EMRGen.Model.Provider.Provider], is an interface and cannot be constructed. Are you missing a type mapping? (Strategy type BuildPlanStrategy, index 3)".
Is it possible to achieve the above mention functionality with Unity? Namely have Unity infer a concrete type from the Interface and also inject the constructor of the concrete type with the appropriate concrete object based on constructor parameters. Below is sample of my types defined in Unity and a skeleton class listing for what I want to achieve. IProviderRepository is implemented by ProviderRepository which has a constructor that expects a type of IRepository.
<typeAlias alias="ProviderRepositoryInterface" type="EMRGen.Model.Provider.IProviderRepository, EMRGen.Model" />
<typeAlias alias="ProviderRepositoryConcrete" type="EMRGen.Infrastructure.Repositories.Providers.ProviderRepository, EMRGen.Infrastructure.Repositories" />
<typeAlias alias="ProviderGenericRepositoryInterface" type="EMRGen.Infrastructure.Data.IRepository`1[[EMRGen.Model.Provider.IProvider, EMRGen.Model]], EMRGen.Infrastructure" />
<typeAlias alias="ProviderGenericRepositoryConcrete" type="EMRGen.Infrastructure.Repositories.EntityFramework.ApplicationRepository`1[[EMRGen.Model.Provider.Provider, EMRGen.Model]], EMRGen.Infrastructure.Repositories" />
<!-- Provider Mapping-->
<typeAlias alias="ProviderInterface" type="EMRGen.Model.Provider.IProvider, EMRGen.Model" />
<typeAlias alias="ProviderConcrete" type="EMRGen.Model.Provider.Doctor, EMRGen.Model" />
Illustrate the call being made inside my class:
public class PrescriptionService
{
PrescriptionService()
{
IUnityContainer uc = UnitySingleton.Instance.Container;
UnityServiceLocator unityServiceLocator = new UnityServiceLocator(uc);
ServiceLocator.SetLocatorProvider(() => unityServiceLocator);
IProviderRepository pRepository =
ServiceLocator.Current.GetInstance<IProviderRepository>();
}
}
public class GenericRepository<IProvider> : IRepository<IProvider>
{
}
public class ProviderRepository : IProviderRepository
{
private IRepository<IProvider> _genericProviderRepository;
//Explict public default constructor
public ProviderRepository(IRepository<IProvider> genericProviderRepository)
{
_genericProviderRepository = genericProviderRepository;
}
}
What you want to do is possible, but you need to tell Unity how to map from interfaces to concrete types. AFAICT, your current configuration registers a lot of types, but doesn't specify how they relate to each other.
That said, static Service Locator is an anti-pattern. Consider changing your code to use proper Constructor Injection instead. That would also simplify your code considerably:
public class PrescriptionService
{
private readonly IProviderRepository pRepository;
public PrescriptionService(IProviderRepository pRepository)
{
if (pRepository == null)
{
throw new ArgumentNullException("pRepository");
}
this.pRepository = pRepository;
}
}
Using Unity, you would be able to wire it up like this:
var container = new UnityContainer();
container.RegisterType<PrescriptionService>();
container.RegisterType<IProviderRepository, ProviderRepository>();
container.RegisterType<IRepository<IProvider>, MyRepository<IProvider>>();
var ps = container.Resolve<PrescriptionService>();
Configure the container and resolve all components in the application's Composition Root.
You should only use XML configuration if you need to be able to change certain components without recompiling your application.
High Level
With StructureMap, Can I define a assembly scan rule that for an interface IRequestService<T> will return the object named TRequestService
Examples:
FooRequestService is injected when IRequestService<FooRequest> is requested
BarRequestService is injected when IRequestService<BarRequest> is requested
Details
I have a generic interface defined
public interface IRequestService<T> where T : Request
{
Response TransformRequest(T request, User current);
}
and then I have multiple Request objects that implement this interface
public class FooRequestService : IRequestService<Foo>
{
public Response TransformRequest(Foo request, User current) { ... }
}
public class BarRequestService : IRequestService<Bar>
{
public Response TransformRequest(Bar request, User current) { ... }
}
Now I am at the point where I need to register these classes so that StructureMap knows how to create them because in my controller I want have the following ctor (which I want StructureMap to inject a FooRequestService into)
public MyController(IRequestService<Foo> fooRequestService) { ... }
Right now to get around my issue I have implemented an empty interface and instead of having the FooRequestService implement the generic interface I have it implement this empty interface
public interface IFooRequestService : IRequestService<Foo> { }
Then my controllers ctor looks like so, which works with StructureMaps' Default Convention Scanner
public MyController(IFooRequestService fooRequestService) { ... }
How could I create a rule with StructureMap's assembly scanner to register all objects named TRequestService with IRequestService<T> (where T = "Foo", "Bar", etc) so that I don't have to create these empty Interface definitions?
To throw something else into the mix, where I am handling StructureMap's assembly scanning does not have any reference to the assembly that defines IRequestService<T> so this has to use some sort of reflection when doing this. I scanned the answer to "StructureMap Auto registration for generic types using Scan" but it seems as though that answer requires a reference to the assembly that contains the interface definition.
I am on the path of trying to write a custom StructureMap.Graph.ITypeScanner but I am kind of stuck on what to do there (mainly because I have little experience with reflection).
You are on the right path with the scanner. Thankfully there is one built into StructureMap. Unfortunately it is not yet, as of this writing, released. Get the latest from trunk and you will see a few new things available within the scanner configuration. An example for your needs is below.
public class MyRegistry : Registry
{
public MyRegistry()
{
Scan(x =>
{
x.TheCallingAssembly();
//x.AssembliesFromApplicationBaseDirectory();
x.WithDefaultConventions();
x.ConnectImplementationsToTypesClosing(typeof (IRequestService<>));
});
}
}
First you need to tell the scanner configuration which assemblies to include in the scan. The commented AssembliesFromApplicationBaseDirectory() method also might help if you are not doing a registry per assembly.
To get your generic types into the container use ConnectImplementationsToTypesClosing.
For an example on how to setup use registries when setting up the container see:
http://structuremap.sourceforge.net/ConfiguringStructureMap.htm
If you like you can skip using registries in general and just do a scan within ObjectFactory.Initialize.
Hope this helps.