So I'm looking for some clarification how it would be possible to remove the service locator from my application.
I have a ViewManagerService that is responsible for knowing which view is active, which views are open and creating a new view.
Currently my ViewModels get an IViewManagerService injected into them via constructor injection. These ViewModels expose ICommands that when invoked can then make a call to
viewManager.Transition("MyCoolView", somePrimaryKey);
The ViewManagerService then uses a service locator to look up and instantiate a new view with the key "MyCoolView". The reason for using a key string is so I can decouple the View from the ViewModels. I would like to keep the ViewManagerService generic enough so I can use it for other apps, so I don't want it to depend on a specific IAbstractFactory interface.
Any tips/suggestions ?
You can get rid of magic strings completely by using WPF's data templating engine. The best way to do that is to use the MVVM pattern. It's orthogonal to DI, but a great enabler.
Once you've made that transition, you can have a pure DI architecture without having to rely on the Service Locator anti-pattern.
Related
Assume that there is WPF application which uses MVVM light toolkit.
Good example of this toolkit is Locator.
It is great it contains SimpleIoC which enables us to register Services and be Interface Driven.
Sometimes Locator constructor can really grows.
Unfortunatelly besides registering Interfaces it contains some logic as.:
if(SimpleIoc.Default.GetInstance<MainViewModel>().LoadProject())
{
var project = SimpleIoc.Default.GetInstance<MainViewModel>().LoadedProject
SimpleIoc.Default.Register<ConfigService>(new Service(project))
}
It was only an example - what If I need more logic during Locator Constructor.
Maybe my Services Architecture is wrongly created since they they are not independent or Maybe in such cases I should resign Locator usage - but then I will lost DI.
Another things is that in few ViewModels there is Reference to
Locator.GetInstance which I found another not a good practise since it should be injected via contructor to enable testability.
Another aspect is Using it correctly with AvalonDock.
AvalonDock is great anchorable control which enable to prepare apps which could be similar to such apps as Visual Studio with anchorable, dockable panes.
This panes are actualy another ViewModels which are bound to AvalonDock via property.
MainViewModel has property Tools = new Tools[] { ViewModel1, ViewModel2}
But each ViewModel was registered in Locator.
therefore I am using (violate DRY) them in MainViewModel as
Property getter: Locator.GetInstance()
which is in my opinion another bad example - even not safe.
What if any service required by Avalon Tool ViewModel1 is not registered yet but it is invoked via getter during MainViewModel instantiation.
It started to be a mismatch. Do you have any good practise?
I found many examples such as Workspaces (MainViewModel) but nobody used at the same time Locator which I found very useful.
I would like to keep Locator because I consider it to be a good thing which enables mme to have my project testable thanks to dependency Injection and Interface Driven.
Any Ideas suggestions? I would be thankful.
I'd avoid this. As you rightly point out, there is a lot more going on here then simply registering types.
Instead, I'd pass the ConfigService instance to the Viewmodel in its constructor. As long as it is register first, you can IOC the config service and view model.
SimpleIOC.Register<IViewModel>(()=>{return new ViewModel(SimpleIOC.GetInstance<IConfigService>())});
... That's all from memory so might not be accurate but does show the custom constructor idea from SimpleIOC.
In your view model constructor you can then call the service .Register method passing itself as a parameter.
That keeps the 'knowledge' in your view model and your locator stays focused on doing what it should.
I can create views myself using IoC without any problems if all dependencies that my view constructor needs as arguments are registered within my IoC-container.
But in case if I try to extensively use DataTemplates, then WPF creates my views. And in case if view has no default constructor, then WPF will fail and crash whole app. Thus my question is - are there any extensibility points in WPF so that I can provide a view factory to it, which will be able to create my views even when they do not have default constructor?
Unfortunately, and to my knowledge, the answer is no. I was just looking for the same thing, but WPF can only create user controls with parameterless constructors.
One solution would be to use the Service Locator pattern, where your UserControl has access to the container in its constructor and Resolves its dependency by itsself. I personally don't like this pattern. Some call Service Locator an anti-pattern, and in the long run, it can get you into trouble.
I am working on a WPF application using MVVM pattern. I need to do data validation(using Data Annotations) for my data entry screens.
But the tricky part to write a common piece of code is rather than using simple property I need to use properties with are calling GetValue and SetValue method. But my entities are being generated by entity framework using templates and modifying template to achieve this things seems very difficult.
I am using this technique to validate my data
http://blogs.microsoft.co.il/blogs/tomershamam/archive/2010/10/28/wpf-data-validation-using-net-data-annotations-part-ii.aspx
http://blogs.microsoft.co.il/blogs/tomershamam/archive/2010/10/11/notifyingobject-for-wpf-amp-silverlight.aspx
If there is better and authentic way to validate the entity data, i'll be more than happy to change my approach or if I need to change the template then please point me to some great reference.
Firstly. Really bad idea to do this, not because it is hard, but due to that you need to inherit DependencyObject. DependencyObject is an STA Threaded class. You won't be able to use a worker thread to instantiate your objects, which means you can't use a worker thread to use Entity Framework.
Now, I suggest you use the MVVM pattern with WPF. You should have a View bind to a ViewModel, which then binds to your Entity Framework POCO objects.
You can try IValidateObject for you validation https://stackoverflow.com/questions/13917890/mvc4-custom-validation-via-ivalidateobject-validate-method-not-working
I personally however prefer the FluentValidation library.
If I am generating POCO objects from EntityFramework, and using these to go to/from the WCF server, is there any reason to create client-side Models for the Views & ViewModels to use instead of just using the POCOs directly?
Almost all the MVVM examples I have looked at bind straight to the object returned from the WCF service. Is this good practice? Are there arguments that can be made for actually mapping the POCO to a Model and having the Views/ViewModels working with the Model object instead of the POCO?
The main reason I could think of is validation, however since the EF POCOs are partial classes, they can be expanded on to include validation.
EDIT
Most answers so far have brought up INotifyPropertyChanged as the main reason to build a separate Model. Does your answer change if you are using Self-Tracking entities instead of POCOs which already includes INotifyPropertyChanged? STEs are also partial classes which can be expanded upon to include validation.
Validation is the main reason not to bind directly to a POCO. In addition, if the POCO doesn't already implement INotifyPropertyChanged and other required interfaces, the experience working with the object on the WPF side may be less desirable, and implementing a ViewModel to wrap this makes sense.
Providing a ViewModel to wrap your POCO allows you to encapsulate the logic into ICommand implementations as well as implement required interfaces cleanly.
I disagree only slightly with Reed (an unusual circumstance to be sure). I would NOT implement a ViewModel to wrap the POCO. I would implement a Model class to wrap the POCO and expose the Models to the ViewModel via a Service layer.
The ViewModel's primary job is to appropriately present Model data to the View and react to its requests. The architecture I'm working on for this looks like so:
1 ViewModel for each View
The ViewModel calls a Data Service layer object to retrieve Model instances (not to be confused with a WCF service)
The Data Service layer issues the appropriate CRUD requests to the backend (this uses WCF, RIA, or RESTful Services for Silverlight but could be ADO.NET or EF directly for WPF).
The Data Service uses the returned POCOs to create Model objects.
Model objects wrap the POCO object and implement INotifyPropertyChanged. Model objects enforce business rules.
I'm still working through the details but I will be publishing something more concrete in the near future.
My Models accept a WCF object which exposes those properties which I wish to use in my ViewModel. I can then also extend the object as needed. My properties point to the WCF object's property and when I have to send the object back to the WCF service, I don't have to do any more work. The models inherit INotifyPropertyChanged and INotifyDataErrorInfo which the DTOs (mentioned here as POCOs) will not have. Your business logic / validaton exists in your Silverlight application and not in your WCF Service.
The View binds to the ViewModel which has a Model (or an observable collection of Models). The Models have a WFCObject which is a DTO (mentioned here as POCO). I use my ViewModel to communicate with the service, MVVM Light has the models communicate with the service / provider - which I don't like.
Bind to EF POCOs if you want to do simple CRUD or you want to make something fast.
Otherwise, your server-side models will tend to be very closely related to the database, which changes very slowly, as compared to user interface. For less trivial UI, you'll find yourself putting more and more kludges just to fit your database model into UI (or otherwise, which is even worse).
Also, there are performance issues (e.g. would you like to transmit whole entity when for UI you need only couple of properties?), and maintenance issues (e.g. if you would like to validate premium customer's order quite differently from ordinary one).
See also http://ayende.com/Blog/archive/2010/08/06/data-access-is-contextual-a-generic-approach-will-fail.aspx
Rachel's POCO's are just dumb objects generated by EF and used for transport (DTO). Therefore, they shouldn't have other things cluttering up their domain. This is a very nice way of designing your code because it decouples any client-side requirements from those on the server-side. That's why MVVM exists - to extend the MVC model incorporating those concerns.
There is no reason you can't bind to them in your views as long as you are not modifying them directly. You can add functionality to them by adding a partial class but I wouldn't even do that. In that case you should follow the MVVM design tenants and separate those into model objects that serve your needs in the client. This will be quite automated once you hook up INotifyPropertyChanged events to notify your views.
I would like to use Ninject in my WinForms application. I cannot figure out how to use it for my user controls. Sometimes they rely on the services I want to configure through the DI framework. These controls need to be manageable through the designer (thus need default constructors).
So, is there a way to inject dependencies into properties of this user control? Since the designer needs to be able to construct it, kernel.Get<TestClass> won't work here. Is there a method or some code that will let me "fill-in" the dependencies in the Form_OnLoad() method?
I can also think of other examples where I would want to Inject into the properties of an already existing object, but th WinForms user control is the easiest to explain.
I think you need to invert your thinking. In Model View Controller, the View has only one responsibility: to display data.
How that data gets there is the Controller's responsibility, and how the data is represented in memory is determined by the Model.
Although there are no specific MVC frameworks for Windows Forms, it's possible to make crude ones manually, or you could go have a look at the (now retired) Composite Application Block to get an idea about how this can be done (although the CAB is perhaps too complicated for most people's tastes). There are more elegant options available today, but they involve WPF.
In any case, instead of injecting your dependencies into your Views, inject them into Controllers, and have the Controllers instantiate and correctly populate the Views (your Controls).
In this way, you can keep your Controls free of DI concerns, as they should be.
I think the question is what DI tool can you use to get dependency injection to work with windows forms. Everyone does the MVC example because it's easy to implement(the same example if floating around the we as if it were new and original). If you have an answer for doing it using winforms or even WPF - that would be helpful.
This answer here basically says - in any case, I don't know so inject them into controllers and populate the views - really? Back to the MVC? Again - winforms.