6

I'm trying to load some .dll files dynamically. The Files are Plugins (self-written for now) which have at least one class that implements MyInterface. For each file I'm doing the following:

    Dictionary<MyInterface, bool> _myList;

    // ...code

    Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
    foreach (Type type in assembly.GetTypes())
    {
        var myI = type.GetInterface("MyInterface");
        if(myI != null)
        {
            if ((myI.Name == "MyInterface") && !type.IsAbstract)
            {
                var p = Activator.CreateInstance(type);
                _myList.Add((MyInterface)p, true);
            }
        }
    }

Running this causes a cast exception, but I can't find a workaround. Anyway I am wondering why this doesn't work at all. I'm looking for a solution in .NET Framework 3.5.

Another thing that happened to me was getting null in p after running the following at the point before adding a new entry to _myList in the code above:

var p = type.InvokeMember(null, BindingFlags.CreateInstance, null,
                          null, null) as MyInterface;

This code was the first attempt on loading the plugins, I didn't find out why p was null yet. I hope someone can lead me to the right way :)

Phil
  • 130
  • 6
  • 1
    this code is not working, what is x and where you init it? – Marcelo De Zen Aug 08 '12 at 15:51
  • In your code snippet above, is "x" in "if (x !=null)" really supposed to be "myI"? – David W Aug 08 '12 at 15:52
  • You should also verify that the type has a default constructor, since your code assumes that. – Adi Lester Aug 08 '12 at 15:52
  • I don't understand `var myI = type.GetInterface("MyInterface"); if(x != null)`. Should it be `if (myI != null)`? – Robert Harvey Aug 08 '12 at 15:53
  • 2
    [Activator.CreateInsance(type)](http://msdn.microsoft.com/ru-ru/library/0hcyx2kd.aspx) assumes there is a parameterless constructor of your type. What kind of exception do you get? If it's `MissingMethodException` the problem (almost for sure) is that your class does not have a parameterless constructor. – J0HN Aug 08 '12 at 16:01
  • I renamed x sorry for that I edited it. Yes my "Plugin" has a parameterless constructor and I'll check that too if it's working so far. I get a `InvalidCastException` – Phil Aug 08 '12 at 16:05
  • @Z3R0 Is it possible the `InvalidCastException` comes from the type's constructor? – Adi Lester Aug 08 '12 at 16:08
  • the type's constructor is `MyPlugin(){}` and the stack trace says it's on the `_myList.Add(...);` line. btw it says "PluginTest.MyPlugin cannot be PluginSystem.MyInterface" – Phil Aug 08 '12 at 16:14

3 Answers3

5

There's much easier way to check if your type can be casted to your interface.

Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
foreach (Type type in assembly.GetTypes())
{
    if(!typeof(MyInterface).IsAssignableFrom(type))
        continue;

    var p = Activator.CreateInstance(type);
    _myList.Add((MyInterface)p, true);
}

If IsAssignableFrom is false, there's something wrong with your inheritance, which is most likely cause of your errors.

Sergei Rogovtcev
  • 5,804
  • 2
  • 22
  • 35
  • well yes it's `false`. However I have only one member now and really don't know what could be wrong with the inheritance. – Phil Aug 08 '12 at 16:40
  • Does your "plugin" assembly reference the assembly where interface is defined? Does your running code (code in sample) reference *same* assembly? – Sergei Rogovtcev Aug 08 '12 at 16:50
4

You should really read Plug-ins and cast exceptions by Jon Skeet which explains the behaviour you see and how to do plug-in frameworks properly.

Indy9000
  • 8,651
  • 2
  • 32
  • 37
  • What I could take out of it was that the plugin's assembly is not the same as my application's assembly. – Phil Aug 08 '12 at 16:47
  • I wish more people would vote this one up, as I think that's probably the OP's issue. Basically, if you think of this like C++, and the Interface definition like a .h file, you'll run into this error. If you think of it in a "managed types" way you'll see that there's two interfaces, one per file, if it's being compiled the (wrong) way the link says it might be. – Kevin Anderson Aug 08 '12 at 16:49
1

Please look into the following code. I think Type.IsAssignableFrom(Type type) can help you out in this situation.

Assembly assembly = Assembly.LoadFrom(currentFile.FullName);
///Get all the types defined in selected  file
Type[] types = assembly.GetTypes();

///check if we have a compatible type defined in chosen  file?
Type compatibleType = types.SingleOrDefault(x => typeof(MyInterface).IsAssignableFrom(x));

if (compatibleType != null)
{
    ///if the compatible type exists then we can proceed and create an instance of a platform
    found = true;
    //create an instance here
    MyInterface obj = (ALPlatform)AreateInstance(compatibleType);

}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
mchicago
  • 780
  • 9
  • 21