Creating tree of dependencies with MEF

As a follow up to my previous post, here’s the simplified – Console based version of the code.

Disclaimer.

This is a solution. Not the best one, not recommended by anyone, just the one that happened to solve my problem. So take it with a (big) grain of salt, and if you know a better one, use the Leave your comment function 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 IShellView is not provided directly by any type implementing the interface. Instead it its exported by the presenter, as a field that gets set by MEF via constructor. That way, when the Shell needs the “View” MEF sees that it needs to create a Presenter for that, and in order to create presenter it needs to use the ImportingConstructor, and provide it with IMyView and IModel. Since the type implementing the IView is IMyView it gets injected into the Presenter. Also, since it implements IShellView as well, it satisfies the needs of Shell and gets injected into it.

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

Technorati Tags: