Ninject for winforms - does my architecture make this useless? - winforms

I'm trying out Ninject with a winforms app (basically a sketch, I'm using it sort of like a kata, but nothing so rigorous or specific) in .net 4.
To create the main form, I'm doing something like:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
[...]
IKernel kernel = BuildKernel();
Application.Run(kernel.Get<frmMain>());
}
static IKernel BuildKernel()
{
var modules = new INinjectModule[]
{
[..modules]
};
return new StandardKernel(modules);
}
}
Fine. This creates a main form and displays it nicely, passing the appropriate interface implementations to the injected constructor.
Now what? My application is an MDI and will have several child windows for manipulating the application model. I don't have a reference to the kernel anymore, so how am I supposed to Get() these forms? The obvious answer is 'pass the kernel to the form' I suppose, but that's a horribly messy strategy and I'm sure that doesn't fit into the philosophy of DI.
I will point out here that the documentation for Ninject 2 sucks. Everything I can find repeats the basic examples, without really explaining how DI using Ninject makes anything easier. The standard of example given isn't complicated enough to make the trouble of coding and creating modules and bindings worthwhile.
edit #1:
Having studied the links kindly provided by Sam Holder, I'm trying out the 'composition root' approach. My architecture now forces all the Forms it uses to derive from a CompositedForm with constructor semantics thus:
[Inject]
public CompositingForm(ICompositionRoot CompositionRoot)
{
InitializeComponent();
this.CompositionRoot = CompositionRoot;
}
public readonly ICompositionRoot CompositionRoot;
public CompositingForm() : this(new DummyCompositionRoot()) { }
The second constructor is for the benefit of the Forms Designer, which is stupid and can't understand the form markup unless you provide an empty constructor. Now, every form created using IKernel.Get<AForm>() will (should) have a composition root injected into it.
So, as I am a slow learner - now the question is really 'What should go in this composition root'?

can't you pass a factory for creating the child forms to the forms constructor, and the form uses this to get them, then ninject will wire up the factory dependency when the form is created using the get?
I think you should configure everything in the application root using the DI container and after that the container shouldn't be needed, but I've not really used DI containers in anger, and not NInject at all, so am going on what I've read...
This answer may help

Note: I do not know much about Ninject but i worked with Spring.net that is much more complicated. The principles behind sould be something similar.
Sam Holder answer is excellent if you have several objects of one (injected) type to create (for example CustomerOrderItem).
If you just want to wire your mainform i would sugest that your mdi-frmMain constructor gets parameters for every childwindow it should contain and let Ninject create and insert the childwindows. This way there is no need to Reference NInject outside "class Program
". This is called Constructor-Injection.
Alternatively you can add a method to the form that adds a page to you mdi (MethodInjection).
static void Main()
{
[...]
IKernel kernel = BuildKernel();
var main = kernel.Get<frmMain>();
main.AddClientForm(kernel.Get<CustomerForm>()) ;
main.AddClientForm(kernel.Get<InvoiceForm>()) ;
Application.Run(main);
}

Thanks to João Almeida and Kellabyte I have found a method that is more or less satisfactory:
Define a custom Attribute which exposes whatever business rules you care about;
Define an implementation of IInjectionHeuristic which recognises this attribute;
Use a ViewModelLocator to load modules into the ninject kernel.

Related

How do I implement IActivationForViewFetcher for a child UserControl?

I've just added ReactiveUI to an existing code base. Of course, for the first control I tried it with I hit a snag. I'm using it with a UserControl embedded in a TabControl. The code looks something like this:
public partial class TabPageControl : UserControl, IViewFor<TestViewModel>
{
public TabPageControl()
{
InitializeComponent();
ViewModel = new TestViewModel();
this.WhenActivated(dispose =>
{
dispose(this.Bind( ... ));
dispose(this.BindCommand( ... ));
});
}
}
When I run the app, I get the following error message:
Don't know how to detect when TabPageControl
is activated/deactivated, you may need to implement
IActivationForViewFetcher
So, how do I implement IActivationForViewFetcher? I'm not sure what I'm supposed to do with GetAffinityForView. I'm assuming in GetActivationForView I need to check to see if the UserControl is the currently visible inside the TabControl?
Although I would like to understand how to implement the methods for IActivationForViewFetcher (especially the part where I identify that a control is in the VisualTree) - the real cause of my problem was that my main assembly didn't have the appropriate references (the controls are in a class assembly).
I'm assuming (because I've skimmed the ReactiveUI source) ReactiveUI.Winforms.Registrations needs to be instantiated by the main assembly - which includes registering ActivationForViewFetcher.
Incidentally, the class library is written in C# and the main assembly is VB.NET. So I'm not sure whether this contributed to the problem.
At least it's working now!
I don't if this will ever help anybody, since this thread is so old.
What solved my issue was having ReactiveUI.WPF,ReactiveUI.WinForms, CefSharp.WPF and CefSharp.WinForms NuGet references on all the projects/plugins that were running on the App.
My suspicion is that when ReactiveUI/CefSharp is initialized and it doesn't contain all the info/files it needs, it will not possible to add them later on runtime. But this is just guessing based on my experience.
I know it's an old thread, but just to save other developers time when facing this problem.
My solution was to add the following code in the entrypoint of the project that makes use of ReactiveUi and ReactiveUi.Wpf.
var reactiveUiWpfName = typeof(ReactiveUI.Wpf.Registrations).Assembly.FullName;
Assembly.Load(reactiveUiWpfName);
Of course, it was just required because I couldn't reference ReactiveUi or ReactiveUi.Wpf in my application startup project due to the project specifications, otherwise this error wouldn't appear anyway.
(Please, observe that, in your case you should use ReactiveUi.Winforms in the places I've used ReactiveUi.Wpf)

Passing dependency injected classes vs a container into an application startup WinForm

I am working on a WinForms application which has been configured into the typical 3 layers of UI, BLL, and DAL. I created a separate project to act as the startup project. Another project was also created to act as a home made dependency injection container with the purpose of performing all the dependency injection setup. The home made dependency injection container is instantiated by the startup project which then passes in the instantiated objects to the first WinForm.
The home made dependency injection container implementation is shown below:
public class AppDependencyInjection
{
public BLL.DataServices.DepartmentDataServices BllDeptDataServices = null;
private DAL.DataServices.DepartmentDataServices DalDeptDataServices = null;
public BLL.ReportServices.RequestReports BllRequestReports = null;
private DAL.ReportServices.RequestReports DalRequestReports = null;
public AppDependencyInjection()
{
DalDeptDataServices = new DAL.DataServices.DepartmentDataServices();
BllDeptDataServices = new BLL.DataServices.DepartmentDataServices(DalDeptDataServices);//inject actual implementations
DalRequestReports = new DAL.ReportServices.RequestReports();
BllRequestReports = new BLL.ReportServices.RequestReports(DalRequestReports);//inject actual implementations
}
}
The startup project is shown below:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//instantiate dependent classes and inject into class constructors
AppDependencyInjection aDI = new AppDependencyInjection();
//Pass objects with injected dependencies into app startup WinForm
Application.Run(new MDIS.WinForms.UI.Form1(aDI.BllDeptDataServices, aDI.BllRequestReports));
}
The receiving WinForm is instantiated as follows with the injected objects:
public Form1(BLL.DataServices.DepartmentDataServices aBllDeptDataServices,
BLL.ReportServices.RequestReports aBllRequestReports)
{
InitializeComponent();
BllDeptDataServices = aBllDeptDataServices;
BllRequestReports = aBllRequestReports;
}
The WinForm uses the injected objects in the following two button click events:
private void btnGetAllDepartments_Click(object sender, EventArgs e)
{
List<DepartmentDto> aDepartmentDtoList = BllDeptDataServices.GetAllDepartments();
}
private void btnGetAllRequests_Click(object sender, EventArgs e)
{
List<RequestDetailDto> aRequestDetailDtoList = BllRequestReports.GetAllRequestDetail();
}
This works for now with not much problem because I am only passing in 2 injected objects. But this seems to be a problem if the number of objects grows to more than 5 then I'll be passing in more than 5 parameters to the startup WinForm. I can limit the parameters to be passed in to just one if I decide to pass in the home made dependency injection container called AppDependencyInjection to the WinForm instead of individual injected classes. If I do this, it will make the presentation layer dependent on the home made dependency injection project, thereby making the presentation layer dependent on both the BLL and the dependency injection project. Is this acceptable? What else can I do to accommodate future growth of dependency injected classes in the application?
But this seems to be a problem if the number of objects grows to more than 5 then I'll be passing in more than 5 parameters to the startup WinForm.
If you inject more than 5 dependencies, that is an indication that your class does too much; has too many responsibilities. It violates the Single Responsibility Principle. If that happens you start thinking about splitting your classes in multiple smaller classes. For instance, you might be able to group certain dependencies and their logic into Aggregate Services or your can split up our Form into multiple smaller components/controls. Rembember: the key is composition.
I decide to pass in the home made dependency injection container called AppDependencyInjection to the WinForm instead of individual injected classes.
You shouldn't do this. This is a pattern called Service Locator and it has many downsides. Stick to dependency injection and only inject what a class directly needs If this gets cumbersome, for instance because a class has too may dependencies, there's something wrong with your code/design (such as a SRP violation).
Also note that it is not advisable to create your own DI library. Such library will lack many important features that the available DI libraries give you, yet gives no advantage over using Pure DI (i.e. hand-wiring object graphs). You lose compile-time support, without getting anything back.
When your application is small, you should start with Pure DI and once your application and your DI configuration grow to the point that maintaining you Composition Root becomes cumbersome, you could consider switching to one of the established DI libraries.
In your case, it seems you are somewhere in the middle. Although dependencies seem to come from a common 'dependency injector', you are still hand-wiring your classes manually without reflection (i.e. you are calling the constructors explicitly). Please be aware that once you are start using reflection, it becomes time to use one of the known DI libraries.

One Windows Form needs an access to the components of another. What is the easiest implementation?

In my project I'm using C++/CLI and Windows Forms. I have two Forms. One is executed in main()
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew FormA);
Another FormB is executed from the instance of FormA
FormB^ fb = gcnew FormB();
fb->Show();
I need to change components of FormB from FormA. Normally they are in private: section of class FormB. Is there any nice way to do that different from simply making them all public? In Native C++ I would use friend class but it's not allowed in C++/CLI.
C++/CLI has an access modifier that native C++ does not have. You are looking for internal:
Empowered by the strong support for modules in .NET. It is broader than friend but you have a pretty hard guarantee that whomever is messing with your private parts is never more than a few cubicles away from yours. Code that accesses internal members must be compiled into the same assembly. So your FormB class must be in the same project as your FormA class. The common case.
If you need the equivalent of friend across modules then you need the [InternalsVisibleTo] attribute. Exposing members with a public property would be another common way.
While providing public access to FormB's members may seem like a quick and easy solution, I would advise you to add some methods on FormB to perform said actions.
This way, you can call those methods from FormA, and at the same time retain proper encapsulation.
Hope this helps.

How to create WPF/Silverlight module utilizing prism but also that can be embedded in non-prism applicationss

I want to have create a WPF or Silverlight module which cannot only be utilised by Shell's bootstrapper, but also can be embedded in non-PRISM applications.
In short is there a way PRISM module can be intialised from module itself rather than initialsing from Shell?
Ulimate goal is to have WPF/Silverlight PRISM module, which can be initialsed by non-PRISM applications.
There is no barrier to this.
The IModule interface has a single, parameterless void method: Initialize().
A non-prism application can initialize the module by calling that method. That's it.
If the other application has a different plugin system, with a different interface, your module can implement that interface as well, and the body of whatever initialization method that interface uses can simply call Initialize(), or vice versa.
For example:
public interface IMyPluginModule
{
void StartModule();
}
public class MyModule : IModule, IMyPluginModule
{
public void Initialize()
{
// actual initialization code here
}
public void StartModule()
{
Initialize();
}
}
It's a little more complicated than it appears at first glance, but it is doable. I don't know if you are using Prism 4 yet, but if so, Microsoft actually provides guidance for this scenario:
http://msdn.microsoft.com/en-us/library/ff921109(v=PandP.40).aspx
There is a bit of project manipulation you need to do to get two projects running side-by-side. There is a sample included with Prism v4 called "MultiTargeting" if you need to see a working sample.
Your question regarding to allowing a module to be initialized by itself, rather than having the orchestrating Shell / Bootstrapper is the wrong approach, however. Essentially what you would have would be two shells... one WPF and one Silverlight. Take a look at the samples and see what you think.
Hope this helps.

How to use DataTemplates in Prism

I have been using Prism for a while now and enjoy how much easier it is to decouple my modules.
This works especially great for views and view models since you can inject the view models via interfaces and the views via the region manager.
Unfortunately this only works when my views are full blown user controls unless I'm missing something here (and I sincerely hope I am).
A lot of times though, I'll create a ViewModel and a matching DataTemplate. These can then be used by other assemblies to compose a view.
My problem is, that I see no way of referring to these datatemplates without referencing the containing assembly, so in my xaml file I write something like:
<ResourceDictionary Source="pack://application:,,/......>
Of course this is not really decoupled, although I try to make sure, that I don't refer to the assembly anywhere else in my code.
Another solution I thought of, was to put the datatemplates into the Infrastructure project, but I don't like that too much either,as I want everything that belongs to a module to be contained in it (except the interfaces of course).
So, does anyone have a good workaround, or did I miss some Prism feature?
I would suggest creating a service that encapsulates adding resource dictionaries to the Application.Resources.MergedDictionaries collection.
// Service interface (defined in the 'infrastructure' project)
public interface IResourceAggregator
{
void AddResource(Uri resourceUri);
}
// Service implementation (implemented at the application/shell level)
class ResourceAggregator : IResourceAggregator
{
public void AddResource(Uri resourceUri)
{
var resourceDictionary = new ResourceDictionary() { Source = resourceUri };
var app = Application.Current;
app.Resources.MergedDictionaries.Add(resourceDictionary);
}
}
I would expect you would "resolve" this service during module load and use it to "register" the module-local resource dictionaries.
You would need to merge the resources when the module starts. You can read more about this here: http://blogs.southworks.net/jdominguez/2008/09/presentation-model-with-datatemplates-in-compositewpf-prism-sample/
Of course you can further abstract this functionality into a reusable service.

Resources