Sign in to follow this  

[C#] DLL Class-Interface Casting

This topic is 2855 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a very basic interface defining 3 functions: Load, Release, and Update. I also have 2 projects, one project which loads DLLs and calls functions based on the interface prototype and another which outputs a DLL containing a class whose base is the interface prototype. My goal is to load a DLL at runtime and instantiate a copy of the DLL's class, holding it in an interface container. I'm fairly positive that my problem has to do with how I'm compiling my interface class. I copied the interface file from my original project into the DLL, and then derived from the interface in the DLL project to create the new class. Here is the code I use to load the DLL... private IPlugin LoadPluginDLL(string DLLPath) { Assembly pluginASM = Assembly.LoadFile(DLLPath); Type[] types = pluginASM.GetTypes(); foreach (Type type in types) { if (type.IsClass) { object pluginObj = Activator.CreateInstance(type); IPlugin plugin = (IPlugin)pluginObj; bool isIPlugin = type.IsInstanceOfType(plugin); return plugin; } } return null; } Were you to run this code, it would throw the exception that pluginObj cannot be cast to type IPlugin, although their parents share exactly the same source code in separate files/projects. The system does not recognize the similar parents, as the IsInstanceOfType will return false. I would really like to derive a variable of type IPlugin out of this rather than use the MethodInvoke. Thanks!

Share this post


Link to post
Share on other sites
You can't just ensure that they share the same source code. Types in .NET are the sum of their source, namespace, and parent assembly. So even though they share the same name and the same source, your two IPlugin interfaces are distinctly separate objects at runtime.

There's a good reason for this; namely, what would you expect to happen if you accidentally modified the source of one of them so that they didn't match up anymore? You can imagine the craziness that this could cause (C++ programmers could tell you I'm sure).

Anyway, the solution is to have a third assembly DLL containing the interface type, and then reference that assembly from both your application and the plugin DLL.

Share this post


Link to post
Share on other sites
Hehe, I was fairly sure of that being the problem. I really appreciate the feedback. That's a pretty good idea, I didn't think of adding an intermediate DLL. It seems strange though that there's not a more robust way. I'm trying to set it up so that a third party can develop plugins for a program as simply as possible. I guess if this is the only way, then that's the best it can be. Again, major kudos for the feedback!

Share this post


Link to post
Share on other sites
Actually I just created the other DLL and tied it in, turns out it's an insanely simple and pain-free process! As a C++ developer I'm continually impressed by how amazing C# and .NET is.

That being said, after compiling and linking a release DLL containing the interface it is still unable to recognize it as a base class of my plugin. Both projects are linked properly, as there is code in both projects referencing the IPlugin and that all works as intended. Also the source for the IPlugin has been removed from both projects, so it's not a case of local conflict... I'll continue to search for a simple error...


-Edit
I'm not quite sure what it was, but a clean rebuild and relinking the references fixed my problem. It now works as intended.

For a microguide to anyone else who's interested in creating plugins in C#:
(This is all pseudo-code written on the fly, please don't tear it apart)

Create an interface class. This will be a facade between the program and the plugin.
Note that interface classes can't contain variables.

namespace x
{
interface y
{
void func(int args);
}
}

Compile this class as a DLL. When you create a new project you can specify the project to be a "Class Library", it will build a DLL instead of an EXE.

Link your program and your plugin to the interface DLL. Simple add the newly created DLL in the References tab on the solution explorer (assuming MSVC# here).

Once linked to your projects, you should be able to derive your plugin from your interface class.

On the plugin, you should override all functions defined in the interface class. You may also add variables and such as if it where a stand-alone program. If you want your plugin to have extra functionality specific to your program, you can add it your interface DLL.

Conversely, on the program you may use the System.Reflection functionality to dynamically load your plugin.

Example:

private IPlugin LoadPluginDLL(string DLLPath)
{
Assembly pluginASM = Assembly.LoadFile(DLLPath);
Type[] types = pluginASM.GetTypes();
foreach (Type type in types)
{
if (type.IsClass)
{
object pluginObj = Activator.CreateInstance(type);
IPlugin plugin = pluginObj as IPlugin;
bool isIPlugin = type.IsInstanceOfType(plugin);
return plugin;
}
}
return null;
}

It's a bit of a hassle but there are a lot of really neat applications for this type of system. I hope this helps!

[Edited by - SeiryuEnder on February 23, 2010 9:08:50 PM]

Share this post


Link to post
Share on other sites

This topic is 2855 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this