【问题标题】:How Caliburn.micro uses MEF to import custom pluginsCaliburn.micro 如何使用 MEF 导入自定义插件
【发布时间】:2017-08-07 15:51:48
【问题描述】:

我在插件目录中有一些扩展插件。我打算在ViewModel中导入插件并使用它,但是我无法成功导入。我想我没有办法成功配置Configure,求指教。

引导程序:

public class AppBootstrapper : BootstrapperBase
{
    private CompositionContainer container;

    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void Configure()
    {
        string pluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");
        if (!Directory.Exists(pluginPath))
            Directory.CreateDirectory(pluginPath);

        var fi            = new DirectoryInfo(pluginPath).GetFiles("*.dll");
        AssemblySource.Instance.AddRange(fi.Select(fileInfo => Assembly.LoadFrom(fileInfo.FullName)));

        var catalog       = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
        var batch         = new CompositionBatch();
        container         = new CompositionContainer(catalog);

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

        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue(catalog);

        container.Compose(batch);
    }

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

    protected override object GetInstance(Type service, string key)
    {
        var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;
        var exports = this.container.GetExportedValues<object>(contract);

        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 service)
    {
        return this.container.GetExportedValues<object>(AttributedModelServices.GetContractName(service));
    }

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

视图模型

 [ImportMany]
 IEnumerable<Lazy<IPlugin, IPluginsMetaData>> plugins;

【问题讨论】:

    标签: c# wpf mvvm mef caliburn.micro


    【解决方案1】:

    其实我的Bootstrapper并没有问题,问题出现在我的IPlugin类。在找问题的过程中,我也找到了Bootstrapper的Configure方法用另一种写法。我会把整个插件代码都贴出来给大家参考下~

    BootStrapper 配置

    protected override void Configure()
    {
        var catalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>());
        var batch   = new CompositionBatch();
        var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins");
    
        if (!Directory.Exists(path))
            Directory.CreateDirectory(path);
    
        catalog.Catalogs.Add(new DirectoryCatalog(path));
        container = new CompositionContainer(catalog);
    
        batch.AddExportedValue(container);
        batch.AddExportedValue<IWindowManager>(new WindowManager());
    
        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue(catalog);
    
        container.Compose(batch);
    }
    

    ShellViewModel

    [Export(typeof(IShell))] 
    public class ShellViewModel : Conductor<object>, IShell
    {
        [ImportMany]
        IEnumerable<Lazy<IPlugin, IPluginMetaData>> plugins;
    }
    

    IPlugin

    public interface IPlugin
    {
         void Do();
    }
    
    public interface IPluginMetaData 
    {
         string Name { get; }
    
         string Code { get; }
    
         //[... more attribute ...]
    }
    
    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class PluginExportAttribute : ExportAttribute, IPluginMetaData
    {
        public string Name { get; set; }
    
        public string Code { get; set; }   
    
        //[... more attribute ...]
    
        public PluginExportAttribute() : base(typeof(IPlugin)) { }
    }
    

    PluginOne

    [PluginExport(Name = "PluginOne", Code = "Key")]
    public class PluginOne : IPlugin
    {
         public void Do()
         {
           Console.WriteLine("I'm PluginOne");
         } 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多