I am facing a problem using dynamically created list of items when Add
method is called on dynamic
variable. Consider following code.
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 });
}
And now, the commented line filteredPlugins.Add(plugin)
will throw System.Reflection.TargetInvocationException
with the message 'object' does not contain a definition for 'Add'
when plugin
is of type
System.ComponentModel.Composition.ExportServices.DisposableLazy<IPlugin,IMetadata>
but it works completely perfect when plugin
is of type
System.Lazy<IPlugin, IMetadata>
When the reflection is used to call Add
method on the instance filteredPlugins
instance as is done on the next line - everything works fine for any type.
My question is WHY is not Add
method found in case of DisposableLazy
type.
This code is part of the method that I use in OnImportsSatisfied()
method. I am using two kinds of import - which differs only in RequiredCreationPolicy
- on has CreationPolicy.NonShared
and the other default value of CreationPolicy.Any
.
[ImportMany(RequiredCreationPolicy = CreationPolicy.NonShared)]
private IEnumerable<Lazy<IPlugin, IMetadata>> plugins = null;
For CreationPolicy.NonShared
fields the underlaying type in the plugins
is DisposableLazy
and for CreationPolicy.Any
the underlaying type in the plugins
is Lazy
.
Edit: As asked in the answer - I am using dynamic
variable because IPlugin
interface can change everytime this method is called and they do not have to have anything in common.
Edit2: I just found similar question C# dynamic type gotcha, so this can be probably closed as duplicite.
Because System.ComponentModel.Composition.ExportServices.DisposableLazy
is a private
class, the runtime binder is having trouble believing you have permission to use type, where reflection doesn't care.
Which begs the question why are you using dynamics at all in this case. Since DisposableLazy<IPlugin,IMetadata>
public interface is it's subclass Lazy<IPlugin, IMetadata>
& IDisposable
, shouldn't you just be using a List<Lazy<IPlugin, IMetadata>>
for either case?
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);
}
}