473,695 Members | 2,421 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C# Plugin system - same interface in two different assemblies...

WTH
I am now aware (I am primarily a C++ developer) that in C# if you reference
the same interface from the same file in two different projects the types
are actually incompatible.

I found this out because I have written a generic plugin system for my
current and future C# needs. I defined a base plugin system interface named
IPlugin (original, I know...) which contains some basic plugin infomration
all plugins of this system must expose (name, friendly name, author,
version, GUID, et cetera) and this interface is defined in the plugin
system's C# file and in its namespace (Common.Utiliti es.PluginSystem .) Then
I have an application, let's call it host.exe which references the plugin
system's namespace and (of course) the 'host' project references the plugin
system's file. The other project is called 'MyPlugin' and it also
references the plugin system's namespace and its project also references the
plugin system's file.

When you compile and build both projects (we haven't even defined an
interface which inherits from IPlugin yet, lol) and run the host.exe
application, the host creates an instance of the plugin manager and tells it
to load the dll produced by the MyPlugin project. No problems. The plugin
manager loads the assembly, checks to see if there are any types of the
interface type requested (host asks the plugin manager to find the interface
type 'IPlugin') and it does. It then makes sure there's a class type which
implements the same interface, and it finds that as well. So far,
everything looks good. The plugin system has found a class that implements
the 'correct' interface in the newly loaded assembly, so it creates an
instances of that type using the activator to create an instance of the type
found in the assembly which matched the criterial we specified ('a class
implementing an interface called IPlugin'.)

Here's where the problem beings. The activator succeeds and returns a type
implementing 'IPlugin' but the returned object handle cannot be case to
IPlugin in host.exe because it throws an exception stating the this is an
invalid cast. Looking at the returned object handle during debugging shows
everything I would expect, and object that implements IPlugin as I had
hoped.

After looking into this a bit I've discovered that the runtime does more
than it appears to when validating types. The assembly name is taken into
account. This means that the runtime considers the interface IPlugin, which
is of course defined in both assemblies so that each assembly can use it, to
be different in each assembly.

Apparently the 'solution' (it really seems like a hack honestly) is to put
IPlugin (and presumably the plugin manager as well while we're at it) in its
own assembly and ensure that the product/tool/whatever remembers to include
it during deployment, and ensure that every developer that wishes to write a
plugin has a copy of that assembly as well.

That's bad enough, but because this plugin system should be generic, a
developer would want to be able to define a new interface in their
tool/product/whatever that derived from IPlugin, for instance
ISuperCoolProdu ctPlugin, and then allow some other developers (potentially
3rd party developers) to be able to create plugins of that type.

Sadly, this means YET ANOTHER assembly must be created, versioned,
supported, and deployed with the first developer's application and given to
the 3rd party to use.

Developer #1 can't put the new interface in the plugin manager's assembly
(which holds IPlugin) because it isn't his to modify, ergo, you have at
least 3 binaries to distribute to run SuperCoolProduc t.exe one of which only
holds the interface ISuperCoolProdu ctPlugin.

That seems ridiculous and very short sighted. Given the enormous
capabilities of reflection and the runtime, how come it can't map the
interfaces properly given that they have THE SAME NAMESPACE... lol. You
would think they would attribute this (or have they already?)

I'm relatively new to C# so I'm wondering if my approach to plugins is
outdated (pre 2.0) or I've missed something like generics and interface
covariance...?

This issue with types in assemblies (especially interfaces) always being
incompatible seems to be a very big issue in regards to code re-usability.

Anytime two assemblies plan to work together and reference the 'same type'
they can't.

Am I using the wrong approach (vanilla interfaces)?

WTH

P.S. BTW, please don't see this as my disrespecting C# because I'm not, it's
fantastic, but so is C++ and that hairy mother has some serious warts - C#
has a few bumps as well, lol. I really just want to write a generic,
re-usable plugin system that has as few deployment dependencies as possible.

Jan 17 '08 #1
7 10597
WTH wrote:
I am now aware (I am primarily a C++ developer) that in C# if you
reference the same interface from the same file in two different
projects the types are actually incompatible.
<snip lengthy explanation>

You got one option: Make a separate assembly declaring the interfaces
you want to be common.

You say it looks like a hack, but .NET is about security and guarantees
in this regard, and the only way to ensure that two interfaces are the
same is to enforce that they are indeed the same. Not just that they
look the same.

So you need the following assemblies (at least):

1. Application host
2. Plugin types
3. Plugin

The host and the plugin both need to reference the common type assembly,
where your interfaces are declared.

Unless the plugin needs to talk to the plugin manager in any way (ie.
use its types), then you can put that in the host application. I'd
probably put that in the external assembly as well but at least here you
can choose.

Note that in .NET 3.5 there is a new plugin system that might define
these common interface for you. I have not looked into it yet though so
I can't really say what it would solve for you, but since Microsoft took
the effort to build a plugin system that supports discoverability ,
extensibility, and err... unloadability.. ., then I think it might do
what you need.

If you use .NET 3.5 and Visual Studio 2008 that is.

--
Lasse Vågsæther Karlsen
mailto:la***@vk arlsen.no
http://presentationmode.blogspot.com/
PGP KeyID: 0xBCDEA2E3
Jan 17 '08 #2
WTH

"Lasse Vågsæther Karlsen" <la***@vkarlsen .nowrote in message
news:%2******** ********@TK2MSF TNGP05.phx.gbl. ..
WTH wrote:
>I am now aware (I am primarily a C++ developer) that in C# if you
reference the same interface from the same file in two different projects
the types are actually incompatible.
<snip lengthy explanation>

You got one option: Make a separate assembly declaring the interfaces you
want to be common.
My post mentions this method.
You say it looks like a hack, but .NET is about security and guarantees in
this regard, and the only way to ensure that two interfaces are the same
is to enforce that they are indeed the same. Not just that they look the
same.
That's not even true for classes much less interfaces. You can match up,
byte for byte types in IL. C# just doesn't appear to let you do this. This
is why I'm looking for alternatives (especially given that I don't know as
much about C# as I should.)
So you need the following assemblies (at least):

1. Application host
2. Plugin types
3. Plugin

The host and the plugin both need to reference the common type assembly,
where your interfaces are declared.
You didn't bother to read my post obviously. I have already explained that
this is the problem, having to do it this way. It works programmaticall y,
but it results in a poor software engineering implementation. I am
currently using this method.
Unless the plugin needs to talk to the plugin manager in any way (ie. use
its types), then you can put that in the host application. I'd probably
put that in the external assembly as well but at least here you can
choose.
I've written quite a few plugin systems and it will be a great value going
forward for the plugin system to reside in the assembly that 3rd party devs
will use (especially given that quite often 3rd party developers want their
plugins to be able to communicate to each other via the 'framework' of the
plugin system.)
Note that in .NET 3.5 there is a new plugin system that might define these
common interface for you. I have not looked into it yet though so I can't
really say what it would solve for you, but since Microsoft took the
effort to build a plugin system that supports discoverability ,
extensibility, and err... unloadability.. ., then I think it might do what
you need.

If you use .NET 3.5 and Visual Studio 2008 that is.
A new plugin system? Do you mean a new assembly loading/unloading
mechanism? Interesting. Thanks for the tip.

WTH

Jan 17 '08 #3
On Jan 17, 4:26 pm, "WTH" <w...@nospam.co mwrote:

<snip>
Is it simpler for developers to (a)not use a shared assembly or (b)use a
shared assembly? a.
Look at it a different way:

Is it simpler for developers to (a) duplicate code or (b) not
duplicate code? b.

Using a common assembly avoids code duplication.

Jon
Jan 17 '08 #4
On Jan 17, 3:49 pm, Lasse Vågsæther Karlsen <la...@vkarlsen .nowrote:

<snip>
So you need the following assemblies (at least):

1. Application host
2. Plugin types
3. Plugin
Not necessarily. The plugin types can be within the application host
assembly, which the plugin then references. This works fine, and I've
done it many times.

Jon
Jan 17 '08 #5
WTH <wt*@nospam.com wrote:
All of those situations mean you've got the code in two places. That
doesn't sound like good practice to me.

? Do you mean it's defined twice?
Yes - the source code for the interface is present twice.
But that's the whole point.
That's duplication, which it's good practice to avoid.
Define it
where and when you need it, don't force people to have it defined all the
time like you would if they have to include an assembly to get one interface
and that assembly contains 30 other interface definitions. The code is
still there. If you simply put one interface per assembly you're only
including in the developers code once but then they have to have all the
assemblies which they 'may' use...
No, they only have to reference the assemblies they *do* use.
No need. Just put each plugin in its host's assembly, and reference
that. If you have many plugins, you have complexity whatever you do.
Duplicating source code just makes that worse, rather than better.

What on earth are you talking about? Put each plugin in its hosts assembly?
Did you mean interface?
Yes, I meant the interface.
If you meant interface, that's a very strange way
to deploy and SDK. What if you're application/host requires licensing?
What if it has a complicated configuration? Serious deployment
dependencies?
Who said anything about configuring it or installing it? You don't need
to do either of those things just to *reference* it.

Of course, if it becomes a problem for any reason, you can separate out
the interface into its own assembly - no problem.

<snip>
But code duplication is A-OK by you is it? Sorry, I really don't buy
it.

You mean multiple definitions of the interface? Do you not realize that
this happens no matter what method you choose? Are you worried about typos
or something? lol.
When somebody re-uses a class that someone else wrote, do you consider that
code duplication and you don't "buy it"?
No, I don't consider that code duplication. The source code only lives
in one place. Changes to it only have to occur in one place, then get
deployed everywhere it's used. I consider that better than having the
source code everywhere that the interface would be used. I'm rather
glad I don't have to include the interface code for IDisposable,
IEnumerable<T>, IList<Tetc in every project which uses them.
The latter is *much* better IMO.

Well, in my experience in supporting the exact scenarios I have described,
it is far easier to develop, support, and extend via the former.
Your experience which is limited in C#, by your own admission.
I'm afraid I see having to duplicate source code as a much bigger wart
than compiling against a fixed binary.

You seem to have latched onto this as your only reasoning as to why C#
cannot discern that two interfaces are identical.
Nope - it's just *one* good reason. It's a good enough one for me.
Various other reasons are also available, but I only need the one.
I'd hate to think of how
you share code with others, presumably you just send them an assembly and if
there's a problem with it, they have to ask you to fix it and ship them a
new assembly.
I suspect that most people who use my open source library only want or
need the DLL. Those who want to change the source can do so - but I'd
expect they'd usually still build to a DLL and reference that.
Assemblies are the units of code reference in .NET - not source code.
Hopefully you're sitting around with nothing to do when this
happens. Here we can't do that. If there's a bug in an SDK client helper
class, the sdk developer can modify it because he has the file, not the
assembly. He doesn't have to wait for a new version of the SDK to come out
in 6 months to a year.
No, but he then has to patch it every time there's a new release of the
SDK. Meanwhile, he may have introduced other bugs. The whole thing's a
versioning nightmare.

I don't expect to convince you, to be honest.

--
Jon Skeet - <sk***@pobox.co m>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
Jan 18 '08 #6
On Jan 17, 3:10 pm, "WTH" <w...@nospam.co mwrote:
"Jon Skeet [C# MVP]" <sk...@pobox.co mwrote in messagenews:MP* *************** ****@msnews.mic rosoft.com...
[...]
No need. Just put each plugin in its host's assembly, and reference
that. If you have many plugins, you have complexity whatever you do.
Duplicating source code just makes that worse, rather than better.

What on earth are you talking about? Put each plugin in its hosts assembly?
Did you mean interface? If you meant interface, that's a very strange way
to deploy and SDK. What if you're application/host requires licensing?
What if it has a complicated configuration? Serious deployment
dependencies? Et cetera.
Er... how is the plugin developer going to *test* his plugin if he
doesn't have the host application installed? I would think that
licensing, configuration, and deployment are issues that you need to
solve anyway, if you want to actually write a plugin that works.

Jesse
Jan 18 '08 #7
WTH
No need. Just put each plugin in its host's assembly, and reference
that. If you have many plugins, you have complexity whatever you do.
Duplicating source code just makes that worse, rather than better.

What on earth are you talking about? Put each plugin in its hosts
assembly?
Did you mean interface? If you meant interface, that's a very strange
way
to deploy and SDK. What if you're application/host requires licensing?
What if it has a complicated configuration? Serious deployment
dependencies ? Et cetera.

Er... how is the plugin developer going to *test* his plugin if he
doesn't have the host application installed? I would think that
licensing, configuration, and deployment are issues that you need to
solve anyway, if you want to actually write a plugin that works.
Generally speaking you have a test harness. You write one to help offload
work from the always understaffed and overwrought QA team to developers who
can use it to run regression tests. Now, you don't need a test harness, I'm
just prone to making QA happy, and most enterprise products are distributed.
For example, I wouldn't install the middleware layer on my development box
so I could build a plugin for it. I'd build a plugin for it, and install it
on one of the development installations (we have several and QA has dozens.)
Personally, I do the test harness method when I can.

WTH

Jan 18 '08 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
1809
by: Reinhold Birkenfeld | last post by:
Hello, another philosophical question: How would you implement a plugin system (for a web-based application)? Conditions are: - One plugin can have one or many "parts" (or "subplugins", or whatever) - Each subplugin has a type - The rest of the plugin interface is dependent on the type
2
1739
by: Dave | last post by:
Hi, all, I'm trying to implement a simple plugin framework, with some unexpected results. I'm using Python 2.3.4 on Windows 2000. My script loader.py loads plugin packages from a directory (in this case its own), and checks a variable defined in the package's __init__.py for information on the plugin. The directory in which loader.py sits is itself a package::
2
20949
by: Rudolf | last post by:
Dear NG, I want to create a Plugin System in C# (WinForms). Has anybody experience about this, tips, tricks, or any links. Thank you very much The DotNetJunkie
7
8448
by: thechaosengine | last post by:
Hi all, Can anyone tell me if it is advisable (or even possible) to define a namespace across 2 or more assemblies? For example, consider the namespace SampleApplication.Data.Providers Would it be possible to have assembly A define a class as part of that namespace as well as Assembly B also declaring a class to be within it as well?
6
1191
by: Craig Buchanan | last post by:
i have two classes: User and Group. Each is in their own assembly. The User class has Groups collection and the Group has a Users collection. I would like to strongly-type these collections, but i can't seem to avoid the circular reference between projects. is there a way around this? Thanks, Craig Buchanan
3
4715
by: Bob S | last post by:
A class in assembly A implements a COM interface as follows : internal interface IMyInterface { int MyMethod(); } class MyClass : IMyInterface
4
2076
by: Arne-Kolja Bachstein | last post by:
Hi there, I am planning to implement a plugin system, based on the observer pattern in some way, but now I am stuck with the instantiation of the plugins. I want the plugins to have their own class, abstracted from the class Plugin. So far its nothing new. But how could I possibly automate the instantiation of the included plugin, without knowing it/hardcoding it? I'd like to have an array of activated plugins and based on this I
0
8647
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8585
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9004
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8864
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8838
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7682
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4592
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2288
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
1986
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.