通过 .NET Core 上的 MEF 将参数传递给插件构造函数? [英] Passing parameters to plugin constructor via MEF on .NET Core?

查看:26
本文介绍了通过 .NET Core 上的 MEF 将参数传递给插件构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了几个小时试图弄清楚如何通过 MEF (System.Composition) 将参数传递给插件构造函数,但都无济于事.不用说,相关文档很少,查看源代码也无济于事.

这曾经很容易做到,使用 CompositionHost.ComposeExportedValue 方法,但在 .NET Core 版本中,我似乎找不到任何有效的方法.我在下面附上了我不完整的代码,然后是抛出的异常.

在这方面的任何帮助将不胜感激.谢谢....

使用系统;使用 System.Composition;使用 System.Composition.Hosting;使用 System.Reflection;命名空间 MefMe{公共接口IPlugin{无效警报();}[导出(typeof(IPlugin))]公共类插件:IPlugin{私人字符串代码;[导入构造函数]公共插件(字符串代码){this.code = 代码;}public void Alert() =>Console.WriteLine(代码);}课程计划{静态无效主(字符串 [] args){var config = new ContainerConfiguration().WithAssembly(Assembly.GetEntryAssembly());var 容器 = config.CreateContainer();//抛出一个 CompositionFailedException;见注释var plugin = container.GetExport();插件.警报();}}}

<块引用>

发生System.Composition.Hosting.CompositionFailedException
HResult=0x80131500 Message=未找到合同的导出'String' -> 部分 'Plugin' 的导入 'code' 需要 -> 需要通过对合同IPlugin"的初始请求源= StackTrace:在System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency依赖项,HashSet1 检查,Stack1 检查)在System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckDependency(CompositionDependency依赖项,HashSet1 检查,Stack1 检查)在System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency依赖项,HashSet1 检查,Stack1 检查)在System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.Execute(CompositionContract合同)在System.Composition.Hosting.Core.ExportDescriptorRegistry.TryGetSingleForExport(CompositionContractexportKey、ExportDescriptor&defaultForExport) 在System.Composition.Hosting.Core.LifetimeContext.TryGetExport(CompositionContract合同、Object&出口)在System.Composition.CompositionContext.GetExport(CompositionContract合同)在System.Composition.CompositionContext.GetExport[TExport](StringcontractName) 在 MefMe.Program.Main(String[] args) 中C:UserslouisDesktopMefMeMefMeProgram.cs:line 36

解决方案

遗憾的是,当前不支持 ComposeExportedValue.有一个开放的 Github Issue 请求该功能.>

有一个冗长的解决方法可以解决问题.我无法找到使用填充值动态创建导出的方法.您可以做的是通过静态参数包使用构造函数中设置的值创建显式属性导出.我已更新您的代码片段以展示我的解决方案.

 命名空间 MefMe{公共接口IPlugin{无效警报();}[导出(typeof(IPlugin))]公共类插件:IPlugin{私人字符串代码;[导入构造函数]公共插件([导入(代码")] 对象代码){this.code = (string)code;}public void Alert() =>Console.WriteLine(代码);}公共类参数{公共静态 IEnumerable>人口参数{得到;放;}[导出(代码",类型(对象))]公共对象代码 { 获取;放;}公共参数(){foreach(PopulatedParameters 中的 var 参数)SetParameter( param.Item1, param.Item2 );}void SetParameter( string nameOfParam, 对象值){var property = typeof( Parameters ).GetProperty( nameOfParam, BindingFlags.Public | BindingFlags.Instance );property.SetValue( this, value );}}公开课计划{静态无效主(字符串[] args){Parameters.PopulatedParameters = new Tuple[] { new Tuple("code", "myvalue") };var config = new ContainerConfiguration().WithAssembly( typeof( IPlugin ).Assembly );var 容器 = config.CreateContainer();//抛出一个 CompositionFailedException;见注释var plugin = container.GetExport();}}}

I spent several hours trying to figure out how to pass parameters to a plugin constructor via MEF (System.Composition) but all to no avail. Needless to say, there are very few relevant docs and a look through the source code didn't help.

This used to be really easy to do, using the CompositionHost.ComposeExportedValue method, but in the .NET Core version I can't seem to find anything that works. I've enclosed my incomplete code, below, followed by the exception that is thrown.

Any help in this regard would be greatly appreciated. Thanks....

using System;
using System.Composition;
using System.Composition.Hosting;
using System.Reflection;

namespace MefMe
{
    public interface IPlugin
    {
        void Alert();
    }

    [Export(typeof(IPlugin))]
    public class Plugin : IPlugin
    {
        private string code;

        [ImportingConstructor]
        public Plugin(string code)
        {
            this.code = code;
        }

        public void Alert() => Console.WriteLine(code);
    }

    class Program
    {
        static void Main(string[] args)
        {
            var config = new ContainerConfiguration()
                .WithAssembly(Assembly.GetEntryAssembly());

            var container = config.CreateContainer();

            // Throws a CompositionFailedException; see notes
            var plugin = container.GetExport<IPlugin>();

            plugin.Alert();
        }
    }
}

System.Composition.Hosting.CompositionFailedException occurred
HResult=0x80131500 Message=No export was found for the contract 'String' -> required by import 'code' of part 'Plugin' -> required by initial request for contract 'IPlugin' Source= StackTrace: at System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency dependency, HashSet1 checked, Stack1 checking) at System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckDependency(CompositionDependency dependency, HashSet1 checked, Stack1 checking) at System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency dependency, HashSet1 checked, Stack1 checking) at System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.Execute(CompositionContract contract) at System.Composition.Hosting.Core.ExportDescriptorRegistry.TryGetSingleForExport(CompositionContract exportKey, ExportDescriptor& defaultForExport) at System.Composition.Hosting.Core.LifetimeContext.TryGetExport(CompositionContract contract, Object& export) at System.Composition.CompositionContext.GetExport(CompositionContract contract) at System.Composition.CompositionContext.GetExport[TExport](String contractName) at MefMe.Program.Main(String[] args) in C:UserslouisDesktopMefMeMefMeProgram.cs:line 36

解决方案

Unfortunately ComposeExportedValue is not currently supported. There is an open Github Issue requesting the feature.

There is a long winded workaround that will do the trick. There is no way that I can find to create exports on the fly with populated values. What you can do is create explicit property exports with the values set in the constructor via a static bag of parameters. I have updated your code snippet to show my solution.

 namespace MefMe
{
    public interface IPlugin
    {
        void Alert();
    }

    [Export( typeof( IPlugin ) )]
    public class Plugin : IPlugin
    {
        private string code;

        [ImportingConstructor]
        public Plugin( [Import( "code" )] object code )
        {
            this.code = (string)code;
        }

        public void Alert() => Console.WriteLine( code );
    }

    public class Parameters
    {
        public static IEnumerable<Tuple<string, object>> PopulatedParameters { get; set; }
        [Export( "code", typeof( object ) )]
        public object code { get; set; }

        public Parameters()
        {
            foreach (var param in PopulatedParameters)
                SetParameter( param.Item1, param.Item2 );
        }

        void SetParameter( string nameOfParam, object value )
        {
            var property = typeof( Parameters ).GetProperty( nameOfParam, BindingFlags.Public | BindingFlags.Instance );
            property.SetValue( this, value );
        }


    }

    public class Program
    {           
        static void Main( string[] args )
        {
            Parameters.PopulatedParameters = new Tuple<string, object>[] { new Tuple<string, object>( "code", "myvalue" ) };

            var config = new ContainerConfiguration()
                .WithAssembly( typeof( IPlugin ).Assembly );
            var container = config.CreateContainer();

            // Throws a CompositionFailedException; see notes
            var plugin = container.GetExport<IPlugin>();

        }
    }
}

这篇关于通过 .NET Core 上的 MEF 将参数传递给插件构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆