Dependency Injection in a ASP.NET Custom Server Control - c#

I am writing some asp.net custom server controls and looking for the best practice as to how to inject a dependency that the control needs.
When deciding on how to do this, there are a couple of factors which I am taking into consideration:
1) How easy would it be to inject this dependency through markup.
2) How easy would it be to inject this dependency through code-behind.
3) This injection has to be as early as possible in the control life cycle, preferably the control should have all of its dependencies available in the OnInit().
Bases on these factors, the only way I can think of doing this it so have a string property on the control which will have the fully qualities type to the dependency. Once the control initializes it can load that type and do what it needs to do.
Example:
public class MyControl : CompositeControl
{
public string RepositoryType { get; set; }
protected IRepository Repository { get; set; }
protected override void OnInit()
{
EnsureChildControls();
}
protected override void CreateChildControls()
{
if (!ChildControlsCreated)
{
Repository = ComponentFactory.Instanciate(RepositoryType);
}
}
}
I run into this kind of situation all the time and was wondering if anyone else
figured out another/better/different to inject the dependency.
Thanks :)

What I've done is on init of the control, query the DI container and populate those references. You could nest this logic in a specialized base class that your custom server control can inherit from, so then it's reused. OR: There is a special AddedControl method that is called everytime a control is added to the control tree. The caveat here is that it probably only calls the method on the parent control, and does not propogate up. It may work depending on your scenario.
There isn't much in the lifecycle that lets you know when a control is created (other than the AddedControl method or the Init method that runs at the beginning of the process) to be able to tap into, and you can't customize the constructor of the control.
In regards to #1, to use the markup approach would require tapping into the design-time aspect of controls, and leveraging the design time attributes to the fullest. But #1 means defining the mappings in markup, which is not quite the point of a DI container. The designer still needs the property or something to assign the reference to, so it would essentially be double work of defining the property, then defining something in the designer, when the DI container takes care of that for you.

Related

Correct way to use DI when creating new objects in Collection

MVVM, using PRISM 6 and Unity.
Bootstrapper takes care of creating intial View, which is in turn AutoWired to the ViewModel (i.e. View Model is resolved and it's DI's are taken care of).
Now the View Model has a Collection of other View Models.
This Collection can be added to with User Input, say with a button push.
The View Models in the collection require access to a singleton that I have to manage the "Workspace" (paths for image folders etc). So I would also want the creation of those objects to have that "Workspace" singleton injected into it.
In the method that would create a new ViewModel, what's the correct way to utilize DI/IoC to create it?
The only way I see it (dangerous to say "only" I know, that's why I'm asking for help) is:
Inject the Unity Container into the View Model that contains the
collection, then Resolve the new View Models as the button is hit.
The new View Models would be setup with a dependency on the
interface for the "Workspace" object.
Create a new View Model when the button is hit and pass the
"Workspace" into the constructor (of course the Workspace would need to be DI'd into the parent View Model to be passed down).
I have read multiple places that getting into passing the Container down via DI so that one can use Resolve<> isn't "correct".
Is this where creating a generic Factory would help? This still forces me to pass the container down, now it's just in the form of a factory though...
public T factory<T>(IContainer _container)
{
return _container.Resolve<T>();
}
Often when I read about DI, it is treated as the be all and end all. I more often than not use IoC heavily even in my small and simple projects, however, it is just pattern and has a place like everything else.
The Microsoft Press book Adaptive Code via C# explains SOLID well, justifies its use, covers the various forms of DI and the cost/benefit of each technique. For me, it made a lot of sense of these issues, managing project growth, and dealing with external dependencies.
I would NOT pass the UnityContainer to anything outside of my bootstrapper, other than a system which abstracts and breaks apart the bootstrapping/modularity process. In addition to the points you have made about this, Unity is a third-party dependency to your application just like anything else, and I would be very selective of which (if any) I tie myself to.
For your example above, I would use a simple factory. You could abstract this as far as you like, but a good compromise would be relieving your primary ViewModel of the burden of having to create its own children.
When using DI, there is nothing wrong with instantiating things yourself where appropriate. The most appropriate place of course is a factory. I wouldn't create a generic factory, as you stated, this is basically just like passing around the IoC container. Define a typed factory instead:
public interface IWorkspaceItemViewModelFactory
{
WorkspaceItemViewModel CreateWorkspaceItem();
}
The implementation of this might look something like this:
public class WorkspaceItemViewModelFactory
{
private readonly IWorkspaceManager _workspaceManager;
public WorkspaceItemViewModelFactory(IWorkspaceManager workspaceManager)
{
_workspaceManager = workspaceManager;
}
public WorkspaceItemViewModel CreateWorkspaceItem()
{
return new WorkspaceItemViewModel(_workspaceManager);
}
}
This class is an information expert with the single responsibility of creating WorkspaceItemViewModel instances. It has the right the use the new keyword, and have knowledge of WorkspaceItemViewModel dependencies. You may wish to insulate the ViewModel with an interface, but the value might be very little in your use case. Ultimately, you are using IoC, DI, and Interface Segregation for a reason, and when they stop delivering value to your particular application their use becomes noise.
Your view model could make use of this something like:
public class ExampleViewModel : ViewModelBase
{
public ExampleViewModel(IWorkspaceItemViewModelFactory workspaceItemViewModelFactory)
{
AddItemCommand = new ActionCommand(() =>
{
var newItem = workspaceItemViewModelFactory.CreateWorkspaceItem();
WorkspaceItems.Add(newItem);
});
}
public ICommand AddItemCommand { get; }
public ObservableCollection<WorkspaceItemViewModel> WorkspaceItems { get; } = new ObservableCollection<WorkspaceItemViewModel>();
}

Simple Injector - register collection

I use Simple Injector to create IoC container. I took pattern here:
Page Navigation using MVVM in Store App
As I asked in comment to above post, I would like to register collection of INavigationPage. I did it like that:
private static void RegisterNavigationPages()
{
Container.RegisterCollection<INavigationPage>(new []
{
typeof(MainNavigationPage),
typeof(SecondNavigationPage)
});
}
Inside the container I have ViewModels and NavigationService to:
Container.Register<INavigationService, NavigationService>(Lifestyle.Singleton);
Container.Register<IMainViewModel, MainViewModel>(Lifestyle.Singleton);
Container.Register<ISecondViewModel, SecondViewModel>(Lifestyle.Singleton);
This is way how I set DataContext of page:
DataContext = App.Container.GetInstance<IMainViewModel>();
Everything is OK but I want to use NavigationPages from that collection inside my ViewModel constructor. I can do it by index:
public SecondViewModel(INavigationService navigationService, IEnumerable<INavigationPage> navigationPageCollection)
{
NavigationService = navigationService;
_navigationPage = (navigationPageCollection.ToList())[0];
GoToMainPageCommand = new Command(GoToMainPageAction);
}
but it isn't elegant solution because when I change order of NavigationPages I will have to change all indexes in whole application. Is it any solution when I will can recognize which NavigationPage I want to use in ViewModel constructor?
I can't do it by typeof, because that NavigationPage types are in UIProject and I can't have reference there from ViewModel project because of circular reference dependency.
Currently the correctness of the SecondViewModel is completely dependent on the order and filling of the navigationPageCollection, which makes it really fragile. If your SecondViewModel needs a MainNavigationPage, that's what you should inject. Don't inject a collection; inject the page itself. That probably means that MainNavigationPage needs its own interface, such as IMainNavigationPage. That removes any ambiguity that you are having right now. But instead of having loads of one-to-one mapping non-generic interface (a violation of the RAP principle), you might be better of defining a few generic abstractions.
I have a similar problem and have solved this issue before. Read my blog here clean factory pattern
Basically what you need is to add a method or property to identify the user in the INavigationPage, and then also add the same identifier in the SecondViewModel. The SecondViewModel constructor just need to iterate through the IEnumerable and find the page that it needs.

How to inject dependencies into view models in Caliburn.Micro?

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.

Simple Injector inject multiple dependency in BaseClass

I have a BaseViewModel which is inherited by multiple ViewModel classes. In my BaseViewModel I have a couple of dependencies which get injected from ViewModel. Now if I need to add a new dependency in my BaseViewModel I need to change all the VM which inherit BaseViewModel. Please let me know how can it be handled in Simple Injector. Following is my code structure:
How can I make my base class injection independent so that I don't need to make changes in all my inherited class?
Code:
public class BaseViewModel
{
protected readonly IAESEnDecrypt AESEnDecrypt;
protected readonly IDataService DataService;
protected readonly INavigationService NavigateToPage;
public BaseViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt)
{
AESEnDecrypt= encrypt;
NavigateToPage = nav;
DataService = data;
}
}
public class ViewModel
{
public ViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt) : base (nav, data, encrypt)
{
}
}
My BaseViewModel Contains some of the following Interfaces whose implementation is injected through constructor:
- NavigationService
- DataService
- GeoLocationService
- SmartDispatcher
- MessageBus which implement Message Aggregator
It also Contains some common properties as static variables whose data is used throughout the application like UserDetails. And also contains CancellationToken, IsBusy to display progressbar.
BaseViewModel also contain HandleException method which handle all the incoming exceptions from all ViewModel.
Also Contains some common Commands which are used in all the Views like Si
gnoutCommand, NavigationBar Commands.
Actually it has started to contain all kinds of common methods used among various ViewModel.
Please suggest how can i refactor this code?
Your last sentence:
Actually it has started to contain all kinds of common methods used among various ViewModel
Precisely describes your problem! As Steven already described, that you're building almost the complete application through a single base class. Thereby infringing the Open-Closed principle which you are heavinly experiencing now.
The trick is design your application around very small SOLID ViewModels of which you compose the application at runtime. By splitting the ViewModels and using a UserControl as your views you can compose big complicated views for the user, while you still get all the benefits from using a SOLID design. So let’s take a look at some of your different interfaces that you implement and some of the functions you ‘handle’ in the base class:
NavigationService
This sounds like a service which controls the flow in your application. This sounds to me like your mainview(model). You could create a single MainViewModel which as a single property, let’s say CurrentView.Assuming you’re using WPF you typically would bind this property to a ContentControl. The content of this control can be everything from a single TextBlock to a complete UserControl. The UserControls can still be very complicated as they could be composed of multiple child usercontrol and so on. Using a MVVM framework (like e.g. Caliburn Micro or MVVM Light) for this is optionally but will come in handy.
It could also be an application global service with some of kind of callback or delegate function to perform navigation to a certain View(Model). It is in any case an infrastructural part of your application that deserves it own class and shouldn't be put away in a base class.
DataService
A single dataservice was the way I worked for over 10 years. Every time I hit my head against the wall. There comes a point in time that you need something special which is not included in your dataservice and you will probably go through your complete code base to make the right adjustments. Speaking of the Open-Closed principle…
Than I learned about the Command/Handler and Query/Handler pattern. You can read about this here and here. Using this pattern everywhere you need data you just inject the correct IQueryHandler<,> and use it right there. Not every view(model) needs data and certainly not the same data. So why use a global DataService? This is will also improve your Lifetime management of your DBContext object.
HandleException
Why is your base class responsible for handling the exceptions of your viewmodel? What does the base class know about this exceptions? What does the base class do? Log the exception, show a message to the user (what kind of message?) and silently continue? Letting the application break down 3 minutes later and leaving a user ignorant of what happened?
I.M.O. exception should not be catched if you didn’t expect them to be thrown in the first place. Than log the exception at an application level (e.g. in your Main), show an ‘Excuse me’ message to the user and close the application. If you expect an exception, handle it right there and then and handle according.
UserDetails
Ask yourself the question how many of your 40 ViewModels actually need this information? If all 40 are in need of this information, there is something else wrong with your design. If not, only inject this details (or even better an IUserContext) in the ViewModels that actually use them.
If you use it for some kind of authentication consider using a decorator wrapping the task they need permission for performing it.
IsBusyIndicator
Again: do you need this in every ViewModel? I think not. I think furthermore, showing the user a busy indicator is a responsibility of the View, not the ViewModel and the as the length of the task determines if you need to show this, make it a responsibility of the task (assuming you’re looking at your tasks also in a SOLID manner by using e.g. the already mentioned Command/Handler pattern).
With WPF you could define a Dependency Property that you can bind to the view, thereby showing some kind of busy indicator. Now just inject a ShowBusyIndicatorService in the task that needs to show it. Or wrap all your (lengthy) tasks in a ShowBusyIndicatorDecorator.
Design
Now let’s look at some simple interfaces you could define to build up your View(Model)s. Let’s say we decide to make every ViewModel responsible for a single task and we define the following (typical LoB) tasks:
Show (any kind of) data
Select or choose data
Edit data
A single task can be stripped down to ‘Show data of single datatype (entity)’. Now we can define the following interfaces:
IView<TEntity>
ISelect<TEntity>
IEdit<TEntity>
For each interface type you would create a Processor/Service or DialogHandler depending on your semantic preferences which would do the typical MVVM stuff like finding a corresponding view and binding this to viewmodel and show this in some way (a modal window, inject it as usercontrol in some contentcontrol etc.).
By injecting this single Processor/Service or DialogHandler in the your ‘Parent’ ViewModel where you need to navigate or show a different view you can show any type of entity by a single line of code and transfer the responsibility to the next ViewModel.
I’m using these 3 interfaces now in a project and I really can do everything I could do in the past, but now in SOLID fashion. My EditProcessor, interface and viewmodel look like this, stripped down from all not so interesting stuff. I’m using Caliburn Micro for the ViewModel-View Binding.
public class EditEntityProcessor : IEditEntityProcessor
{
private readonly Container container;
private readonly IWindowManager windowManager;
public EditEntityProcessor(Container container, IWindowManager windowManager)
{
this.container = container;
this.windowManager = windowManager;
}
public void EditEntity<TEntity>(TEntity entity) where TEntity : class
{
// Compose type
var editEntityViewModelType =
typeof(IEntityEditorViewModel<>).MakeGenericType(entity.GetType());
// Ask S.I. for the corresponding ViewModel,
// which is responsible for editing this type of entity
var editEntityViewModel = (IEntityEditorViewModel<TEntity>)
this.container.GetInstance(editEntityViewModelType);
// give the viewmodel the entity to be edited
editEntityViewModel.EditThisEntity(entity);
// Let caliburn find the view and show it to the user
this.windowManager.ShowDialog(editEntityViewModel);
}
}
public interface IEntityEditorViewModel<TEntity> where TEntity : class
{
void EditThisEntity(TEntity entity);
}
public class EditUserViewModel : IEntityEditorViewModel<User>
{
public EditUserViewModel(
ICommandHandler<SaveUserCommand> saveUserCommandHandler,
IQueryHandler<GetUserByIdQuery, User> loadUserQueryHandler)
{
this.saveUserCommandHandler = saveUserCommandHandler;
this.loadUserQueryHandler = loadUserQueryHandler;
}
public void EditThisEntity(User entity)
{
// load a fresh copy from the database
this.User = this.loadUserQueryHandler.Handle(new GetUserByIdQuery(entity.Id));
}
// Bind a button to this method
public void EndEdit()
{
// Save the edited user to the database
this.saveUserCommandHandler.Handle(new SaveUserCommand(this.User));
}
//Bind different controls (TextBoxes or something) to the properties of the user
public User User { get; set; }
}
From you IView<User> you can now edit the current selected User with this line of code:
// Assuming this property is present in IView<User>
public User CurrentSelectedUser { get; set; }
public void EditUser()
{
this.editService.EditEntity(this.CurrentSelectedUser);
}
Note that by using this design you can wrap your ViewModels in a decorator to do crosscutting concerns, like logging, authentication and so on.
So this was the long answer, the short one would be: loose the base class, it is biting you and it will bite you more and harder!
Prevent having this base class in the first place. This base class is a big code smell and the result is your current pain. Such a base class will violate the Single Responsibility Principle (SRP) and will just act as a big helper class for all derived view models, or it even seems that you are putting cross-cutting concerns in there. The base class might even hide the fact that your view models violate the SRP. They probably do too much; have too many responsibilities.
Instead, try to do the following:
Move cross-cutting concerns out of the base class into decorators or find another way to apply cross-cutting concerns.
Group related dependencies together into a aggregate service and inject such aggregate service into your view model.
In a well designed application, there is hardly ever a need for having such base class that takes dependencies.
If you aren't able to change your design (but please do take a look it this; you will be in a much better place without that base class), you can revert to explicit property injection. Simple Injector does not do this out-of-the-box, but the documentation describes how to do this.
Basically, it comes down to writing a custom IPropertySelectionBehavior, moving the constructor dependencies of the BaseViewModel to public properties and marking them with a custom attribute.
But again, only use property injection as a last resort. Property injection will only hide the design problem; it will not solve it.
You can use the ServiceLocator (anti)pattern to make the injection independent, HOWEVER you should not do this as it violates the principles of SOLID. Mark Seemann - Service Locator violates SOLID
You should rather stick to adding the dependencies in the constructor as this is in line with SOLID OO design principles.

IoC/DI in the face of winforms and other generated code

When using dependency injection (DI) and inversion of control (IoC) objects will typically have a constructor that accepts the set of dependencies required for the object to function properly.
For example, if I have a form that requires a service to populate a combo box you might see something like this:
// my files
public interface IDataService {
IList<MyData> GetData();
}
public interface IComboDataService {
IList<MyComboData> GetComboData();
}
public partial class PopulatedForm : BaseForm {
private IDataService service;
public PopulatedForm(IDataService service) {
//...
InitializeComponent();
}
}
This works fine at the top level, I just use my IoC container to resolve the dependencies:
var form = ioc.Resolve<PopulatedForm>();
But in the face of generated code, this gets harder. In winforms a second file composing the rest of the partial class is generated. This file references other components, such as custom controls, and uses no-args constructors to create such controls:
// generated file: PopulatedForm.Designer.cs
public partial class PopulatedForm {
private void InitializeComponent() {
this.customComboBox = new UserCreatedComboBox();
// customComboBox has an IComboDataService dependency
}
}
Since this is generated code, I can't pass in the dependencies and there's no easy way to have my IoC container automatically inject all the dependencies.
One solution is to pass in the dependencies of each child component to PopulatedForm even though it may not need them directly, such as with the IComboDataService required by the UserCreatedComboBox. I then have the responsibility to make sure that the dependencies are provided through various properties or setter methods. Then, my PopulatedForm constructor might look as follows:
public PopulatedForm(IDataService service, IComboDataService comboDataService) {
this.service = service;
InitializeComponent();
this.customComboBox.ComboDataService = comboDataService;
}
Another possible solution is to have the no-args constructor to do the necessary resolution:
public class UserCreatedComboBox {
private IComboDataService comboDataService;
public UserCreatedComboBox() {
if (!DesignMode && IoC.Instance != null) {
comboDataService = Ioc.Instance.Resolve<IComboDataService>();
}
}
}
Neither solution is particularly good. What patterns and alternatives are available to more capably handle dependency-injection in the face of generated code? I'd love to see both general solutions, such as patterns, and ones specific to C#, Winforms, and Autofac.
I believe there is no silver-bullet solution here. I would use property injection in this case to leave parameterless constructor. Also I personally do not like injection of services into UI classes, I prefer injecting some kind of Presenters there. Then you have a property Presenter which will be set by IoC container and in setter of this property you will have your initializing code.
Out of your two solutions I do not like second one especially because of referencing IoC container in your code which is bad IMO.
I would say that your UI, especially sub-elements of your UI, shouldn't need to be provided with any services.
It's hard to judge how feasible this is for your app, but MVC or MVP is meant to avoid this need.
I would try to redesign so that a controller is responsible for interacting with services and that controller gives the view elements everything they need, rather than letting the view elements ask for what they need.

Categories