I'd like my app to be not strictly tied to an IOC, so basically my application should need to call an IOC factory pattern that solve the specific implementation on runtime.
So, first off I've created my interface:
IIOCService
interface IIOCService
{
void RegisterSingleton<RegisterType>()
where RegisterType : class;
void RegisterMultiple<RegisterType>()
where RegisterType : class;
void RegisterMultiple<RegisterType>(IEnumerable<Type> implementationTypes);
// and so on
}
then an implementation of IIOCService, using TinyIOC
class TinyIOCServiceImpl : IIOCService
{
private static readonly TinyIOCServiceImpl _Current = new TinyIOCServiceImpl();
public static TinyIOCServiceImpl Current
{
get
{
return _Current;
}
}
TinyIoC.TinyIoCContainer container;
public TinyIOCServiceImpl()
{
container = TinyIoC.TinyIoCContainer.Current;
}
public void RegisterSingleton<RegisterType>()
where RegisterType : class
{
container.Register(typeof(RegisterType)).AsSingleton();
}
// ...and so on
}
For the class that decides to resolve the implementation of the IOC container, I've created an IOCFactory
IOCFactory
class IOCFactory
{
public enum IOC { TinyIOC }
public IIOCService GetService(IOC iocType)
{
switch (iocType)
{
case IOC.TinyIOC:
return TinyIOCServiceImpl.Current;
default:
throw new NotSupportedException();
}
}
}
Now my question is:
Should I need to reinstantiate the factory for every class where IOC is needed or there is some more elegant way?
IIOCService iocService = new IOCFactory().GetService(IOCFactory.IOC.TinyIOC);
// code needed everytime I need to use IOC (i.e. ServiceLocator, ViewModelLocator, etc.)
// is this code a bit redundant ???
I agree that creating a wrapper around your IOC container is a bit redundant. But, if you need to call your IOC container to resolve a specific, on run-time determined, instance of an interface, you can create a resloving interface (not with the factory pattern, but staying within the IOC pattern). Something like this (this is too basic, just so you can get the idea):
public interface IResolve {
public T Resolve<T>();
}
You can create an implementation for this specific interface and expose it to your IOC container. There is no issue doing this in a single instance pattern.
When you need to resolve something in a class that was resolved by the IOC container, just add the IResolve to your constructor and you can address the IOC container without a dependency on whatever brand of IOC container is used.
I hope this brought some clarity for you?
Related
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);
I am using unity mvc4 package, it is auto injecting into my controllers fine. But now I am manually doing other parts of my application, helpers etc.
How can I access the singletons within the container from other classes?
How do I call MethodWithDependency(param) on my instance of MyClass2? Am I supposed to do the below? It looks far too messy.
public class MyClass1
{
public void Main()
{
var myObject2 = container.Resolve<MyClass2>;
var someObject = container.Resolve<SomeClass>;
myObject2.MethodWithDependency(someObject);
}
}
public class MyClass2
{
public void MethodWithDependency(SomeClass someObject)
{
}
}
Each object that needs its dependencies resolved can potentially have them resolved by the container. To not to spoil your code with containers, you create local factories and implement specific factory providers elsewhere, in the Composition Root which is the only place in your application where container is created and used directly.
This requires discipline, however you are able to structure your code so that there is no explicit reference to the container except for the Composition Root and still container does the job.
I wrote a tutorial on that once, it is too long to quote it here:
http://www.wiktorzychla.com/2012/12/di-factories-and-composition-root.html
Answering your specific question: to have singletons you just use the ContainerControllerLifetimeManager as the parameter to the register method.
http://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx
Create MyClass2 so that it accepts SomeClass as an argument in the constructor (you are injecting the SomeClass dependency into your MyClass2 object).
Then, you can register your Instances with the Container. At that point, when you resolve your MyClass2 object, your SomeClass object will also be resolved and injected into MyClass2.
Beautiful, huh?
The Code
public class MyClass1
{
private UnityContainer _container;
public void Main()
{
this.RegisterContainer();
// Since SomeClass was registered, when you resolve MyClass2, it will
// magically resolve an instance of SomeClass that the MyClass2
// constructor needs.
var myObject2 = this._container.Resolve<MyClass2>;
myObject2.MethodWithDependency();
}
private void RegisterContainer()
{
// Here, initialize your Container then register your singletons.
this._container = new UnityContainer();
// Do not use container.RegisterType<>()....
// RegisterInstance, by default, implements a singleton behavior.
this._container.RegisterInstance<SomeClass>();
this._container.RegisterInstance<MyClass2>();
}
}
public class MyClass2
{
private SomeClass _someClass;
// You are injecting the SomeClass dependency into your MyClass2 class.
// Hence the name — Dependency Injection.
public MyClass2(SomeClass someClass)
{
this._someClass = someClass;
}
public void MethodWithDependency()
{
// use your _someClass object.
this._someClass.DoSomething();
}
}
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.
I'm currently trying to work out how to set the initial values for some fields using Ninject.
I have something like this:
public class SomeClass
{
private ISomething _something;
public SomeClass(string someParam)
{
}
public void DoAThing()
{
_something.DoSomething();
}
}
My dilemma comes about in the setting of _something to an initial value, given I don't want the class to know anything about which default implementation of ISomething to use, is there a way of achieving this in Ninject?
I should add that passing the initial values in via the constructor is not an option.
I should also add that this is in a class-library, so any information on how and when the setup of the kernel & injection should take place would be great :)
Elaboration: It seems that people could be getting confused, I am not trying to get an ISomething into the class (it isn't a dependency), rather, the default implementation of ISomething is the dependency, this is why I went for the service-locator pattern, for actual dependencies I would of course have them in the constructor.
Thanks.
Yes, it's not very good to have highly coupled classes, thus depending on abstractions is a good choice. But hiding your dependencies is not very good solution. Make them visible to clients of your class, and use dependency injection to provide concrete implementations of dependencies to your class:
public class SomeClass
{
private ISomething _something;
public SomeClass(ISomething something, string someParam)
{
_something = something;
}
public void DoAThing()
{
_something.DoSomething();
}
}
Also consider to create factory, which will provide default implementation of ISomething to created SomeClass objects.
In the end I decided to go with a static IOC access class to allow my code to gain access to the core Ninject Kernel used by the class library for the main injection.
So:
internal static class IOC
{
private static readonly IKernel _kernel;
static IOC()
{
_kernel = new StandardKernel(new IModule[] {
new SomethingModule(),
});
}
static T Get<T>()
{
return _kernel.Get<T>();
}
}
internal sealed class SomethingModule : StandardModule
{
public override void Load()
{
Bind<ISomething>().To<ConcreteSomething>(
new ConstructorParam("arg", "value"));
}
}
Then in my previous class:
public class SomeClass
{
private ISomething _something;
public SomeClass(string someParam)
{
_something = IOC.Get<ISomething>();
}
public void DoAThing()
{
_something.DoSomething();
}
}
Now I can get concrete implementations and even have them initialised with default values to boot!
The way of getting the concrete classes initialised with default values is a little flimsy, but I'm sure there are smarter ways of achieving this in Ninject, but it does appear that a hybrid solution of service-locator-esque code and Ninject works quite well!
BTW I believe you could also have multiple IOC containers in differing scopes (themselves passed along via Ninject :P) to prevent creating a behemoth "everything everywhere" kernel.
Hope this helped someone!