【问题标题】:Using PCL MEF2 with Caliburn.Micro将 PCL MEF2 与 Caliburn.Micro 一起使用
【发布时间】:2015-04-08 19:18:59
【问题描述】:

我不确定如何连接 Caliburn.Micro 以使用 MEF2 的 PCL 版本。我见过MefBootstrapper example,但它使用了很多不可用的类,而且我在转换到新的 API 时遇到了麻烦。

这是我目前所拥有的:

using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;
using System.Linq;
using Caliburn.Micro;

namespace Test
{
    public class Bootstrapper : BootstrapperBase
    {
        private CompositionHost _host;

        public Bootstrapper()
        {
            Initialize();
        }

        protected override void Configure()
        {
            var config = new ContainerConfiguration();
            config.WithAssemblies(AssemblySource.Instance);

//            batch.AddExportedValue<IWindowManager>(new WindowManager());
//            batch.AddExportedValue<IEventAggregator>(new EventAggregator());
//            batch.AddExportedValue(container);

            _host = config.CreateContainer();
        }

        protected override object GetInstance(Type serviceType, string key)
        {
            string contract = string.IsNullOrEmpty(key) ? serviceType.ToString() : key;
            var exports = _host.GetExports<object>(contract).ToArray();

            if (exports.Any())
                return exports.First();

            throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
        }

        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return _host.GetExports<object>(serviceType.ToString());
        }

        protected override void BuildUp(object instance)
        {
            _host.SatisfyImports(instance);
        }

        protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
        {
            DisplayRootViewFor<IShell>();
        }
    }
}

但是,CompositionHost 似乎没有任何导出,我不知道如何向其中添加对象(WindowManager 和 EventAggregator)。

【问题讨论】:

    标签: c# .net mef caliburn.micro portable-class-library


    【解决方案1】:

    玩了一会儿之后,这是我想出的,它似乎有效:

    [Export(typeof(IWindowManager))]
    public class MyWindowManager : WindowManager
    {
    }
    
    [Export(typeof(IEventAggregator))]
    public class MyEventAggregator : EventAggregator
    {
    }
    
    public interface IShell
    {
    }
    
    public class AppBootstrapper : BootstrapperBase
    {
        private CompositionHost _host;
    
        public AppBootstrapper()
        {
            Initialize();
        }
    
        protected override IEnumerable<Assembly> SelectAssemblies()
        {
            // TODO: Add additional assemblies here
            yield return typeof(AppBootstrapper).GetTypeInfo().Assembly;
        }
    
        protected override void Configure()
        {
            var config = new ContainerConfiguration();
            var assemblies = AssemblySource.Instance.Union(SelectAssemblies());
            config.WithAssemblies(assemblies);
    
            _host = config.CreateContainer();
        }
    
        protected override object GetInstance(Type serviceType, string key)
        {
            var exports = _host.GetExports(serviceType, key).ToArray();
    
            if (exports.Any())
                return exports.First();
    
            throw new Exception(string.Format("Could not locate any instances of contract {0}.", serviceType.Name));
        }
    
        protected override IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return _host.GetExports<object>(serviceType.ToString());
        }
    
        protected override void BuildUp(object instance)
        {
            _host.SatisfyImports(instance);
        }
    
        protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
        {
            DisplayRootViewFor<IShell>();
        }
    }
    

    【讨论】:

      【解决方案2】:

      我的回复肯定晚了,但也许这对其他在糟糕的 MEF2 文档中苦苦挣扎的人有帮助,如果有人提出更好的实现,或者在这个解决方案中发现任何问题,它肯定也会对我有所帮助;就是这样。

      对于较少面向属性的方法(这是 MEF2 的基本功能之一),并且为了避免将 CM 可注射剂包装到自定义类中的黑客攻击,您必须配置程序集导出,如下所示:

      protected override IEnumerable<Assembly> SelectAssemblies()
      {
          return new[]
          {    
              typeof (IEventAggregator).GetTypeInfo().Assembly,
              typeof (IWindowManager).GetTypeInfo().Assembly,
              typeof (MefBootstrapper).GetTypeInfo().Assembly
          };
      }    
      
      protected override void Configure()
      {
          var config = new ContainerConfiguration();
      
          // note that the event aggregator is in the core CM assembly,
          // while the window manager in the platform-dependent CM assembly,
          // so that we need 2 conventions for 2 assemblies.
          ConventionBuilder cmBuilder = new ConventionBuilder();
          cmBuilder.ForType<EventAggregator>().Export<IEventAggregator>();
      
          ConventionBuilder cmpBuilder = new ConventionBuilder();
          cmpBuilder.ForType<WindowManager>().Export<IWindowManager>();
      
          ConventionBuilder appBuilder = new ConventionBuilder();
          appBuilder.ForTypesMatching(t =>
              t.Name.EndsWith("ViewModel", StringComparison.OrdinalIgnoreCase)).Export();
          appBuilder.ForType<MainViewModel>().Export<IShell>();
      
          config.WithAssembly(typeof(IEventAggregator).GetTypeInfo().Assembly, cmBuilder);
          config.WithAssembly(typeof(IWindowManager).GetTypeInfo().Assembly, cmpBuilder);
          config.WithAssembly(typeof(MefBootstrapper).GetTypeInfo().Assembly, appBuilder);
      
          _host = config.CreateContainer();
      }
      

      基本上,您必须注意以下几点:

      1. CM 对象分布在不同的程序集中,因为其中一些在所有平台之间共享,而另一些则更特定于平台。在这种情况下,事件聚合器位于 CM 核心程序集中,而窗口管理器位于 Caliburn.Micro.Platform 之一。
      2. 在 MEF2 中,您可以使用约定自动将所需对象标记为导出。在我的示例中,我将EventAggregator 标记为导出,作为接口IEventAggregator 选择的实现,对于窗口管理器也是如此;此外,我将我的主视图模型导出为IShell 接口的实现,并通过从我的应用程序集中导出名称以ViewModel 结尾的所有类来导出所有视图模型。这样,我就不需要任何ExportAttribute

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-24
        • 1970-01-01
        • 2017-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-28
        • 1970-01-01
        相关资源
        最近更新 更多