WPF w/ Unity Loading Modules Based on Interface - wpf

I'm writing a WPF app using Prism/Unity.
I have my main app (with a bootstrapper).
I have interfaces for each of my modules. For example:
MyModuleA implements IMyModuleA
MyModuleB implements IMyModuleB
I want to implement loose coupling and dependency injection.
So in my bootstrapper, I want to specify that I'm loading a library (type) based on an interface. This would allow me build the module independently.
In my bootstrapper, I have the following:
protected override void ConfigureModuleCatalog() {
base.ConfigureModuleCatalog();
string path = #"Modules.MyModuleA.dll";
var assembly = Assembly.LoadFrom(path);
var type = assembly.GetType("Modules.MyModuleA.MyModuleA");
ModuleCatalog.AddModule(new ModuleInfo {
ModuleName = type.Name,
ModuleType = type.AssemblyQualifiedName,
Ref = new Uri(path, UriKind.RelativeOrAbsolute).ToString()
});
}
Is this the best way to do it?

I must say this is not the best way to do that because you are still specifying type by string which is even worse because leaves space for human error. Dependency injection and loose coupling is about using Interface and registering different types implementing that interface on the fly.
If you want to load different modules on the fly for the same interface you should use your own Bootstraper which is called at desired code path. And inside of it use:
if(shouldUseEmail)
Container.RegisterType<IFeedbackService, EmailFeedbackService>();
else
Container.RegisterType<IFeedbackService, SMSFeedbackService>();
And later on you resolve like this:
var feedbackService = Container.Resolve<IFeddbackService>();
Or use DI (dependency injection in constructors)

Related

How to pass data to an external assembly User Control through MEF

I am a beginner in MEF. According to my requirement I have to show the multiple plugin UI according to the selection of plugin. For that I have to pass plugin related data to the external plugin UserControl.
[InheritedExport(typeof(IConnect))]
public interface IConnect{}
Below code is using to initializing the external UI from the main application,
[ImportMany(typeof(IConnect))]
public IEnumerable<Lazy<IConnect>> Plugins;
....
var catalog = new DirectoryCatalog(#"C:\TestDll\");
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
var childControl = SelectedPlugin as UserControl;
//Here I have to pass the required data to the usercontrol. How to do this?
Dockpanel.Children.Add(childControl );
Could you please suggest a way to pass data to the external user control
Our entire team here at work has been using MEF for years now, and I'm reasonably familiar with how it works.
To get everything bootstrapped off the ground, the first thing to do is ensure that a common MEF container is shared between your main application and the user control in your external assembly.
If you don't have a common MEF container, then your MEF imported classes will never be able to communicate with the host application, as they will be living in separate MEF universes.
Once you have a common container, anywhere you want to bootstrap a class out of the container, you can use something like this:
var test = MefContainer.GetExportedValue<ITest>();
test.Run();
Q. How do I add MEF to my project?
A. Using NuGet, search for "microsoft composition", and add MEF 2.
Q. So how do we create this shared MEF container?
A. As follows:
Follow through a tutorial such as From Zero to Proficient with MEF.
Create a class library that is shared between your imported control, and the host application.
In this class library, create a singleton class called MefContainer. This means that anybody that wants to grab something out of the MEF container can reference this singleton to obtain the MEF container. The MEF container contains classes from all of the auto-discovered assemblies in the directories that we want to scan.
Q. How do I communicate with the user control?
A. Add this class to your shared class library:
public interface ITest
{
string SharedValue { get; set; }
}
[Export(typeof(ITest))]
public class Test : ITest
{
[ImportingConstructor]
public Test()
{
}
public string SharedValue { get; set; }
}
Now, both the host app and the user control can grab an instance of the same class out of the MEF container:
var test = MefContainer.GetExportedValue<ITest>();
var result = test.SharedValue;
By default, classes that are obtained from the MEF container are singleton's, unless we explicitly say that we want non-shared classes.
Q. How about adding Reactive Extensions (RX)?
It's ok to have a class with shared values. But it's nicer if one component can fire events off, and any other component can listen to this event.
To do this, add RX to your project using NuGet (search for "reactive extensions", add "Reactive Extensions - Main Library").
Add a Subject to your shared class:
private Subject<string> MyEvent { get; set; }
Now, if you have a MEF reference to this shared class, you can send an event out:
var t = MefContainer.GetExportedValue<ITest>();
t.MyEvent.OnNext("hello");
And, any other class can subscribe to these events:
var t = MefContainer.GetExportedValue<ITest>();
t.MyEvent.Subscribe(
o =>
{
Console.Write(o);
});
If code is already running in the MEF composition container, then there is no need to use MefContainer to get at the container. You can simply MEF import the shared communication class using the constructor:
public interface IClassRunningInContainer
{
}
[Export(typeof(IClassRunningInContainer))]
public class ClassRunningInContainer : IClassRunningInContainer
{
[ImportingConstructor]
public ClassRunningInContainer(ITest t)
{
t.OnNext("Hello, world!");
}
}
Final Notes
Don't make the mistake of using MEF as a general dependency injection (DI) solution. You will run into roadblocks further down the road, as MEF is does not have the level of built in diagnostics to find out if things have gone wrong, compared to a dedicated dependency injection solution, such as Unity.
The ideal pattern is to use MEF for importing whole assemblies, then use Unity as your day to day DI container.

Loading dependencies in Unity Container in WinForms application

This is how the solution partially looks like.
Since I am using the Onion Architecture in a Winforms environment, hence I have the UI, Infrastructure and Core layers. All the layers are loosely coupled using Dependency Injection. What I want to achieve is that whenever a form from e.g. Accounts Forms (Class Library) is loaded, all the dependencies for that should be loaded in the UnityContainer i.e. types registered. These dependencies are interfaces and implementations present in Core and Infrastructure projects.
My confusion is that where should I write the code to register dependencies? What would be the Composition Root for this application? Please note that forms from e.g. Accounts Forms, HR Forms, etc are all loaded using reflection in the Main Windows application which references only the Base Forms Project.
After Eben Roux's suggestions
Here is how I am executing the wireup code when the assembly is loaded:
Dim assemb As System.Reflection.Assembly
...
...
If assemb IsNot Nothing Then
Dim type As Type = GetType(IDependencyWiring)
Dim modules As List(Of Type) = assemb.GetTypes().Where(Function(p) type.IsAssignableFrom(p) AndAlso p.IsClass).ToList()
For Each [module] As Type In modules
Dim argTypes As Type() = New Type() {}
Dim cInfo As ConstructorInfo = [module].GetConstructor(argTypes)
Dim dependencyWiringModule As IDependencyWiring = DirectCast(cInfo.Invoke(Nothing), IDependencyWiring)
dependencyWiringModule.WireUp()
Next
End If
Here's is the Module having the WireUp method:
Public Class AccountModule : Implements IDependencyWiring
Private Shared Container As IUnityContainer
Public Sub New()
Container = New UnityContainer()
End Sub
Public Sub WireUp() Implements IDependencyWiring.WireUp
Container.RegisterType(Of IInterface1, Class1)()
Container.RegisterType(Of IInterface2, Class2)()
Container.RegisterType(Of IInterface3, Class3)()
Container.RegisterType(Of IInterface4, Class4)()
End Sub
Public Shared Function Resolve(typeToResolve As Type) As Object
Return Container.Resolve(typeToResolve.GetType())()
End Function
End Class
So my questions now are:
Is it the right approach to store the Container as Shared and use it to resolve dependencies via Resolve method?
There is a problem in the way I am encapsulating the Resolve behavior of the Container. What would be the right syntax for that? I don't want to reference Unity on each of the form to be able to call the Resolve method, so I am encapsulating that i my own Resolve method. In this way I could easily replace the AccountModule with another one if I want to change the IOC Container without having the change the container references everywhere.
With this type of plug-in architecture you effectively end up with more than one composition root (of sorts). There will in all probability be some dependencies only your plug-in knows about and can wire up.
So part of your architecture should be the loading of the plug-ins. This probably happens somewhere in the main application in the wire-up bit (composition root) which would then give each plug-in the opportunity to perform its wiring.
Since not all plug-ins may need wiring one could make that explicit by using a seperate interface:
public interface IDependencyWiring
{
public void WireUp(IDependencyContainer container); // <-- changed to conform to update
}
And then in the main composition root:
foreach (var plugin in plugins)
{
var wiring = plugin as IDependencyWiring;
if (wiring != null)
{
wiring.WireUp(myContainer);
}
}
I hope that makes sense.
Update:
Firstly I would use a safe cast. TryCast in the VB.NET world. You could use dependency iversion to get rid of Unity from the actual plug-ins by using your own interface. Something like so:
public interface IDependencyContainer
{
void Register(Type type);
void Register<T>();
void Resolve(Type type);
void Resolve<T>();
}
Well, you would add what you need. Then pass in the reference to the container in the wire-up as I did up top public void WireUp(IContainer container);.
The Resolve behahiour is somewhat problematic in that you seem to be headed in a Service Locator direction. Try to get as much of the resolving done by the container by using constructor (or other) injection. Of course this works fine for Singleton components. For the Transient ones I'd rather use a Singleton factory that receives an instance of the IDependencyContainer (so that will also be registered), and it does the resolving (creation, really) for you.

WPF / Prism library and multiple shells

I'm pretty new with Prism and after playing a bit around, there a few questions that arise. I'm trying to create a modular application that basically contains a map control in a shell window. The plugin modules offer different tools for interacting with the map. Some of the modules are pretty independent and simply display pins on the map.
1st question: How would RegionManager come into play for the module-specific classes (presenters) that must interact with the main map control? Usually in a RegionManager you register a specific view which is linked to a ViewModel, but in my case there is one single view (the map view) with multiple presenters acting on it.
2nd question: I need to be able to open several windows (shells) -- a bit like an MS Word document -- that should all be extended by the plugin modules. In a single-shell environment, when the module specific classes were instantiated, they could use the Dependency Injection Container to get a reference to the RegionManager or the Shell itself in order to get access to the map control. However with multiple shells, I don't see how to get access to the map control of the right shell. The dependency container has references to object global to the application, not specific for the shell I'm currently working in. Same is true for the EventAggregator.
Any input would be very welcome,
Ed
After hours of reading Prism-related articles and forums I've come across the article "How to build an outlook style application" on Erwin van der Valk's Blog - How to Build an Outlook Style Application.
In one part of the architecture, a Unity Child Container was used to resolve type instances. That's exactly what I needed for the answer to my 2nd question: I needed to have "scoped" (by window) dependency injection (ex: window scoped EventAggregator, Map control, etc.)
Here's how I create a new window:
private IShellWindow CreateNewShell(IRegionManager regionManager)
{
IUnityContainer childContainer = this.Container.CreateChildContainer();
... register types in child container ...
var window = new ShellWindow();
RegionManager.SetRegionManager(window, regionManager);
window.Content = childContainer.Resolve<MapDocumentView>();
return window;
}
So MapDocumentView and all its components will be injected (if needed) window-scoped instances.
Now that I can have scoped injected objects, I can get the window-scoped map in my module-based MapPresenter. To answer my 1st question, I defined an interface IHostApplication which is implemented by the Bootstrapper which has a MapPresenterRegistry property. This interface is added to the main container.
Upon initialization, the modules will register their presenters and upon the window creation, they will be instantiated.
So for the module initialization:
public void Initialize()
{
...
this.hostApplication.MapPresenterRegistry.Add(typeof(ModuleSpecificMapPresenter));
...
}
The code that initializes the map window:
private void View_Loaded(object sender, RoutedEventArgs e)
{
// Register map in the == scoped container ==
container.RegisterInstance<IMap>(this.View.Map);
// Create map presenters
var hostApplication = this.container.Resolve<IHostApplication>();
foreach (var mapPresenterType in hostApplication.MapPresenterRegistry)
{
var mapPresenter = this.container.Resolve(mapPresenterType) as IMapPresenter;
if (mapPresenter != null)
{
this.mapPresenters.Add(mapPresenter);
}
}
}
The module-specific MapPresenter:
public ModuleSpecificMapPresenter(IEventAggregator eventAggregator, IMap map)
{
this.eventAggregator = eventAggregator;
this.map = map;
this.eventAggregator.GetEvent<AWindowSpecificEvent>().Subscribe(this.WindowSpecificEventFired);
// Do stuff on with the map
}
So those are the big lines of my solution. What I don't really like is that I don't take advantage of region management this way. I pretty much have custom code to do the work.
If you have any further thoughts, I would be happy to hear them out.
Eduard
You have one main view and many child views, and child views can be added by different modules.
I'm not sure that the RegionManager class can be applied in this situation, so I would create a separate global class IPinsCollectionState
which must be registered as singleton in the bootstrapper.
public interface IPin
{
Point Coordinates { get; }
IPinView View { get; }
//You can use a view model or a data template instead of the view interface, but this example is the simplest
}
public interface IPinsCollectionState
{
ObservableCollection<IPin> Pins { get; }
}
Your main view model and different modules can receive this interface as a constructor parameter:
public class MapViewModel
{
public MapViewModel(IPinsCollectionState collectionState)
{
foreach (var item in collectionState.Pins)
{ /* Do something */ };
collectionState.Pins.CollectionChanged += (s, e) => {/* Handle added or removed items in the future */};
}
//...
}
Example of a module view model:
public class Module1ViewModel
{
public Module1ViewModel(IPinsCollectionState collectionState)
{
//somewhere in the code
collectionState.Pins.Add(new Module1Pin());
}
}
The second question can be solved in many different ways:
Application.Current.Windows
A global MainViewModel which contains the list of ShellViewModels and if you add new view model it will be displayed in new window. The bootstrapper is single for all windows.
Some kind of shared state which is passed to the constructor of the bootstrapper.
I don't know how these windows are related between themselves, and I don't know which way is the best, maybe it is possible to write an application with separated windows.

Considerations when architecting an extensible application using MEF

I've begun experimenting with dependency injection (in particular, MEF) for one of my projects, which has a number of different extensibility points. I'm starting to get a feel for what I can do with MEF, but I'd like to hear from others who have more experience with the technology. A few specific cases:
My main use case at the moment is exposing various singleton-like services that my extensions make use of. My Framework assembly exposes service interfaces and my Engine assembly contains concrete implementations. This works well, but I may not want to allow all of my extensions to have access to all of my services. Is there a good way within MEF to limit which particular imports I allow a newly instantiated extension to resolve?
This particular application has extension objects that I repeatedly instantiate. I can import multiple types of Controllers and Machines, which are instantiated in different combinations for a Project. I couldn't find a good way to do this with MEF, so I'm doing my own type discovery and instantiation. Is there a good way to do this within MEF or other DI frameworks?
I welcome input on any other things to watch out for or surprising capabilities you've discovered that have changed the way you architect.
Is there a good way within MEF to
limit which particular imports I allow
a newly instantiated extension to
resolve?
Load the extension code in a separate container, and make sure that the restricted parts are not available in that container. Let's simplify the situation to these classes to construct an example:
[Export]
public class MyExtension
{
[Import]
public PublicService Service { get; set; }
}
[Export]
public class PublicService
{
}
[Export]
public class InternalService
{
}
[Export]
public class Program
{
[Import]
public MyExtension Extension { get; set; }
[Import]
public PublicService Service1 { get; set; }
[Import]
public InternalService Service2 { get; set; }
}
The goal is to allow MyExtension to import PublicService, but not InternalService. Internal code like Program should be able to import anything. You can achieve that like this:
var publicCatalog = new TypeCatalog(typeof(PublicService), typeof(MyExtension));
var publicContainer = new CompositionContainer(publicCatalog);
var internalCatalog = new TypeCatalog(typeof(Program), typeof(InternalService));
var internalContainer =
new CompositionContainer(internalCatalog, publicContainer);
var program = internalContainer.GetExport<Program>();
This code will not throw a composition exception. If you now change the import on MyExtension to the forbidden InternalService, you will get a composition exception as desired.
A side effect of this set-up is that PublicService cannot import any private services either, just like MyExtension. This kind of makes sense, because otherwise nothing would stop PublicService from exposing a private service via a property.
I have used TypeCatalog for the example, but in practice you should probably use something like the FilteredCatalog sample.
This particular application has
extension objects that I repeatedly
instantiate. I can import multiple
types of Controllers and Machines,
which are instantiated in different
combinations for a Project. I couldn't
find a good way to do this with MEF,
so I'm doing my own type discovery and
instantiation. Is there a good way to
do this within MEF or other DI
frameworks?
You might just be after the PartCreationPolicy attribute, which controls whether a part is shared (as in, created only once per container) or instantiated multiple times for each import. You can also specify the RequiredCreationPolicy parameter in an import attribute.
If that doesn't solve your problem, take a look at the PartCreator sample in the MEF sources (though note that it will probably soon be renamed to ExportFactory, it already has been in the silverlight edition of MEF).

Silverlight: Cannot use reflection to GetValue of a field across XAPs?

I have a Silverlight application which has two different XAPs - an InitialXAP which is loaded statically by the HTML page and a DynamicXAP which is loaded from code within the initial XAP. The DynamicXAP is loaded with code similar to this:
var asm = LoadAssemblyFromXap(stream, "DLLName");
// LoadAssemblyFromXAP will load the DynamicXAP as a file stream,
// unpack it and load DLLName as a dll.
var controllerType = asm.GetType("ClassNameToInstantiate_InsideAsm");
var constructor = controllerType.GetConstructor(Type.EmptyTypes);
return constructor.Invoke(null);
I have a class which uses reflection (specifically FieldInfo.GetValue) to do data binding. This class is defined in the InitialXAP. If I try to use this class in the DynamicXAP, I get an error:
Message: Unhandled Error in Silverlight Application System.FieldAccessException: Class.In.DynamicXAP.Which.Uses.The.Reflection.Class.In.InitialXAP
at System.Reflection.RtFieldInfo.PerformVisibilityCheckOnField(IntPtr field, Object target, IntPtr declaringType, FieldAttributes attr, UInt32 invocationFlags)
at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, Boolean doVisibilityCheck, Boolean doCheckConsistency)
at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, Boolean doVisibilityCheck)
at System.Reflection.RtFieldInfo.GetValue(Object obj)
I can get around this error by creating a subclass of the class using reflection and overriding the method using reflection like so:
public class InitialXAP.ClassUsingReflection {
public virtual object GetValue()
{
return fieldInfo.GetValue(parent);
}
}
public class ClassUsingReflection : InitialXAP.ClassUsingReflection {
public override object GetValue()
{
return fieldInfo.GetValue(parent);
}
}
But I would prefer to avoid this duplication by allowing reflection from the InitialXAP in the DynamicXAP. Any ideas on what I can do?
Although there is a learning curve, I would look at Silverlight MEF or Prism (both are together at last in the latest Prism 4 Beta). They both support dynamic loading of modules and enforce good patterns for reuse and separate/team development.
InitialXAP.ClassUsingReflection...
Note the duplicate isn't part of the inital xap namespace (ClassUsingReflection), and may be imported.
Notice GetVisible - as in not visible to Dynamic xap...
Just leave the duplicate (take away base class obviously) and try.

Resources