Using MEF I want to do the following.
I have a WPF Shell. To the shell I want to Import from another DLL a UserControl that is also a View of my MVP triad. The way the MVP triad works, is that in presenter I have a constructor that takes both IModel and IView and wires them up. So, in order for this to work, I need MEF to do the following:
Instead what it does, is it only creates the type Exporting IView and passes it to the shell, basically skipping steps 2 and 3. Its pretty logical, when you think about it, but how can I tell MEF to also create the whole triad when I ask for a IView. I don't need to reference Presenter nor model anywhere else in my Shell .dll so puting it as an Import as well is not an option (and it would be quite ugly anyway :).
I'm using the latest drop of MEF (Preview 2 Refresh). Anyone?
==Update==
I have found a solution and I blogged about it here:
Krzysztof Koźmic's blog - Creating tree of dependencies with MEF
However, I'd be more than happy if someone came up with a better solution.**
Check my answer here.
http://codebetter.com/blogs/glenn.block/archive/2008/11/12/mvp-with-mef.aspx
EDIT: (Added from the link, to prevent not being flagged as low quality / LOA)
1: using System.ComponentModel.Composition;
2: using System.Reflection;
3: using Microsoft.VisualStudio.TestTools.UnitTesting;
4:
5: namespace MVPwithMEF
6: {
7: /// <summary>
8: /// Summary description for MVPTriadFixture
9: /// </summary>
10: [TestClass]
11: public class MVPTriadFixture
12: {
13: [TestMethod]
14: public void MVPTriadShouldBeProperlyBuilt()
15: {
16: var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
17: var container = new CompositionContainer(catalog.CreateResolver());
18: var shell = container.GetExportedObject<Shell>();
19: Assert.IsNotNull(shell);
20: Assert.IsNotNull(shell.Presenter);
21: Assert.IsNotNull(shell.Presenter.View);
22: Assert.IsNotNull(shell.Presenter.Model);
23: }
24: }
25:
26: [Export]
27: public class Shell
28: {
29: private IPresenter _presenter = null;
30:
31: public IPresenter Presenter
32: {
33: get { return _presenter; }
34: }
35:
36: [ImportingConstructor]
37: public Shell(IPresenter presenter)
38: {
39: _presenter = presenter;
40: }
41: }
42:
43: public interface IModel
44: {
45: }
46:
47: [Export(typeof(IModel))]
48: public class Model : IModel
49: {
50:
51: }
52:
53: public interface IView
54: {
55: }
56:
57: [Export(typeof(IView))]
58: public class View : IView
59: {
60: }
61:
62: public interface IPresenter
63: {
64: IView View { get;}
65: IModel Model { get; }
66: }
67:
68: [Export(typeof(IPresenter))]
69: public class Presenter : IPresenter
70: {
71:
72: private IView _view;
73: private IModel _model;
74:
75: [ImportingConstructor]
76: public Presenter(IView view, IModel model)
77: {
78: _view = view;
79: _model = model;
80: }
81:
82: public IView View
83: {
84: get { return _view; }
85: }
86:
87: public IModel Model
88: {
89: get { return _model; }
90: }
91:
92: }
93: }
So what’s going on here?
Shell gets injected with Presenter. Presenter gets injected with View and Model. Everything here is singletons, but doesn’t have to be.
The difference between our two examples is that the Presenter is getting injected into the shell rather than the View. If the Presenter is creating the View then you can’t just grab the View first (as he was doing), or the Presenter will not get created. Well you can do it, but you end up hacking it to bits. Cleaner is to just inject the Presenter and have it expose an IView. We did this in Prism and it worked quite well.