MEF 插件没有来自主机的数据

发布于 2024-11-10 06:40:46 字数 2812 浏览 2 评论 0原文

我试图将配置数据从主机放入插件,但我总是在插件处得到空值。我负责插件的代码如下:

Form:

public partial class MyForm : Form
{
    public MyForm()
    {
        InitializeComponent();

        DataStorage.Instance.LoadModes();
        DataStorage.Instance.ActiveMode = "aaa";
        DataStorage.Instance.RulesFile = "bbb";
        DataStorage.Instance.SetProjectName("cccc");
        DataStorage.Instance.LoadRules();
        DataStorage.Instance.LoadPlugins();

    }
}

DataStorage:

[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(ConfigStorage))]  
public class DataStorage: ConfigStorage
{

    //fields and properties here

    public string ActiveMode;

    [ImportMany(typeof (IAPlugin))]
    public IEnumerable<Lazy<IAPlugin, IAPluginData>> aPlugins;

    [ImportMany(typeof (IBPlugin))]
    public IEnumerable<Lazy<IBPlugin, IBPluginData>> bPlugins;

    private CompositionContainer _container;

    private static readonly DataStorage instance = new DataStorage();

    static DataStorage()
    {
    }

    private DataStorage()
    {
            Init();
    }


    public static DataStorage Instance
    {
        get { return instance; }
    }


    private void Init()
    {
        //code here
    }

    public void LoadPlugins()
    {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(ConfigStorage).Assembly));
        catalog.Catalogs.Add(new DirectoryCatalog(Settings.Default.GetPathFor("Plugins")));

        _container = new CompositionContainer(catalog);

        try
        {
            _container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }
}

ConfigStorage:

public abstract class ConfigStorage
{

    public string RulesFile;
    public string ActiveMode;
//properties and methods
}

Plugin:

[Export(typeof (IAPlugin))]
[ExportMetadata("Name", "myNameIsBond")]
public class myNameIsBond :  IAPlugin
{

     protected readonly ConfigStorage configStorage;

     [ImportingConstructor]
     public myNameIsBond (ConfigStorage configStorage)
    {
        if (configStorage == null)
            throw new ArgumentNullException("configStorage");
        this.configStorage = configStorage;
    }


    public string DoStep(string url)
    {
        Console.WriteLine(configStorage.ActiveMode); //this is null - it should be "aaa"
        return url;
    }

}

当我运行 plugin.Value.DoStep("sth"); the Console.WriteLine(configStorage.ActiveMode); 总是打印 null - 当我调试时:configStorage 中的所有字段都是 null。我做错了什么?如何将 DataStorage 实例放入我的插件中?

I'm trying to put config data from host to plugins but I always get nulls at plugins. My code responsible for plugins is below:

Form:

public partial class MyForm : Form
{
    public MyForm()
    {
        InitializeComponent();

        DataStorage.Instance.LoadModes();
        DataStorage.Instance.ActiveMode = "aaa";
        DataStorage.Instance.RulesFile = "bbb";
        DataStorage.Instance.SetProjectName("cccc");
        DataStorage.Instance.LoadRules();
        DataStorage.Instance.LoadPlugins();

    }
}

DataStorage:

[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(ConfigStorage))]  
public class DataStorage: ConfigStorage
{

    //fields and properties here

    public string ActiveMode;

    [ImportMany(typeof (IAPlugin))]
    public IEnumerable<Lazy<IAPlugin, IAPluginData>> aPlugins;

    [ImportMany(typeof (IBPlugin))]
    public IEnumerable<Lazy<IBPlugin, IBPluginData>> bPlugins;

    private CompositionContainer _container;

    private static readonly DataStorage instance = new DataStorage();

    static DataStorage()
    {
    }

    private DataStorage()
    {
            Init();
    }


    public static DataStorage Instance
    {
        get { return instance; }
    }


    private void Init()
    {
        //code here
    }

    public void LoadPlugins()
    {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(ConfigStorage).Assembly));
        catalog.Catalogs.Add(new DirectoryCatalog(Settings.Default.GetPathFor("Plugins")));

        _container = new CompositionContainer(catalog);

        try
        {
            _container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            Console.WriteLine(compositionException.ToString());
        }
    }
}

ConfigStorage:

public abstract class ConfigStorage
{

    public string RulesFile;
    public string ActiveMode;
//properties and methods
}

Plugin:

[Export(typeof (IAPlugin))]
[ExportMetadata("Name", "myNameIsBond")]
public class myNameIsBond :  IAPlugin
{

     protected readonly ConfigStorage configStorage;

     [ImportingConstructor]
     public myNameIsBond (ConfigStorage configStorage)
    {
        if (configStorage == null)
            throw new ArgumentNullException("configStorage");
        this.configStorage = configStorage;
    }


    public string DoStep(string url)
    {
        Console.WriteLine(configStorage.ActiveMode); //this is null - it should be "aaa"
        return url;
    }

}

When I run plugin.Value.DoStep("sth"); the Console.WriteLine(configStorage.ActiveMode); always print null - when I debugging: all fields from configStorage are nulls. What I'm doing wrong? How can I put DataStorage instance to my plugins?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不顾 2024-11-17 06:40:46

我认为问题在于 ConfigStorage 导出显示在目录中,因此导入对目录创建的版本而不是您配置的单例感到满意。尝试将 PartNotDiscoverableAttribute 放在 DataStorage 类上。

顺便说一句,您的 DataStorage 构造函数是私有的,但看起来目录仍然可以创建它的单独版本,因为构造函数是通过反射调用的。

I think the problem is that the ConfigStorage export is showing up in the catalog, so the imports are getting satisfied with a version created by the catalog instead of the singleton you have configured. Try putting a PartNotDiscoverableAttribute on the DataStorage class.

As an aside, your DataStorage constructor is private, but it looks like the catalog can still create a separate version of it because the constructor is invoked through reflection.

沙沙粒小 2024-11-17 06:40:46

我通常根本不使用实例变量,只是让 MEF 创建单例,但如果您确实想要拥有实例属性,您可以执行类似的操作

// note that there is no export attribute here
public class DataStorage: ConfigStorage
{
    [Export(typeof(ConfigStorage))] 
    public static DataStorage instance { get; private set; }
}

,以便 MEF 将导出您的单例实例而不是创建新对象。

I typically don't use an instance variable at all and just let MEF create the singleton, but if you really want to have an instance property you can do something like

// note that there is no export attribute here
public class DataStorage: ConfigStorage
{
    [Export(typeof(ConfigStorage))] 
    public static DataStorage instance { get; private set; }
}

So that MEF will export your singleton instance rather than creating a new object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文