i'm playing with MEF and in the example i see this code ( i call it the MEF compose code):
var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts();
In most examples this is done in the same source file as the Startup Program class lives, as well as all of the other interfaces and classes.
Now i want to use the MEF, but i wonder what this container does. As far as i guessed it does the export / import mapping, but what if i have this code (from a windows forms app:
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
and in that Form1 i want to create an object of type Auditer (which has a property of type ILogger marked import, and i have a class implementing ILogger marked export).
Do i have to place the MEF compose code in the void Main(), in the Load event of Form1, or in the constructor of the Auditer class?
I only get it to work when i put it (the MEF compose code) in the constructor of the Auditer class, but the examples i read somehow give me the idea that you only have to call the compose code once.
The CompositionContainer is the class that actually composes your parts in MEF.
When you want to use MEF, you need to always compose the part that's attributed with the import definitions. If you have a property in Form1 that's marked with [Import(typeof(ILogger))], at some point, you'll need to compose your Form1 instance.
The CompositionContainer is the class that actually performs this composition. It finds the appropriate exported ILogger based off the Catalog(s) contained within the container, and constructs types, matches exports to the imports, etc.
The reason that the MEF samples only "compose" one time is that, often, with DI, you'll have a single instance of the container constructed and setup at the beginning of the application, and it will compose your "main" window. All other classes will be composed automatically if they're being used as part of the main window. (For example, if Form1 composes an ILogger, but your ILogger implementation has an [Import] of it's own, it too will get composed in that pass.)
That being said, there is no fixed rule that specifies you can't compose more than once. In WPF and Silverlight, for example, it's frequent that MEF can't construct your object, which means it can't automatically compose your object for you. In these situations, a common pattern is to use the CompositionInitializer (in the box in Silverlight, not in the desktop) to have parts compose themselves, based off a static catalog. I recently blogged about this approach for WPF.
With Windows Forms, this may be less necessary, since there isn't a third party product (the XAML parser) constructing your types. However, you could still use this same approach, if you so choose.
Related
I am developing a modular WPF application with Prism in .Net Core 5.0 (using MVVM, DryIoc) and I would like to have a module that is not a WPF module, i.e., a module with functionality that can be used by any other module. I don't want any project reference, because I want to keep the loosely coupled idea of the modules.
My first question is: is it conceptually correct? Or is it mandatory that a module has a screen? I guess it should be ok.
The second and more important (for me) is, what would be the best way to create the instance?
This is the project (I know I should review the names in this project):
HotfixSearcher is the main class, the one I need to get instantiated. In this class, for example, I subscribe to some events.
And this is the class that implements the IModule interface (the module class):
namespace SearchHotfix.Library
{
public class HotfixSearcherModule : IModule
{
public HotfixSearcherModule()
{
}
public void OnInitialized(IContainerProvider containerProvider)
{
//Create Searcher instance
var searcher = containerProvider.Resolve<IHotfixSearcher>();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IHotfixSearcher, HotfixSearcher>();
}
}
}
That is the only way I found to get the class instantiated, but I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
For modules that have screens, the instances get created when navigating to them using the RequestNavigate method:
_regionManager.RequestNavigate(RegionNames.ContentRegion, "ContentView");
But since this is only a library with no screens, I can't find any other way to get this instantiated.
According to Prism documentation, subscribing to an event shoud be enough but I tried doing that from within my main class HotfixSearcher but it does not work (breakpoints on constructor or on the event handler of the event to which I subscribe are never hit).
When I do this way, instead, the instance is created, I hit the constructor breakpoint, and obviously the instance is subscribed to the event since it is done in the constructor.
To sum up, is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
Thanks in advance!
Or is it mandatory that a module has a screen?
No, of course not, modules have nothing to do with views or view models. They are just a set of registrations with the container.
what would be the best way to create the instance?
Let the container do the work. Normally, you have (at least) one assembly that only contains public interfaces (and the associated enums), but no modules. You reference that from the module and register the module's implementations of the relevant interfaces withing the module's Initialize method. Some other module (or the main app) can then have classes that get the interfaces as constructor parameters, and the container will resolve (i.e. create) the concrete types registered in the module, although they are internal or even private and completely unknown outside the module.
This is as loose a coupling as it gets if you don't want to sacrifice strong typing.
is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
You can skip the var searcher = part :-) But if the HotfixSearcher is never injected anywhere, it won't be created unless you do it yourself. OnInitialized is the perfect spot for this, because it runs after all modules had their chance to RegisterTypes so all dependencies should be registered.
If HotfixSearcher is not meant to be injected, you can also drop IHotfixSearcher and resolve HotfixSearcher directly:
public void OnInitialized(IContainerProvider containerProvider)
{
containerProvider.Resolve<HotfixSearcher>();
}
I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
It is used, I suppose, although not through calling one of its methods. It's used by sending it an event. That's just fine. Think of it like Task.Run - it's fine for the task to exist in seeming isolation, too.
I'm working on legacy code.
I have different methods of the same class that pass different arguments to the constructor of a dependency. I'm trying to get some basic IoC usage introduced. Right now I have StructureMap passing my arguments like this:
var thing = ObjectFactory.GetInstance<IThingInterface>(new ExplicitArguments(
new Dictionary<string, object> {
{ "constructorArgA", notShown },
{ "constructorArgB", redacted.Property } }));
Where the actual properties passed for constructorArgA and B change depending on where I am.
Instead of "constructorArgA" is there a way to configure this via actual types, like you can do when configuring the objectFactory, like:
x.For<IHidden>().Use<RealType>()
.Ctor<IConfig>().Is(new Func<IContext, IConfig>(
(context) => someMethodToGetIConfig()));
If I were writing this from scratch I'd probably structure the dependencies a bit different to avoid this, but that's not an option for me right now.
This is something of a classic/common question with DI Containers.
My first choice would be to create a "manual" abstract factory to create IThingInterface, and then use Structuremap to inject IThingInterfaceFactory where it is needed. By manual factory, I mean a class the calls new ThingInterface() and returns it. If you do it this way, your implementation will no longer be container-managed, and if it has dependencies, they would no longer be provided by the container (may or may not be a problem for you).
Second choice would be to create an abstract factory that actually uses/wraps the container. So basically your first code snippet but wrapped in a factory class where the Create() method takes your parameters. This has the advantage of everything (including your implementation and its dependencies) being container-managed, but the disadvantage of referencing your container directly (which is not a best practice--see Article on Composition Roots).
You could also do setter injection, but I would personally consider it a last resort.
Castle Windsor has a good solution to this problem built in (Typed Factory Facility). Not sure if switching containers in an option, but you might consider it.
I understand that a MEF CompositionContainer creates and keeps instances of classes. I don't know under what circumstances a CompositionContainer has a class instance in its bowels.
Can anybody list operations performed on the CompositionContainer or methods of the CompositionContainer class that cause the CompositionContainer to store an instance of a class within the CompositionContainer.
Is it possible to view class instances held within a CompositionContainer in the debugger or any other fashion?
The CompositionContainer will keep references to all shared parts for the lifetime of the CompositionContainer. (The default CreationPolicy is Any for both imports and exports, which means by default all parts will be shared unless otherwise specified.)
References to NonShared parts will be kept if the part implements IDisposable. The reference will be released when the root export that was pulled from the container is released (if that export was from a NonShared part). Exports can be released either by calling CompositionContainer.ReleaseExport, or ExportLifetimeContext.Dispose for exports created with an ExportFactory.
I don't think there's any simple way to view what's held by the CompositionContainer. The source code is available so you could theoretically dive into it and figure out exactly where it's stored.
In regards to your second question (#2 above) ...
Using the QuickWatch Window (Shift + F9) or a regular Watch window, copy the following in there:
((System.ComponentModel.Composition.Hosting.CompositionContainer)(this.Container))._catalogExportProvider._activatedParts
The line above assumes that the object you are stopped on has a "this.Container" property, which is the CompositionContainer of the scope you are referring to.
From there, you'll get an array of ActivatedParts. You then navigate the dictionary of Parts. Find the Part Definition you want to find the instance of, and expand its "Non-Public Members". There you will find the CachedInstance, and this will be the instance of your "Shared" exported part that's been created.
I think Parts that are exported NonShared and not IDisposable aren't cached or held onto at all. At least that's the behavior I've seen.
I'm learning prism V4 using MEF to load my modules. Loading modules does work, but in one module I want to load a View/ViewModel (MVVM) and don't really know how I get MEF to resolve all this stuff for me.
First: how do I need to mark the ViewModel (I follow the StockTraderRI example) so it is not loaded on startup but instead can be loaded during runtime into a region?
Second: how do I load the ViewModel using MEF so it gets connected to the corresponding interfaces?
MEF does this very nicely for things on startup which are marked as [Export], but I got no idea how to achieve this during runtime.
You can use what is known as a Lazy Export so that the interface is not resolved until you explicitly use it.
If you need to create multiple instances, MEF doesn't support this particularly well. You can either do your own discovery and instantiation, or you can define the Export like this:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(ISomething)]
public class Something : ISomething { }
The downside is that now wherever you need to create the instance, you need to have a reference to the actual Container instance. Then you can do:
var something = _container.GetExportedObject<ISomething>();
EDIT: Okay, I think I understand better what you're after. Here is how I've typically resolved this issue:
I implement my View objects as UserControl instances and don't set a DataContext anywhere in their code or XAML.
I create a DataTemplate that binds from the Type of the ViewModel to the UserControl.
On my MainViewModel (or whatever corresponds to the View hosting the regions), I expose a general RegionX Object (possibly typed to an interface if all of my ViewModels will share some common functionality, but Object works fine).
I create a ContentPresenter with Content bound to the RegionX property.
Now my MainViewModel can import different ViewModel instances corresponding to the types of ViewModels that might be hosted by the RegionX. When I want to switch the 'active' View in the region, I simply set RegionX to the corresponding ViewModel.
Suppose that the ApplicationSettings class is a general repository of settings that apply to my application such as TimeoutPeriod, DefaultUnitOfMeasure, HistoryWindowSize, etc... And let's say MyClass makes use of one of those settings - DefaultUnitOfMeasure.
My reading of proper use of Inversion of Control Containers - and please correct me if I'm wrong on this - is that you define the dependencies of a class in its constructor:
public class MyClass {
public MyClass(IDataSource ds, UnitOfMeasure default_uom) {...}
}
and then call instantiate your class with something like
var mc = IoC.Container.Resolve<MyClass>();
Where IDataSource has been assigned a concrete implementation and default_uom has been wired up to instantiate from the ApplicationSettings.DefaultUnitOfMeasure property. I've got to wonder however, if all these hoops are really that necessary to jump through. What trouble am I setting myself up for should I do
public class MyClass {
public MyClass(IDataSource ds) {
UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
}
}
Yes, many of my classes end up with a dependency on IoC.Container but that is a dependency that most of my classes will have anyways. It seems like I maybe should make full use of it as long as the classes are coupled. Please Agile gurus, tell me where I'm wrong.
IoC.Container.Resolve("default_uom");
I see this as a classic anti-pattern, where you are using the IoC container as a service locater - the key issues that result are:
Your application no longer fails-fast if your container is misconfigured (you'll only know about it the first time it tries to resolve that particular service in code, which might not occur except for a specific set of logic/circumstances).
Harder to test - not impossible of course, but you either have to create a real (and semi-configured) instance of the windsor container for your tests or inject the singleton with a mock of IWindsorContainer - this adds a lot of friction to testing, compared to just being able to pass the mock/stub services directly into your class under test via constructors/properties.
Harder to maintain this kind of application (configuration isn't centralized in one location)
Violates a number of other software development principles (DRY, SOC etc.)
The concerning part of your original statement is the implication that most of your classes will have a dependency on your IoC singleton - if they're getting all the services injected in via constructors/dependencies then having some tight coupling to IoC should be the exception to the rule - In general the only time I take a dependency on the container is when I'm doing something tricky i.e. trying to avoid a circular dependency problems, or wish to create components at run-time for some reason, and even then I can often avoid taking a dependency on anything more then a generic IServiceProvider interface, allowing me to swap in a home-bake IoC or service locater implementation if I need to reuse the components in an environment outside of the original project.
I usually don't have many classes depending on my IoC container. I usually try to wrap the IoC stuff in a facade object that I inject into other classes, usually most of my IoC injection is done only in the higher layers of my application though.
If you do things your way you can't test MyClass without creating a IoC configuration for your tests. This will make your tests harder to maintain.
Another problem is that you're going to have powerusers of your software who want to change the configuration editing your IoC config files. This is something I'd want to avoid. You could split up your IoC config into a normal config file and the IoC specific stuff. But then you could just as well use the normal .Net config functionality to read the configuration.
Yes, many of my classes end up with a dependency on IoC.Container but that is a dependency that most of my classes will have anyways.
I think this is the crux of the issue. If in fact most of your classes are coupled to the IoC container itself chances are you need to rethink your design.
Generally speaking your app should only refer to the container class directly once during the bootstrapping. After you have that first hook into the container the rest of the object graph should be entirely managed by the container and all of those objects should be oblivious to the fact that they were created by an IoC container.
To comment on your specific example:
public class MyClass {
public MyClass(IDataSource ds) {
UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
}
}
This makes it harder to re-use your class. More specifically it makes it harder to instantiate your class outside of the narrow usage pattern you are confining it to. One of the most common places this will manifest itself is when trying to test your class. It's much easier to test that class if the UnitOfMeasure can be passed to the constructor directly.
Also, your choice of name for the UOM instance ("default_uom") implies that the value could be overridden, depending on the usage of the class. In that case, you would not want to "hard-code" the value in the constructor like that.
Using the constructor injection pattern does not make your class dependent on the IoC, just the opposite it gives clients the option to use the IoC or not.