在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.Any
中plugins
中的下划线类型为Lazy
。
编辑:正如答案中所提到的 - 我正在使用dynamic
变量,因为每次调用此方法时IPlugin
接口都可以更改,并且它们不必包含任何内容常见的。
编辑2:我刚发现了类似的问题C# dynamic type gotcha,因此可能会将其视为重复项。
答案 0 :(得分:2)
因为System.ComponentModel.Composition.ExportServices.DisposableLazy
是private
类,所以运行时绑定程序很难相信您有权使用类型,而反射并不关心。
这引出了一个问题,在这种情况下你为什么要使用动力学呢?由于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);
}
}