Use dependency injection with specific instance - MS Unity - mvvm

I'm writing MVVM application which based on PRISM.
I learning PRISM in those days and I have a technical question about UnityContainer.
Is there any way to inject specific instance while I using container.Resolve?
I will try to explain by example.
Lets register the next types:
var container = new UnityContainer();
container
.RegisterType(typeof(ISomeClass), typeof(SomeClass))
// with string
container
.RegisterType(typeof(IExample), typeof(Example), "SpecificExampleInstance")
// without string
container
.RegisterType(typeof(IExample), typeof(Example));
The constructor of SomeClass get IExample as input parameter.
Now I want resolve instance of SomeClass but tell to "container" to inject into SomeClass constructor the instance of IExample - "SpecificExampleInstance" (the one which registered at line 3 in the code above) and not the IExample - without string (the one which registerd at line 4 of above code - without string)
I'm hoaping that my question clear enough, If not please let me know and I will try to change the formulation.
Thanks

One option is to use the Dependency attribute:
public class SomeClass
{
public SomeClass([Dependency("SpecificExampleInstance")] IExample myExample)
{
// work with the service here
}
}

Related

Prism 7 throws ResolutionFailedException: No public constructor available for type (Interface)

I'm devolping a WPF application, using Prism 7.2. I have a module, which implements the IModule interface, where I register the views and viewmodels in the RegisterTypes method, e.g.:
containerRegistry.Register<IPanelOptimizationViewModel, PanelOptimizationViewModel>();
The problem arises when I try to resolve the implementation:
var vm = containerProvider.Resolve<IPanelOptimizationViewModel>();
whereupon I get the following Unity.ResolutionFailedException:
'Resolution failed with error: No public constructor is available for type
XXX.Infrastructure.Interfaces.IView.'
The PanelOptimizationViewModel class derives from a base class:
public class PanelOptimizationViewModel : ViewModelBase, IPanelOptimizationViewModel
{
public PanelOptimizationViewModel(IPanelOptimizationView view, IPanelOptimizationInputViewModel inpVM) : base(view)
}
and the ViewModelBase looks like this:
public class ViewModelBase : BindableBase, IViewModel
{
public IView View { get; set; }
public ViewModelBase(IView view)
{
View = view;
View.ViewModel = this;
}
}
The interfaces IView and IViewModel are defined in a common Infrastructure project. They are not registered anywhere in the container, but if I remove the IPanelOptimizationInputViewModel parameter, no runtime exception is thrown - leading me to think that I don't need to do this, either.
As far as I have been able to understand, the Unity.Container will use the "most parameterized" constructor (see Unity not using the default constructor of the class), but I cannot provide a parameter in the Register method to specify this, as one apparently could before (pre Prism 7's container abstraction), with the RegisterType method.
How to solve this? Is there an overload of the Prism.Ioc.IContainerRegistry.Register method that allows me to set up the registration for constructor injection?
Should I work directly with the Unity container?
Basically, I am trying to inject a child view's viewmodel into the constructor of my "main" viewmodel, but this does not go well as long as the wrong constructor is called on the base class, with the wrong set of parameters... (if that is what is happening).
Needless to say, all child views and viewmodels have been registered in the RegisterTypes method in the module.
Any help on this would be greatly appreciated
Should I work directly with the Unity container?
Yes, you can evade Prism's "abstraction" of the container by calling the GetContainer() extension method (for your container).
containerRegistry.GetContainer() // here you get a plain IUnityContainer
.RegisterType( ... );

Is there a difference between SimpleIoc.Default.GetInstance and ServiceLocator.Current.GetInstance

I am using version 4 of MVVM Light for Windows 8; it includes SimpleIOC. In various examples I sometimes see code to request an object based on SimpleIoc... and sometimes it is based on ServiceLocator...
Examples include:
userToken = SimpleIoc.Default.GetInstance();
mainVM = ServiceLocator.Current.GetInstance();
What is the difference between using SimpleIoc.Default.GetInstance and ServiceLocator.Current.GetInstance?
If there is no difference, does ServiceLocator just let me to have an option to change my mind about what IOC library I want to use? Does ServiceLocator just provide an additional layer of abstraction that is irrelevant if I am satified with SimpleIoc; or, does ServiceLocator perform some other useful magic that is not obvious to we IOC novices?
Thanks for the insight!
In your ViewModelLocator class you probably have the following line of code:
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc implements the IServiceLocator interface, which means that the ServiceLocator will use it as a DI source when invoked.
Edit:
OK, people want the "full fat and don't spare the cream" answer. Here we go!
ServiceLocator is basically a shell. The code for Service locator is:
public static class ServiceLocator
{
private static ServiceLocatorProvider currentProvider;
public static IServiceLocator Current
{
get
{
return ServiceLocator.currentProvider();
}
}
public static void SetLocatorProvider(ServiceLocatorProvider newProvider)
{
ServiceLocator.currentProvider = newProvider;
}
}
Yup, that's it.
What's ServiceLocatorProvider? It's a delegate that returns an object that implements IServiceLocator.
SimpleIoc Implements IServiceLocator. So when we do:
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
We put our SimpleIoc object into the ServiceLocator. You can use either of these now because whether you call ServiceLocator.Current or SimpleIoc.Default you're returning the same object instance.
So, is there any difference between
userToken = SimpleIoc.Default.GetInstance();
mainVM = ServiceLocator.Current.GetInstance();
?
Nope. None. Both are singletons exposing a static property that is an implementation of IServiceLocator. As mentioned above, you're returning the same instance of object that implements IServiceLocator regardless of which you call.
The only reason why you might want to user ServiceLocator.Current.GetInstance() rather than SimpleIoc.Default.GetInstance() is that at some point in the future you may change DI containers and, if you use ServiceLocator, you won't have to change your code.
Based on Mr. Bugnion's article on MSDN (in the section, "Various Ways to Register a Class"), I am presuming interchangeability of IoC providers is the one and only reason for using ServiceLocator.
As #FasterSolutions stated, SimpleIoc implements IServiceLocator, so I suspect the opposite to your statement about abstraction layers is true. I think you should use ServiceLocator, but this is without empirical evidence; maybe someone can prove me wrong (?)

Unity Registration: Hooking up an interface to a pre-registered concrete class

I already have a concrete class registered in my unity container and I want to, later on, register an interface that hooks up to that class but uses the existing registration.
I can do this using the following code but it causes a resolve at registration time...
container.RegisterInstance<IMyClass>(container.Resolve<MyClass>());
Is it possible to hook the code up with all resolution done at the point the interface is resolved?
The trick is to use an InjectionFactory:
container.Register<IMyClass>(
new InjectionFactory(c => c.Resolve<MyClass>()));
It sounds like you want to create a factory type. Here, a Func delegate type is used to avoid the creation of a new custom factory type:
container.RegisterInstance<Func<IMyClass>>(() => container.Resolve<MyClass>());
Your other types can then take a dependency on this factory:
private IMyClass myClass;
public MyOtherType(Func<IMyClass> myClassFactory)
{
this.myClass = myClassFactory();
}
IUnityContainer container = new UnityContainer();
var onlyInstance = new MyClass();
container.RegisterInstance<IMyClass>(onlyInstance);
IMyClass resolved = container.Resolve<IMyClass>();
if (object.ReferenceEquals(onlyInstance, resolved))
{
Console.WriteLine("Equal");
}
This prints "Equal". This is the way I would register the instance in the first place.
In a comment above, you imply that you do not control the initial registration. That's the real issue. I would recommend going down one of the following paths (in order of preference, highest to lowest):
Create your own UnityContainer independent of the pre-registered one
Create a child container with CreateChildContainer
Use named (non-default) mappings

StructureMap IoC problem getting the instance in runtime

i have 2 concrete types "CategoryFilter" & "StopWordsFilter" that implements
"IWordTokensFilter".
Below is my setup:
ForRequestedType<IWordTokensFilter>().TheDefaultIsConcreteType<CategoryFilter>()
.AddInstances(x =>
{
x.OfConcreteType<StopWordsFilter>();
}
);
The problem is the run-time when structure map auto inject it on my class, bec. i have arguments with same plugin-type:
public ClassA(IWordTokensFilter stopWordsFilter, IWordTokensFilter categoryFilter)
i'm always getting CategoryFilter in my first argument but it should be stopWordsFilter.
How can i setup this in a right way? thanks in advance
There are a number of possible solutions:
1) Does ClassA need to differentiate between the filters, or does it just need to run them both? If not, you can change the constructor to accept an array, which will cause all registered instances of IWordTokensFilter to be injected:
public ClassA(IWordTokensFilter[] filters)
You can then foreach over the filters to apply them.
2) If you do need to differentiate them, because they need to be used differently, you may consider having one implement a marker interface the better describes its purpose. ClassA could then be changed to take in an IWordTokensFilter and an ICategoryFilter (or whatever you name the marker interface). Register CategoryFilter with ICategoryFilter and then both will be injected properly.
public ClassA(IWordTokensFilter stopWordsFilter, ICategoryFilter categoryFilter)
3) You can tell StructureMap explicitly how to create ClassA:
ForRequestedType<ClassA>().TheDefault.Is.ConstructedBy(c => {
return new ClassA(c.GetInstance<StopWordsFilter>(), c.GetInstance<CategoryFilter>());
});
4) You can tell StructureMap to override one of the dependencies for ClassA:
x.ForRequestedType<ClassA>().TheDefault.Is.OfConcreteType<ClassA>()
.CtorDependency<IWordTokensFilter>("stopWordsFilter").Is<StopWordsFilter>();

With Autofac what would be the advantages and disadvantages

I've read about Autofac that it's fast. I've seen the coding involved and it's pretty neat. But I'm not quite sure how to use it. I've used StructureMap, and it has a static ObjectFactory. Ninject has the Kernel, but in Autofac's Google pages they recommend doing something like this :
using( var resolver = builder.Build() ){
var whatINeed = resolver.Resolve<INeedThisService>();
}
It's a WinForms app, so I got an Invalid Object state from doing the above, so I switched to having a global IContainer, and did it this way
using( var resolver = Program.Container.CreateInnerContainer() )
{
var whatINeed = resolver.Resolve<INeedThisService>();
}
I've used it about 3 or 5 times. But is that efficient? Or should I just do something like
var whatINeed = Program.Resolve<INeedThisService>()
and under the covers
internal static TServervice Resolver<TService>(){
if(_container == null ) _container = builder.Build();
return _container.Resolve<TService>();
}
Which would you use, and why? Also is there a penalty for working with CreateInnerContainer()?
I am not an AutoFac expert but do have experience with other Ioc containers. I thought this question would give me a reason to try AutoFac.
Designs based on Ioc containers should strive to isolate all code from having access to the container except at the entry point or host level. I created the following example using AutoFac and WinForms to show how a form could access a service via it's constructor.
I'm not quite sure why you thought you needed the inner container. Perhaps you could comment and I can provide a more detailed response.
static class Program
{
[STAThread]
static void Main()
{
var builder = new ContainerBuilder();
builder.Register<TheService>().As<INeedThisService>();
builder.Register(f => new Form1(f.Resolve<INeedThisService>())).As<Form1>();
using (var container = builder.Build())
{
Application.Run(container.Resolve<Form1>());
}
}
}
public interface INeedThisService { }
public class TheService : INeedThisService
{
public TheService() { Console.WriteLine("ctor ThisService"); }
}
public partial class Form1 : Form
{
public Form1(INeedThisService service)
{
Console.WriteLine("ctor Form1");
InitializeComponent();
}
}
1) From the examples you gave I could make an assumption that you are trying to use IOC container primarily as service locator. Although almost all containers support it, main usage would be Dependency Injection. That means you should avoid calling Resolve method at all and let container inject all dependencies for you. The differences between two of them (Service Locator and Dependency Injection) is beyond this topic.
2) If you still want to use it as service locator you can just use root container (Program.Container in your case) without creating inner containers. The sequence would be:
Create ContainerBuilder
Register you components in the builder
Create root container: builder.Build()
Access root container to resolve component instances
3) Container hierarchies can be useful in the scenarios where you need singleton behaviour in different scopes:
Global \ Session \ Request (Web applications)
Application \ Plugin (Desktop plugin-based applications)
BTW Autofac encourage people to use tagged contexts to solve such problems:
As Mark Lindell pointed out, you don't generally need to access the container directly in an Autofac application.
The recommended approach is to access it once, as Mark has done, when the application starts up.
Other components that subsequently need to create objects can declare a constructor parameter of type IContext, which Autofac will automatically inject.
An alternative, that does not require any dependency on the Autofac assembly, is to use Generated Factories as described at: http://code.google.com/p/autofac/wiki/DelegateFactories
Hope this helps!