I'm fairly new to MVVM PPRISM, and I'm rewriting a project that uses MVVMLight SimpleIOC. I have the following lines of code in registering in MVVM Light and I have doubts whether this is the right way to convert it in MVVM Prims's DryIOC.
SimpleIoc.Default.Register< iClassA, ClassA >();
SimpleIoc.Default.Register< iClassB, ClassB >();
// The factory method is necessary to prevent the linker from removing the class A constructor
SimpleIoc.Default.Register<IClassC>(() => new ClassC(SimpleIoc.Default.GetInstance<IClassA>(), SimpleIoc.Default.GetInstance<IClassB>()));
My question is does containerRegistry.GetContainer().Resolve<IClassInterface>() the right way to convert from SimpleIoc.Default.GetInstance< IClassInterface >()
containerRegistry.Register<iClassA, ClassA>();
containerRegistry.Register<iClassB, ClassB>();
containerRegistry.RegisterInstance<ClassC>(new ClassC((iClassA)containerRegistry.GetContainer().Resolve<iClassA>(), (iClassB)containerRegistry.GetContainer().Resolve<iClassB >()));
So you seem to have two questions in one here, so I'll try to answer each part:
Converting from SimpleIoc to IContainerRegistry
I have the following lines of code in registering in MVVM Light and I have doubts whether this is the right way to convert it in MVVM Prims's DryIOC.
Prism's IContainerRegistry is an abstraction layer around the container meant to keep the vast majority of registration consistent regardless of which DI Container you are using with Prism. This also makes it easier to add support for different containers since Prism has outlined the interface we expect a Container to be able to support.
For instance where you have:
SimpleIoc.Default.Register<iClassA, ClassA>();
This would in theory map to an equivalent:
containerRegistry.Register<iClassA, ClassA>();
Because you're dealing with an abstraction layer it really doesn't matter if the backing container was DryIoc, Unity, or even a custom implementation with SimpleIoc.
Now in the event that there is some container specific API you need to access you can always call the GetContainer() extension to access the underlying container (assuming you're using DryIoc or Unity).
Resolving Types:
So if your container has a method called Resolve that returns the type then yes you could go down to the container to call it but the better question is why would you?
My question is does containerRegistry.GetContainer().Resolve() the right way to convert from SimpleIoc.Default.GetInstance()
In the event that you're trying to resolve something from IContainerRegistry because you need to some crazy initialization. I would suggest using one of DryIoc's built in API's where you might have:
containerRegistry.Register<IFoo, Foo>();
containerRegistry.GetContainer().Register<IBar>(Reuse.Singleton,
Made.Of(() => new BarImplementation("requiredString", Arg.Of<IFoo>()));
You'll notice here that I've purposely ignored your Rp1210 example:
// The factory method is necessary to prevent the linker from removing the class A constructor
SimpleIoc.Default.Register<IClassC>(() => new Rp1210(SimpleIoc.Default.GetInstance<IClassA>(), SimpleIoc.Default.GetInstance<IClassB>()));
There are two reasons I've ignored this...
The comment tells me why they've done this.. the linker. Either turn off linking, or update your linker config to preserve the ctor for your IClassA implementation.
The entire point of using an IoC container is that it will automatically understand that it needs to inject services that are registered.
You'll notice that I'm only referencing that Container specific API because it had a primitive value that I needed to inject.
Related
I really hope this is not a stupid question, but I'm somehow unable to recognize a straight-forward way to inject dependencies into view models using Caliburn.Micro.
I'm having a main shell (conductor) like so:
public class ShellViewModel : Conductor<IScreen>.Collection.OneActive, IShell
{
public ShellViewModel(IEventAggregator eventAggregator) {
ActivateItem(new DashboardViewModel());
}
}
Now I'd like to inject a service into the DashboardViewModel but since the ActivateItem method requires me to pass an instance (rather than e.g. a type), I'm forced to provide the service myself. And since the ShellViewModel isn't aware of an underlying IoC container, I have to have the service injected into the shell.. to me, it looks like Caliburn is trying to enforce a complete graph of all view models and dependencies within an application.
I am aware that I could use a static accessor for my inversion of control container, but I really don't like this approach because I'd like to have a single composition root for my application (the bootstrapper) without having the other parts knowing about dependency injection and such.
couple of ways to do it dependent completely on your choice of container.
MEF [ImportMany] used in the constructor on the parameter that will do the actual import reference the Hello Screens example
The baked in IoC static class you could use IoC.Get<IDashBoard>() or IoC.GetAll<IDashBoard>(), this assumes you have register your types into the container you use. Caution with this one it can be over used and result in anti-pattern behavior. I have done this in one of my apps that does a dashboard, anything that is tagged with IDashBoard in my Container instance, in association with the actual implementation class will get pulled into the collection IoC.GetAll<IDashboard>() or the first item in the collection based on the IoC.Get<IDashBoard>().
You could also make your dashboard inherit Conductor<IDashBoard>.Collection.AllActive, there by allowing you access to the Items property (as part of the Collection) and populate it with the CTOR of your DashBoardViewMode, using IoC.GetAll<IDashboard>() in that one place get all the items you need on your dashboard. From there, I query the Items collection property in OnActivate and match the other viewmodels to the properties that I needed and placed named ContentControls on the DashBoardView accordingly.
this does pull from the container that you have chosen, keeping that in mind you might just want to you the containers' methods to grab the necessary items through its intended design.
I actually moved away from MEF since version used in CM doesn't work with Open Generics and debugging missing Export() attributes was starting to wear me out.
I started to use Ninject , on this relatively small project and i have run into a problem: i have this class
class SomeService : ISomeService
that depends on
class BizLogicModule : IBizLogicModule
that in turn depends on
class DataRepository : IDataRepository
the DataRepository has a ctor that looks like:
DataRepository(BizEntityModel context)
Now, i need to be able to use a single instance of BizEntityModel across more than one IDataRepository instance. I also need to create IDataRepository's along the life of a IBizLogicModule. The IBizLogicModule does not know about Ninject and i want to keep it that way.
so my problem is:
how to wire all that up, using the Ninject kernel, while:
not having to pass the kernel instance around the layers.
leaving the code readable close to what it was prior Ninject (i was just new'ing using a factory method).
The simple part of the wiring i got so far is:
Bind<SomeService>().To<ISomeService>();
Bind<BizLogicModule>().To<IBizLogicModule>();
Bind<DataRepository>().To<IDataRepository>();
Bind<BizEntityModel>().To<BizEntityModel>(); //ToSelf()
// .WithConstructorArgument(context => Kernel.Get<BizEntityModel>)
Your guidance is very much appreciated
EDIT: Thanks for your answers! here's some more data that was requested:
BizEntityModel is registered with Ninject (code updated).
if i understand correctly: i can create instances of IDataRepository in IBizLogicModule using a 'factory method'. but that leaves me with:
1) i need to pass a BizEntityModel to the factory method, some times its bran new and sometimes its an existing instance. using the factory method, it will create anew one every time.
2) is this a problem that SomeService is in another assembly, and only it has a ref to Ninject.dll ?
I repeat the question a like I understood it:
Exactly one BizEntityModel instance exists per BizLogicModule instance (They do not have a reference to each other)
Whenever BizLogicModule creates a DataRepository this BizEntityModel is reused
There are several BizLogicModules
If this is correct the second example in the NamedScope extension documentation should fit for you. See https://github.com/ninject/ninject.extensions.namedscope/wiki/InNamedScope
Make sure that you read the complete docu of this extension: https://github.com/ninject/ninject.extensions.namedscope/wiki
Do you register BizEntityModel with Ninject? If so, you should be able to tell Ninject to supply one and only one instance of a BizEntityModel for every request for the lifetime of the container, or even the program, without having to define and register a traditional singleton instance of BizEntityModel. Even if you have to work with a factory method and Ninject won't let you singleton-scope that registraion, if you have to you can eager-load the object and then register the instance for the dependency as a singleton.
IBizLogicModule should never have to know about Ninject; Ninject should know about BizLogicModule. Try creating an IDataRepository registration that will provide a factory method (factory-scoped so a new instance is created per call), then pass that factory method as a dependency to IBizLogicModule, which will use it when it needs to create IDataRepositories. You're basically passing through the IoC's resolution capabilities to provide a factory class in IBizLogicModule. If you do that for a lot of different class types on IBizLogicModule, you're basically creating a service locator which I would personally avoid, but one or two is a perfectly valid Factory/Creator pattern.
The answer below assumes that you're asking how to resolve many instances of IDataRepository in one IBizLogicModule. Otherwise this question will be too easy :-)
Usually good IoC containers have an ability to inject Factories/Factory methods. I do not have much experience with NInject and I haven't found as good solutions as I know for other containers but HERE you can see example how the main task can be achieved. The only issue here is that you will have to implement a factory on your own and pull IResolutionContext there but anyway this factory will allow you isolating rest of your code (IBizLogicModule) from IoC specifics because it will have only IDataRepositoryFactory dependency.
I'm working on a project that's using the MS Application Blocks. I see the 'Unity' dll is available to me. It's version 1.1 by the way. How can I use dependency injection here?
I have a class
public class ScheduleDataDetailsDC
{
public int ScheduleID;
public List<ScheduleRateLineItem> MinRateList;
public List<ScheduleRateLineItem> MaxRateList;
public List<ScheduleRateLineItem> VotRateList;
public List<ScheduleLOSRateDC> LosRateList;
public List<ScheduleRateParamsDC> RateParams;
}
So when I new it up I am doing this...
new ScheduleDataDetailsDC{
LosRateList = new List<ScheduleLOSRateDC>()
, MaxRateList = new List<ScheduleRateLineItemDC>()
, MinRateList = new List<ScheduleRateLineItemDC>()
, RateParams = new List<ScheduleRateParamsDC>()
, VotRateList = new List<ScheduleRateLineItemDC>()
}
Can Unity 1.1 Help me in anyway here? I would like to just be able to use var x = new ScheduleDetailsDC(), and those 5 inner lists be initialized for me. Can Unity do anything for me here? Please note I've never used DI before.
Thanks for any pointers,
~ck in San Diego
The best thing to do would be to initialise the lists in the constructor and deny direct access to them from other classes by making them into properties:
public class ScheduleDataDetailsDC
{
public ScheduleDataDetailsDC()
{
this.MinRateList = new List<ScheduleRateLineItem>();
//inialise other lists
}
public List<ScheduleRateLineItem> MinRateList { get; private set; }
...
}
It doesn't seem as though dependency injection can really be of use here since the class seems to be a simple data container, although it's difficult to tell without more context.
Yes Unity can help you, but I think it's not the case. You can just initialize your lists incide your object giving them default instances, Unity as any other IoC container shouldn't be used as a simple object builder (despite it could).
I'm not sure specifically what the details of the 1.1 release of Unity are, but generally speaking whenever you are using an Inversion of Control Container, you have to go through the following steps:
Register the types your IoC container (Unity in your case) knows about. This includes all of the main types that you plan to request, plus all of the dependent types. In your case you will need to let it know about ScheduleDataDetailsDC, and what, exactly needs to go into each of the lists that are considered dependencies
Your types should specify all of the required dependencies as constructor arguments. This is what the IoC Container will look at to determine what needs to be injected. If you have optional dependencies then you can use Property Injection to support that (if your IoC container supports it, which I think Unity does)
You must request an instance of your registered type from the container. How exactly you do this depends on you container. There should be a method like Get<T>() or Resolve<T>. Generally your going to request instances of the "Highest Level" classes, i.e the ones that are used somewhere near the entry point for your software. If you do this, and you have applied Dependency Injection for all dependent classes down the line (and you've correctly registered all of the dependent types) you should get an object with all of it's dependencies supplied, and likewise all of that objects dependencies should be supplied, and on down the line.
You also tend to see Interfaces used in conjunction with IoC a lot since you can bind a concrete type to the interface type, and then specify that interface as your dependency. This allows you to apply business rules and configuration values during the binding process that will give you the ability to use different concrete implementations in cases where you would need to do such a thing.
So given all of this, it's hard to say exactly what would be involved in utilizing Unity in the situation you've outlined above. Firstly you would need to register ScheduleDataDetailsDC, but to get the dependencies in place you would also need to register each of the List types, or more specifically each concrete object that would go in each list (and then, of course all of the dependencies for those classes). Since I'm not really sure what the roles of those lists are, it's hard for me to say how you could go about doing that (or even if you could go about doing that).
So I started this new project, and I was trying to incorporate all the new design principles I was reading about, namely trying to make things loosely coupled, testable, and following some patterns.
So I then ran into the issue of having to pass too many factories/managers into my classes constructor, which led me into Dependancy injection.
public class SomeClass
{
public SomeClass(IDBFactory factory, IOrderManager orderManager, ....)
}
So if I use ninject, from what I understand, I would then bind a particular implementation to the class.
So what is going on behind the scenes?
NInject will, whenever I instantiate SomeClass, it will bind the implementation that I defined in the config file?
i.e.
I do:
ISomeClass sc = NInject.Get<ISomeClass>();
and ninject will do:
new SomeClassImpl(pass in all the implementaitons in the constructor)
correct?
I don't know NInject, but most DI Containers support Auto-Wiring, which works this way:
When you request ISomeClass, it looks through its list of all registered types. Using this list, it discovers that the desired implementation of ISomClass is SomeClass.
It will use SomeClass' constructor to create an instance (perhaps using Activator.CreateInstance), so it uses Reflection to figure out which paramters are required.
For each paramameter, it looks at the type and repeats step 1-2 for each.
Thus, the process may be recursive, but in the end, you should end up with a fully populated object graph where all dependencies are satisfied.
Pretty new to dependency injection and I'm trying to figure out if this is an anti pattern.
Let's say I have 3 assemblies:
Foo.Shared - this has all the interfaces
Foo.Users - references Foo.Shared
Foo.Payment - references Foo.Shared
Foo.Users needs an object that is built within Foo.Payment, and Foo.Payment also needs stuff from Foo.Users. This creates some sort of circular dependency.
I have defined an interface in Foo.Shared that proxies the Dependency Injection framework I'm using (in this case NInject).
public interface IDependencyResolver
{
T Get<T>();
}
In the container application, I have an implementation of this interface:
public class DependencyResolver:IDependencyResolver
{
private readonly IKernel _kernel;
public DependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public T Get<T>()
{
return _kernel.Get<T>();
}
}
The configuration looks like this:
public class MyModule:StandardModule
{
public override void Load()
{
Bind<IDependencyResolver>().To<DependencyResolver>().WithArgument("kernel", Kernel);
Bind<Foo.Shared.ISomeType>().To<Foo.Payment.SomeType>(); // <- binding to different assembly
...
}
}
This allows me to instantiate a new object of Foo.Payment.SomeType from inside Foo.Users without needing a direct reference:
public class UserAccounts:IUserAccounts
{
private ISomeType _someType;
public UserAccounts(IDependencyResolver dependencyResolver)
{
_someType = dependencyResolver.Get<ISomeType>(); // <- this essentially creates a new instance of Foo.Payment.SomeType
}
}
This makes it unclear what the exact dependencies of the UserAccounts class are in this instance, which makes me think it's not a good practice.
How else can I accomplish this?
Any thoughts?
Althought somewhat controversial: yes, this is an anti-pattern. It's known as a Service Locator and while some consider it a proper design pattern, I consider it an anti-pattern.
This issue is that usage of e.g. your UserAccounts class becomes implicit instead of explicit. While the constructor states that it needs an IDependencyResolver, it doesn't state what should go in it. If you pass it an IDependencyResolver that can't resolve ISomeType, it's going to throw.
What's worse is that at later iterations, you may be tempted to resolve some other type from within UserAccounts. It's going to compile just fine, but is likely to throw at run-time if/when the type can't be resolved.
Don't go that route.
From the information given, it's impossible to tell you exactly how you should solve your particular problem with circular dependencies, but I'd suggest that you rethink your design. In many cases, circular references are a symptom of Leaky Abstractions, so perhaps if you remodel your API a bit, it will go away - it's often surprising how small changes are required.
In general, the solution to any problem is adding another layer of indirection. If you truly need to have objects from both libraries collaborating tightly, you can typically introduce an intermediate broker.
In many cases, a Publish/subscribe model works well.
The Mediator pattern may provide an alternative if communication must go both ways.
You can also introduce an Abstract Factory to retrieve the instance you need as you need it, instead of requiring it to be wired up immediately.
I agree with ForeverDebugging - it would be good to eliminate the circular dependency. See if you can separate the classes like this:
Foo.Payment.dll: Classes that deal only with payment, not with users
Foo.Users.dll: Classes that deal only with users, not with payment
Foo.UserPayment.dll: Classes that deal with both payment and users
Then you have one assembly that references two others, but no circle of dependencies.
If you do have a circular dependency between assemblies, it doesn't necessarily mean you have a circular dependency between classes. For example, suppose you have these dependencies:
Foo.Users.UserAccounts depends on Foo.Shared.IPaymentHistory, which is implemented by Foo.Payment.PaymentHistory.
A different payment class, Foo.Payment.PaymentGateway, depends on Foo.Shared.IUserAccounts. IUserAccounts is implemented by Foo.Users.UserAccounts.
Assume there are no other dependencies.
Here there is a circle of assemblies that will depend on each other at runtime in your application (though they don't depend on each other at compile time, since they go through the shared DLL). But there is no circle of classes that depend on each other, at compile time or at runtime.
In this case, you should still be able to use your IoC container normally, without adding an extra level of indirection. In your MyModule, just bind each interface to the appropriate concrete type. Make each class accept its dependencies as arguments to the constructor. When your top-level application code needs an instance of a class, let it ask the IoC container for the class. Let the IoC container worry about finding everything that class depends on.
If you do end up with a circular dependency between classes, you probably need to use property injection (aka setter injection) on one of the classes, instead of constructor injection. I don't use Ninject, but it does support property injection - here is the documentation.
Normally IoC containers use constructor injection - they pass dependencies in to the constructor of the class that depends on them. But this doesn't work when there is a circular dependency. If classes A and B depend on each other, you'd need to pass an instance of class A in to the constructor of class B. But in order to create an A, you need to pass an instance of class B into its constructor. It's a chicken-and-egg problem.
With property injection, you tell your IoC container to first call the constructor, and then set a property on the constructed object. Normally this is used for optional dependencies, such as loggers. But you could also use it to break a circular dependency between two classes that require each other.
This isn't pretty though, and I'd definitely recommend refactoring your classes to eliminate circular dependencies.
That does seem a little odd to me. Is it possible to separate the logic which needs both references out into a third assembly to break the dependencies and avoid the risk?