I'm using Ninject for constructor injection to create my concrete objects on the fly. However, I have a scenario where the class contains a method that accepts a string. Based on the value of the string, I would like to obtain a specific class. I accomplished this by creating a factory class to return the concrete class but wasn't sure if this was the best way. Any suggestions?
//Service class
public int GetEmployeeVacationDays(string employeeType)
{
IEmployee employee = EmployeeFactory.CreateEmployee(employeeType);
return employee.VacationDays();
}
//Factory class
public static IEmployee CreateEmployee(string employeeType)
{
if(employeeType == "Salary")
{
return new SalariedEmployee();
}
else
{
return new HourlyEmployee();
}
}
Dependency injection doesn't apply to your scenario. That's the factory pattern. You could configure Ninject to use the factory pattern to provide dependencies if you will for certain objects.
In fact you could entire replace the factory pattern with named bindings:
Bind<IEmployee>().To<FooEmployee>().Named("foo");
Bind<IEmployee>().To<BarEmployee>().Named("bar");
Bind<IEmployee>().To<BazEmployee>().Named("baz");
assuming that employeeType is a valid class name:
return System.Activator.CreateInstance(Type.GetType(className))
Related
I have an abstract factory like this.
public abstract class AbstractFactory
{
public abstract ISyncService GetSyncService(EntityType entityType);
}
And I have its concrete implementation like this.
public class SyncFactory : AbstractFactory
{
private readonly IOperatorRepository _operatorRepository;
public SyncFactory( IOperatorRepository operatorRepository)
{
_operatorRepository = operatorRepository;
}
public override ISyncService GetSyncService(EntityType entityType)
{
return new OperatorSyncService(_operatorRepository);
}
}
This concrete factory is accessed in a method like this.
public void MethodTobeTested()
{
var syncService =
new SyncFactory(_operatorRepository).GetSyncService(entityType);
}
Now I need to write a unit test for MethodTobeTested().
I mocked the return value of the GetSyncService() like this. But it's calling the actual OperatorSyncService, not the mock. I need this mock to mock another method inside OperatorSyncService
private Mock<SyncFactory> _syncServiceMock;
_syncServiceMock = new Mock<SyncFactory>();
_syncServiceMock.Setup(m => m.GetSyncService(operator)).Returns(_operatorSyncServiceMock.Object);
Any idea on how to resolve this?
In your SyncFactory implementation you inject an instance of IOperatorRepository. This is great because it allows you to inject a different version if needs be and creates a seem for you to use a mock implementation of IOperatorRepository.
You have also made an abstract factory which looks good but it looks like the problem is with your usage of the factory;
var syncService =
new SyncFactory(_operatorRepository).GetSyncService(entityType);
In your MethodToBeTested you create a concrete implementation of SyncFactory, this make the point of the abstract factory a little redundent since you cannot inject a different implementation. I don't know where you are geting your _operatorRepository instance from but I can see two ways forward.
In the constructor of the class that contains MethodToBeTested add a parameter that takes an instance of your abstract factory, then get your MethodToBeTested to use this injected factory instead of creating a new one, this would allow you to mock the whole factory - this is my recommended approach because the class containing MethodToBeTested would no longer need to know how to create a factory instance which it shouldn't if you are following the single responsibility principle. There would be no dependence on any concrete implementation.
As above but instead inject IOperatorRepository rather than the factory, you can then inject a mock IOperatorRepository but I would advise against this since you've done such a good job of creating all your abstractions to then cast this work aside and "new up" an instance of syncFactory and creating a concrete dependency
MethodToBeTested is tightly coupled to SyncFactory because the method is manually creating a new instance of SyncFactory. This makes mocking the dependency very difficult.
Assuming
public class ClassToBeTested {
public void MethodTobeTested() {
var syncService = new SyncFactory(_operatorRepository).GetSyncService(entityType);
//...other code
}
}
ClassToBeTested should be refactored to
public class ClassToBeTested {
private readonly AbstractFactory syncFactory;
public ClassToBeTested (AbstractFactory factory) {
this.syncFactory = factory
}
public void MethodTobeTested() {
var syncService = syncFactory.GetSyncService(entityType);
//...other code
}
}
This will allow the dependency to be mocked and injected into the class to be tested and accessed by the method to be tested. The class to be tested now only needs to know what it needs to know. It now no longer needs to be aware of IOperatorRepository.
The new in the method MethodTobeTested creates new instance so no mock can be injected. Inject the factory e.g. as parameter so it can be mocked in the test.
public void MethodTobeTested(AbstractFactory factory)
{
EntityType entityType = null;
var syncService = factory.GetSyncService(entityType);
}
[TestMethod]
public void Method_Condition_Result()
{
// Arrange
TestedClass tested = new TestedClass();
Mock<ISyncService> syncServiceMock = new Mock<ISyncService>();
Mock<AbstractFactory> factoryMock = new Mock<AbstractFactory>();
factoryMock.Setup(f => f.GetSyncService(It.IsAny<EntityType>())).Returns(syncServiceMock.Object);
// Act
tested.MethodTobeTested(factoryMock.Object);
// Assert
// ...
}
I have a console application where I need to execute a certain feature based on input from the user. If the user puts in "feature 1" -> I execute Feature 1, and so on.
I am trying to write this project as clean and as generic as possible, and I want to use the IoC and SOLID concepts, and i am kinda stuck.
What I have so far:
public interface IFeature
{
String execFeature();
}
and
interface IFeatureFactory
{
IFeature createFeature(String input);
}
My first thought was just to have a switch case on the concrete Factory class about the input from the user, and create the concrete Feature accordingly, but I bet there is a better way to do it with IoC.
I read about Ninject factory extension, but didn't understand how to use it in my project.
Whatis the best way to do the factory pattern with IoC/Ninject?
If your IFeature implementations does not have other dependencies than using your approach is fine and very simple. For example lets say you have 2 implementations of IFeature - SomeFeature and OtherFeature that both have parametersless constructor. Your factory implementation as you suggest would be something like that:
public class FeatureFactory: IFeatureFactory
{
IFeature CreateFeature(string input)
{
if(input=="SomeFeature")
{
return new SomeFeature();
}
else
{
return new OtherFeature ();
}
}
}
However when your IFeature implementations have their own dependencies using this approach you lose the point of using Ninject and IoC.
For example lets say That SomeFeature looks something like that:
public class SomeFeature : IFeature
{
private readonly IDependency1 _dependency1;
private readonly IDependency2 _dependency2;
public SomeFeature (IDependency1 dependency1, IDependency2 dependency2)
{
_dependency1=dependency1;
_dependency2=dependency2;
}
string execFeature()
{
//Some code here...
}
}
And OtherFeature is similar...
public class OtherFeature: IFeature
{
private readonly IDependency1 _dependency1;
private readonly IDependency2 _dependency2;
public OtherFeature(IDependency1 dependency1, IDependency2 dependency2)
{
_dependency1=dependency1;
_dependency2=dependency2;
}
string execFeature()
{
//Some code here...
}
}
Now your factory would become something like that:
public class FeatureFactory: IFeatureFactory
{
IFeature CreateFeature(string input)
{
if(input=="SomeFeature")
{
return new SomeFeature(new Dependency1Implementation(), new Dependency2Implementation());
}
else
{
return new OtherFeature(new Dependency1Implementation(), new Dependency2Implementation());
}
}
}
This is the place when you can use the power of the ninject.extensions.factory
by using the container to solve this dependencies for you.(This dependencies can have their own dependencies and it can get messy very quickly).
As other mentioned you can bind every IFeature implementation using named binding.
Bind<IFeature>().To<SomeFeature>().Named("SomeFeature");
Bind<IFeature>().To<OtherFeature>().Named("OtherFeature");
Of Course you should bind other dependencies as well
Bind<IDependency1>().To<Dependency1Implementation>();
Bind<IDependency2>().To<Dependency2Implementation>();
And then bind the IFeatureFactory to Factory using the factory extension.
Bind<IFeatureFactory>().ToFactory();
What you have to do is create factory method for each of your IFeature implementations in IFeatureFactory and call it Get... according to the Feature named binding.
public interface IFeatureFactory
{
IFeature GetSomeFeature();
IFeature GetOtherFeature();
}
Now ninject will implement(!) this class for you and know which implementation to choose for each method.(There is no need for service locator....)
You can use switch statement over the input in your client to choose which factory method to call or you can wrap it in some provider class that will have the switch statement in it, in both cases you will not have to do the 'new' for IFeature implementations yourself.
Of Course you can pass parameters to the implementations constructors by the factory methods if you need to and other more complex things.
I suggest you to read this for further information.
Edit
I would like to emphasis you don't have to write factory method for each implementation, you can use the same method for all (It is possible but more complex). To do it you will need to create custom instance provider to detect which implementation to instantiate (according to the factory parameters for example), more about this in the link above and here.
You can use Named Bindings. Example code:
Bind<IFeature>().To<Feature1>().Named("Feature1");
Bind<IFeature>().To<Feature2>().Named("Feature2");
For more info
Edit
If you don't like Service locator pattern, above approach is not good for your case because you have to use IKernel to resolve IFeature.
One of the main idea of IoC that you should not have dependencies between components of your solution. So it's good approach to use only interfaces and don't create new instances of your classes with keyword "new".
Your issue can't be solved in a simple and elegant way because you can inject only interface which all you features implement.
So you have some features and them implementations:
internal interface IFeature
{
}
internal interface IFeature1 : IFeature
{
}
internal interface IFeature2 : IFeature
{
}
And a factory:
internal interface IFeatureFactory
{
IFeature GetInstance(string featureName);
}
internal class FeatureFactory : IFeatureFactory
{
private readonly ITypeFactory<IFeature1> feature1;
private readonly ITypeFactory<IFeature1> feature2;
private readonly Dictionary<string, ITypeFactory<IFeature>> featuresContainer;
public FeatureFactory(ITypeFactory<IFeature1> feature1, ITypeFactory<IFeature1> feature2)
{
this.feature1 = feature1;
this.feature2 = feature2;
featuresContainer = new Dictionary<string, ITypeFactory<IFeature>>
{
{"Feature1", feature1},
{"Feature2", feature1}
};
}
public IFeature GetInstance(string featureName)
{
if (!featuresContainer.ContainsKey(featureName))
throw new Exception(string.Format("Can't create feature {0}", featureName));
return featuresContainer[featureName].Create();
}
}
You can inject all this stuff in this way:
Bind<IFeatureFactory>().To<FeatureFactory>().InSingletonScope();
Bind<IFeature1>().To<Feature1>();
Bind<IFeature2>().To<Feature2>();
Bind<ITypeFactory<IFeature1>>().ToFactory();
Bind<ITypeFactory<IFeature2>>().ToFactory();
The main idea is that you have only one instance of feature factory for application and you store injected factories of your features. So when you access to IFeatureFactory first time Ninject will create a singleton instance of it. But your features instances will create only when you'll call GetInstance() method.
To make this code work you should add new interface:
public interface ITypeFactory<out T>
{
T Create();
}
And install NuGet package:
https://www.nuget.org/packages/Ninject.Extensions.Factory/
I have to apply the following methods for Ninject, IoC and factory pattern.
Step 1:
Added binding to IOC container
Bind<IFeature>().To<SomeFeature>().Named(nameof(SomeFeature));
Bind<IFeature>().To<SomeFeature>().Named(nameof(SomeFeature));
Step 2:
Create an extension method to resolve your dependency
public class Resolver
{
[Inject]
public IKernal kernal { get; set; }
public T Resolve<T>(string type)
{
return kernal.TryGet<T>(type);
}
}
Step 3 Create an instance of your class
IFeature feature = null;
switch (typeOfFeature)
{
case Feature.SomeFeature:
feature = Resolver.TryResolve<IFeature>(nameof(SomeFeature));
break;
case Feature.OtherFeature:
feature = Resolver.TryResolve<IFeature>(nameof(OtherFeature));
break;
default:
throw new Exception("Type not supported");
}
return feature;
If I understand the Factory Pattern correctly, I might have a factory for creating my Repos that implements an interface like this ...
public interface IRepoFactory
{
T Get<T>() where T : IRepo
}
And in that factory a call to RepoFactory.Get<IRepo1>() will return a newly minted instance of a class implementing IRepo1.
So, in the definition of RepoFactory I will create a new instance of the appropriate type...
switch(...)
{
case typeof(IRepo1):
return new Repo1();
}
Or, I assume, I can define a constructor for Repofactory that takes, as parameters, an interface representing all of the possible return types...
public RepoFactory(IRepo1 repo1, IRepo2 repo2, ..., IRepoN repoN) : IRepoFactory
and let my IoC container do the work of creating the classes.
So, to my question. If I do create a constructor as above, doesn't that mean that each time I include IRepoFactory as a constructor parameter I will get a new instance of Repo1, Repo2,..., RepoN? Is that a resource heavy process? Is it a wasteful way to do things if, in any given case, I will likely need only a subset of the total number of available repos?
Is there a way of getting the IoC (Unity, in my case) to only create an instance at the time it is needed, a Lazy Loading, if you will? Or am I simply worrying about nothing?
You misunderstood Factory. Factory should create instances. That's mean nothing should be in factory constructor beside of Di container or LifeTimeScope.
You can use your own factory or you can use auto generated factory.
I'm not familiar Unity but I checked they have.
public class MyService : IMyService
{
private readonly Func<IRepo1> _repo1;
public MyService(Func<IRepo1> repo1)
{
_repo1 = repo1;
}
public void Method1()
{
var myRepo = _repo1();
}
public void Method2()
{
//Repo1 instance will be different than in Method1
var myRepo = _repo1();
}
}
If you have a container then you can let the container resolve the type of repo when needed.
Here is a rough example of how you can do it. Note you will change the code to suit you specific container and also the assumption here is that you would have also already configured the container to know hot to resolve the types you want.
public class DefaultRepoFactory : IRepoFactory {
IUnityContainer container;
public DefaultRepoFactory(IUnityContainer container) {
this.container = container;
}
public T Get<T>() where T : IRepo {
return (T)container.Resolve<T>();
}
}
Configuration
IUnityContainer myContainer = new UnityContainer();
IRepoFactory myDefaultFactory = new DefaultRepoFactory(myContainer);
myContainer.RegisterInstance<IRepoFactory>(myDefaultFactory);
Let's say that i have a LolCats.Data project that contains various repositories that implements interfaces like this one:
public interface ILolCatRepository
{
ILolCat Get(Guid id);
void Save(ILolCat lolcat);
List<ILolCat> GetAll();
}
In the Get(id) method i need to return a new instance of a type implementing the interface ILolCat. But at the same time I dont want to reference the type LolCat by doing a return new LolCat().
Is there any way for me to let ninject create the instance of the type LolCat for me? Or what's the best pattern here? Not sure if I'm over-thinking this. Maybe it doesn't matter that the repository instantiates LolCat since it returns the interface anyway? On the other hand, if i somehow use Ninject for this, it means that the repository is referencing a specific IOC containers solution which might be bad.
You have a couple of options to avoid doing a new LocalCat():
Option #1
public class LolCatRepository : ILolCatRepository
{
public ILolCat Get(Guid id)
{
return NinjectHelper.Resolve<ILolCat>();
}
}
Ninject is setup as follows:
Bind<ILolCat>().To<LolCat>();
And helper will be something like:
public static class NinjectHelper
{
public static T Resolve<T>()
{
IKernel kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel.Get<T>();
}
}
Option #2 is a bit cleaner and uses constructor injection:
public class LolCatRepository : ILolCatRepository
{
public List<ILocalCat> _localCats;
// ninject will inject this list due to the chain of dependency.
// if it fails, then go with option #1.
public LolCatRepository(List<ILocalCat> localCats)
{
this._localCats = localCats;
}
public ILolCat Get(Guid id)
{
return this._localCats.FirstOrDefault(lc => lc.Id == id);
}
// similarly GetAll
}
Sure, you can have ninject inject an Func<ILolCat> factory into the constructor of ILolCatRepository.
Or you could also create an interface for the factory and use Ninject Factory Extension like
IBindingRoot.Bind<ILolCatFactory>().ToFactory();
On a side note, why are you implementing a new repository for every type? Why no just use an interface like:
public interface IRepository
{
T Get<T>(Guid id);
void Save<T>(T entity);
....
}
Let's say in C# I have a class called A
public class A : IInterfaceA
{
[Dependency]
B _b;
}
Then in B class I have a constructor like this:
public class B
{
...
public B(string someParam) { ... }
...
}
Now, I register class A like this:
_unityContainer.RegisterType<IInterfaceA, A>("RegistrationA");
and to resolve the interface I do:
_unityContainer.Resolve<IInterfaceA>("RegistrationA", new ParameterOverride("someParam", "The param."));
Now I want to know if it is good practice to resolve the class and pass the parameters like this or I should do it another way.
Thanks a lot :)
First of all the code you posted does not work: in fact you're overriding the parameter of class A, while in your code the constructor with the parameter is B.
Generally speaking, using parameter override is not a good practice in my opinion (unless some very specifical context like a console application or a web service using an existing container but it's avoidable in most cases) for these reason:
Using Resolve looks like a Service locator: anti-pattern nowadays. You will find a lot of discussion googling about.
Using ParameterOverride means that the client (the caller of Resolve) knows exactly the type mapped in the container and wants that type initialized with a specific parameter. But this is just the opposite of inversion of control.
The best way is to use an abstract factory. You can add in your code and use a more flexible and SOLID abstract factory:
public interface BFactory {
B Create(string bparam);
}
public class BFactoryUnity : BFactory {
private IUnityContainer container;
public BFactoryUnity(IUnityContainer container) {
this.container = container;
}
public B Create(String bParam) {
var b = new B(bParam);
container.BuildUp(b);
return b;
}
}
So you can register:
_unityContainer.RegisterType<IInterfaceA, A>("RegistrationA")
.RegisterType<BFactory, BFactoryUnity>();
Now the client can resolve only the factory and use it:
var bFactory = _container.Resolve<BFactory>();
var b = bFactory.Create();
Now, in a big application you will need a lot of similar factories. To avoid the boilerplate code of abstract factories and implementations you can find in the web some implementation of automatic abstract factory extensions.