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

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

问题描述

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

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

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

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
HResult = 0x80131500消息=未找到合同的出口 '字符串'->由'插件'的导入'代码'所必需->必需 通过合同的初始请求"IPlugin"来源= StackTrace:在 System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency 依赖项,HashSet 1 checked, Stack 1检查)在 System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckDependency(CompositionDependency 依赖项,HashSet 1 checked, Stack 1检查)在 System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.CheckTarget(CompositionDependency 依赖项,HashSet 1 checked, Stack 1检查)在 System.Composition.Hosting.Core.ExportDescriptorRegistryUpdate.Execute(CompositionContract 合同) System.Composition.Hosting.Core.ExportDescriptorRegistry.TryGetSingleForExport(CompositionContract exportKey,ExportDescriptor& defaultForExport) System.Composition.Hosting.Core.LifetimeContext.TryGetExport(CompositionContract 合同,Object&出口) System.Composition.CompositionContext.GetExport(CompositionContract 合同) System.Composition.CompositionContext.GetExport [TExport](字符串 位于MefMe.Program.Main(String [] args)中的 C:\ Users \ louis \ Desktop \ MefMe \ MefMe \ Program.cs:第36行

解决方案

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

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

 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>();

        }
    }
}

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:\Users\louis\Desktop\MefMe\MefMe\Program.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天全站免登陆