Creating tree of dependencies with MEF

As a fol­low up to my pre­vi­ous post, here’s the sim­pli­fied – Con­sole based ver­sion of the code.

Dis­claimer.

This is a solu­tion. Not the best one, not rec­om­mended by any­one, just the one that hap­pened to solve my prob­lem. So take it with a (big) grain of salt, and if you know a bet­ter one, use the Leave your com­ment func­tion below.

using System;
using System.ComponentModel.Composition;
using System.Reflection;
 
[assembly:AllowNonPublicComposition]
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ComposablePartCatalog catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly());
 
            var container = new CompositionContainer(catalog.CreateResolver());
 
            var shell = new Shell();
 
            container.AddPart(shell);
            container.Compose();
            shell.View();
 
            Console.ReadKey(true);
        }
    }
 
    public class Shell
    {
        [Import("View")]
        private IShellView _view;
 
 
        public void View()
        {
            if (_view == null)
            {
                Console.WriteLine("view is null");
            }
            else
            {
                _view.Show();
            }
 
        }
    }
 
    public interface IShellView
    {
        void Show();
    }
 
    [Export(typeof(IMyView))]
    class ShellView : IShellView, IMyView
    {
        public void Show()
        {
            Go(this, EventArgs.Empty);
            Console.WriteLine(SomeProperty);
        }
        public event EventHandler Go;
        public string SomeProperty
        {
            set;
            private get;
        }
    }
 
 
    public interface IMyView
    {
        event EventHandler Go;
        string SomeProperty { set; }
    }
 
    public class Presenter
    {
        [Export("View")]
        private IMyView _view;
 
        [ImportingConstructor]
        public Presenter(IMyView view, IModel model)
        {
            this._view = view;
            _view.Go += delegate { _view.SomeProperty = model.Text; };
        }
    }
 
    public interface IModel
    {
        string Text { get; }
    }
 
    [Export(typeof(IModel))]
    class Model : IModel
    {
        public string Text
        {
            get { return DateTime.UtcNow.ToString(); }
        }
    }
}

The thing to note is, that the Export with the key “View” and of type IShel­lView is not pro­vided directly by any type imple­ment­ing the inter­face. Instead it its exported by the pre­sen­ter, as a field that gets set by MEF via con­struc­tor. That way, when the Shell needs the “View” MEF sees that it needs to cre­ate a Pre­sen­ter for that, and in order to cre­ate pre­sen­ter it needs to use the Import­ing­Con­struc­tor, and pro­vide it with IMyView and IModel. Since the type imple­ment­ing the IView is IMyView it gets injected into the Pre­sen­ter. Also, since it imple­ments IShel­lView as well, it sat­is­fies the needs of Shell and gets injected into it.

Pretty sweet, and no code was required to achieve this (except for some Attribute magic).

Tech­no­rati Tags: