MEF的错误,是圆形的依赖,现在别的东西 [英] MEF error, was circular dependency and is now something else

查看:292
本文介绍了MEF的错误,是圆形的依赖,现在别的东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个循环依赖,最近来了,因为在我的应用程序体系结构的变化有关。

I've got a circular dependency that recently came about because of a change in my application architecture.

应用程序依赖于一个插件管理器加载插件通过MEF。一切直到工作得很好,因为它看起来是这样的:

The application relies on a plugin manager that loads plugins via MEF. Everything up until worked fine, because it looked something like this:

// model.cs
[Export("Model")]
public class Model
{
  public PluginManager PM { get; set; }

  [ImportingConstructor]
  public Model( [Import] PluginManager plugin_manager)
  {
    PM = plugin_manager;
  }
}

// pluginmanager.cs
[Export(typeof(PluginManager))]
public class PluginManager
{
  [ImportMany(typeof(PluginInterface))]
  private IEnumerable<PluginInterface> Plugins { get; set; }
}

和插件是这样的:

// myplugin.cs
[Export(typeof(PluginInterface))]
public class MyPlugin : PluginInterface
{
}

但现在我有一个情况我想所有的插件有通过接口来查询插件管理(也可能是其他任何物体),了解系统中的其他插件,了解自己的能力的能力。我解决这个通过添加另一个接口,姑且称之为PluginQueryInterface。然后我就在型号实现这个接口。

[Export("Model"))]
[Export(typeof(PluginQueryInterface))]
public class Model : PluginQueryInterface
{
  // same as before
}

,然后插件签名是这样的:

and then the plugin signature would look like this:

// 1st possible implementation
[Export(typeof(PluginInterface))]
public class MyPlugin : PluginInterface
{
  [Import(typeof(PluginQueryInterface))]
  public PluginQueryInterface QueryInterface { get; set; }

  public MyPlugin() {}
}

或本

// 2nd possible implementation
[Export(typeof(PluginInterface))]
public class MyPlugin : PluginInterface
{
  private  PluginQueryInterface QueryInterface { get; set; }

  [ImportingConstructor]
  public MyPlugin( [Import] PluginQueryInterface query_interface)
  {
    QueryInterface = query_interface
  }
}

第二的实施是pretty的显然是一个循环引用,因为插件需要创建插件之前,该PluginQueryInterface被创建,但PluginQueryInterface是Model,必须导入插件管理,而这又需要所有创建的PluginInterfaces的... ...我的确得到了MEF循环依赖错误,当我启动。

The 2nd implementation is pretty clearly a circular reference, because the plugins requires that the PluginQueryInterface be created before the plugin is created, but the PluginQueryInterface is the Model, which must import the PluginManager, which in turn needs all of the PluginInterfaces created... and I do get a MEF circular dependency error when I launch.

第1 执行情况似乎并不像一个循环引用给我。如果PluginQueryInterface是一个属性,那么我认为这将不会得到解决直至使用。和它不使用由构造在所有。那么,为什么不是插件管理欢快创造了我所有的MyPlugins?我得到在这两种情况下相同的MEF错误。

The 1st implementation doesn't seem like a circular reference to me. If the PluginQueryInterface is a property, then I thought it wouldn't be resolved until it was used. And it isn't used by the constructor at all. So why wouldn't the PluginManager merrily create all of my MyPlugins? I get the same MEF error in both cases.

我试图通过再使插件管理实施PluginQueryInterface来解决这个问题,因为:a)它是有意义反正和b)这是一个<一href="http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/"相对=nofollow>众所周知处理循环依赖的方式 - 使两者相互依存类,而不是依赖于一个三等功。现在的问题是,我得到的不同MEF误差!这是这样说的:

I have tried to solve this problem by then making the PluginManager implement the PluginQueryInterface, because a) it makes sense anyway and b) it's a known way of dealing with circular dependencies -- make the two interdependent classes instead depend on a third class. Now the problem is that I get a different MEF error! This is what it says:

GetExportedValue cannot be called before prerequisite import 'Company.App.PluginManager..ctor(Parameter="database_filepath", ContractName="PluginManager.filename")' has been set.

跆拳道?我在code设置断点,我出口值 PluginManager.filename 一直在呼吁GetExportedValue之前设置。

WTF? I set breakpoints in my code, and my exported value PluginManager.filename has been set before calling GetExportedValue.

我完全难住了。任何意见或建议将是pciated现在大大AP $ P $。我一直在敲打我的头靠在MEF覆盖的墙壁几个小时试图调试这个问题。

I am totally stumped. Any observations or suggestions would be greatly appreciated right now. I've been banging my head against the MEF-clad wall for hours trying to debug this problem.

(更新)

我不认为这个较早,但它可能是插件之间的差异,所以我删除了其中的两个插件,现在我的应用程序加载没有MEF的错误。我加了回来,并再次失败。然后,我删除了其他插件,和它的工作。所以它看起来这是其他一些MEF错误。这是几乎一样,如果它不希望我加载多个插件与特定的接口...但我使用ImportMany,并且不会已经体现了自己作为一个 CardinalityException ?

I didn't think about this earlier, but it could have been differences between plugins, so I deleted one of the two plugins, and now my application loads without MEF errors. I added it back, and it failed again. Then I deleted the other plugin, and it worked. So it looks like this is some other MEF error. It's almost as if it doesn't want me to load more than one plugin with a specific interface... but I am using ImportMany, and wouldn't that have manifested itself as a CardinalityException of some kind?

更新

我不明白,这部分MEF的,希望这里有人能解释一下它的全部。步入code一段时间后,我发现我的错误的MEF去除进口的定义源于发现后的值!

I don't understand this part of MEF, and hopefully someone here can explain what it's all about. After stepping into the code for some time, I found that my error stemmed from MEF removing import definitions after finding the value!

    private bool TryGetImportValue(ImportDefinition definition, out object value)
    {
        lock (this._lock)
        {
            if (this._importValues.TryGetValue(definition, out value))
            {
                this._importValues.Remove(definition); // this is the line that got me
                return true;
            }
        }

        value = null;
        return false;
    }

我从来没有过这样的问题,坦白说我有一个很难理解我现在正在做我的进口和出口已经取得了这个问题的表面。我认为我做的东西,MEF的设计者并没有打算任何人去做。我的可以的盲目注释掉 this._importValues​​.Remove(定义); ,但不可能是正确的。我的猜测是,这将归结为我所用的MEF属性,但因为该进口该值的插件有 CreationPolicy.Shared 的创建策略,我为什么要有问题?

I've never had this problem before, and frankly I'm having a hard time understanding what I'm doing now with my imports and exports that has made this problem surface. I assume that I'm doing something that the MEF designers hadn't intended anyone to do. I could blindly comment out the this._importValues.Remove(definition);, but that couldn't possibly be right. My guess is that this will boil down to the MEF attributes I've used, but since the plugin that imports this value has a creation policy of CreationPolicy.Shared, why would I have a problem?

推荐答案

嗯,我有一个可能的解决方案。我没有使用这一点,但使用延迟实例似乎帮助任何经验。至少我可以向前走,而不必更改MEF code,我不完全理解。

Well, I've got a possible solution. I don't have any experience with using this, but using Lazy instantiation seems to help. At least I can move forward without having to change MEF code that I don't completely understand.

这篇关于MEF的错误,是圆形的依赖,现在别的东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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