首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Caliburn.Micro中使用PCL MEF2

在Caliburn.Micro中使用PCL MEF2
EN

Stack Overflow用户
提问于 2015-04-09 03:19:00
回答 2查看 337关注 0票数 0

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

这是我到目前为止所知道的:

代码语言:javascript
复制
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)。

EN

回答 2

Stack Overflow用户

发布于 2015-07-11 05:09:43

在尝试了一下之后,下面是我想出的方法,它似乎起作用了:

代码语言:javascript
复制
[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>();
    }
}
票数 1
EN

Stack Overflow用户

发布于 2015-12-15 02:09:30

我的回复肯定是晚了,但也许这对其他正在为可怜的MEF2文档而苦苦挣扎的人有帮助,当然它也可能对我有帮助,如果有人想出更好的实现,或者在这个解决方案中发现任何问题;所以就是这样。

对于面向属性较少的方法(这是基本的MEF2特性之一),为了避免将CM注入包包装到自定义类中的麻烦,您必须配置程序集导出,如下所示:

代码语言:javascript
复制
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标记为exports,作为要为接口IEventAggregator选择的实现,对于窗口管理器也是如此;此外,我将主视图模型作为IShell接口的实现导出,并通过从我的应用程序集中导出名称以ViewModel结尾的所有类来导出所有视图模型。这样,我就不需要任何ExportAttribute.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29523482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档