使用动态变量调用时,DisposableLazy`2列表没有“添加”方法

时间:2013-06-05 13:04:01

标签: dynamic reflection mef lazy-evaluation

问题

Add变量上调用dynamic方法时,使用动态创建的项列表时遇到问题。请考虑以下代码。

IEnumerable<dynamic> plugins = (IEnumerable<dynamic>)field.GetValue(instance);
if (plugins == null)
  continue;

dynamic filteredPlugins = null;
foreach (var plugin in plugins)
{
  if (filteredPlugins == null)
  filteredPlugins = Activator
    .CreateInstance(typeof(List<>)
    .MakeGenericType(plugin.GetType()));

if (/* this condition does not matter*/)
  //filteredPlugins.Add(plugin);
  filteredPlugins.GetType().GetMethod("Add")
    .Invoke(filteredPlugins, new object[] { plugin });
}

现在,当filteredPlugins.Add(plugin)类型为

时,注释行System.Reflection.TargetInvocationException会向'object' does not contain a definition for 'Add'发送消息plugin
System.ComponentModel.Composition.ExportServices.DisposableLazy<IPlugin,IMetadata>

plugin类型为

时,它完全有效
System.Lazy<IPlugin, IMetadata>

当反射用于在实例Add实例上调用filteredPlugins方法时,如下一行所做的那样 - 一切都适用于任何类型。

我的问题是为什么Add类型的情况下找不到DisposableLazy方法。

背景

此代码是我在OnImportsSatisfied()方法中使用的方法的一部分。我使用的是两种导入 - 仅在RequiredCreationPolicy中有所不同 - on CreationPolicy.NonShared,另一种默认值为CreationPolicy.Any

[ImportMany(RequiredCreationPolicy = CreationPolicy.NonShared)]
private IEnumerable<Lazy<IPlugin, IMetadata>> plugins = null;

对于CreationPolicy.NonShared字段,plugins中的下划线类型为DisposableLazy,而CreationPolicy.Anyplugins中的下划线类型为Lazy

编辑:正如答案中所提到的 - 我正在使用dynamic变量,因为每次调用此方法时IPlugin接口都可以更改,并且它们不必包含任何内容常见的。

编辑2:我刚发现了类似的问题C# dynamic type gotcha,因此可能会将其视为重复项。

1 个答案:

答案 0 :(得分:2)

因为System.ComponentModel.Composition.ExportServices.DisposableLazyprivate类,所以运行时绑定程序很难相信您有权使用类型,而反射并不关心。

这引出了一个问题,在这种情况下你为什么要使用动力学呢?由于DisposableLazy<IPlugin,IMetadata>公共接口是它的子类Lazy<IPlugin, IMetadata>&amp; IDisposable,您是否应该仅使用List<Lazy<IPlugin, IMetadata>>进行任何一种情况?

var plugins = (IEnumerable<Lazy<IPlugin, IMetadata>>)field.GetValue(instance);
if (plugins == null)
  continue;

var filteredPlugins = new List<Lazy<IPlugin, IMetadata>>();
foreach (var plugin in plugins)
{
  if (/* this condition does not matter*/)
     filteredPlugins.Add(plugin);
  }
}