Re: C# Plugin system - same interface in two different assemblies...
- From: "WTH" <wth@xxxxxxxxxx>
- Date: Thu, 17 Jan 2008 13:13:33 -0500
"Jeroen Mostert" <jmostert@xxxxxxxxx> wrote in message news:478f8c75$0$85790$e4fe514c@xxxxxxxxxxxxxxxxx
WTH wrote: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.This is not a hack. This is the way things are supposed to work. It's the only way you could guarantee that the types are compatible, without requiring fully dynamic types from the runtime. However, you're programming against an interface and you don't need the actual type definition, so all is not lost. Read on.
"This is the way things are supposed to work" - That's very apologistic.
I'm sorry. Ha!
LOL :)
It's supposed to work that way because it does? No offense but types are already treated as if they were fully dynamic and assemblies contain entire type definitions including inheritance, ergo, it is EASY for the runtime to recursively evaluate the types.
Sure. It's also costly. If we go for consistency, those typing rules would need to apply to every single type, presumably down to the primitive types that you can't define.
It doesn't have to be by default. There's no reason you coulnd't have an attribute on a type that specified that the type in question should be eligible for this type of treatment.
We're talking a completely different approach to typing here. I find it
easy to see why the .NET designers went with the tried and true approach of just checking a unique identifier for each type (that is, full type name, including assembly version). More intricate type systems that fully accommodate "duck typing" are certainly possible, but TANSTAAFL.
I can understand that, but then why does reflection exist at all except to allow, when necessary, the slow and methodical evaluation of types for the purpose of understanding their usages and capabilities...? That's all I'm saying. There doesn't have to be a stop to using the UID that currently exists, again, I don't care if C# considers them different IF it allows one to be treated like another due to total compatability. Whether assuring total compatability or not is immaterial because it doesn't have to be the default course of action for the runtime.
This discussion is extremely old. What's the identity of a type? Is it its name, its structure, a combination of the two? Every language needs to pick. You disagree with the choice the designers made. Which is fine, but they didn't make the choices they did just to spite you. They went for "easy to understand" and "will never go wrong".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?)This isn't so ridiculous when you start to think what the runtime would have to do to ensure that what you want actually *works*. What if I define a completely different IPlugin in my assembly that occupies the same namespace? The runtime cannot just assume that everything is probably fine and then have the application crash on an incompatible object layout.
I don't care if the runtime thinks they're different, that's simply the progenitor of the problem, I care that the runtime won't let me cast two completely identical interfaces that only differ by assembly - they have the same methods, the same signatures, they take the same simple types - even if they used complex types the runtime could match the types, et cetera ad nauseum ad infinitum. Again, a user can write the C# code to do much the same thing, but the runtime can't? I think it should. Apparently in 3.5 there are changes to alleviate this shortcoming.
Again, I don't care if they are identified as different. I care that the runtime cannot recognize that they are totally compatible types, that they can be cast to one another or used identically. That's what I care about. Now, the compiler identifying them as the same, is not possible (for security reasons), so I'm not interested in them being considered the same definition, I'm interested in them being considered two different definitions of the exact same thing and therefore interchangeable.
Simplicity is in the eye of the beholder.This issue with types in assemblies (especially interfaces) always being incompatible seems to be a very big issue in regards to code re-usability.Well, it's not. The only issue here is that you always need to supply the bridging components in a shared assembly. Typically, that would be a GAC-installed assembly.
It certainly is. Software Engineering is a discipline of success through simplicity.
I find the rule that a type's identity is fully determined by the identity of the assembly it's contained in plus the type's name very simple.
I don't have a problem with that, I have a problem with the runtime not being able to recognize that I should be able to cast MyPluginAssembly.IPlugin to MyHostExe.IPlugin without throwing an exception.
That it happens to be a rule that, for your purposes, turns out to be *too* simple is another matter.
? The rule you wrote above is fine, it's the absence of something so simple as matching types that I find problematic.
You needn't fret much. .NET has very good support for COM and it almost completely handles all the awful COM stuff you have to swallow in "less refined" environments like C++ (or, God forbid, C).Anytime two assemblies plan to work together and reference the 'same type' they can't.You can get around this by using COM. Make IPlugin a COM interface and put it a type library. Although all developers will need that type library to develop against, you won't need to distribute it along with the executable.
Am I using the wrong approach (vanilla interfaces)?
Ugh... I do appreciate the alternative angle (seriously :)), that introduces new complexities (not for me as I've actually help implement the COM/DCOM subsystem on Irix [don't ask].) At least, that's my initial reaction. I'll think on it more. VERY much appreciate the suggestion though.
Hehe, does this send shivers down your spine? lpVtbl->
It's *nearly* transparent, apart from the need to hang a GUID on your interface and tag it as COM-visible. The QueryInterface stuff will all take place in the background.
I know what I'm talking about, since I've glued up managed and unmanaged code through COM and this is really easy (compared to having to marshal everything explicitly). In fact, I've done something very similar to IPlugin, except that I am using a separate interop assembly because I don't care about the extra deployment.
If I did care, I could have eliminated it by supplying the managed definition as a single source file and demanding that everyone copy that, but, guess what, we think just reusing the same assembly is *simpler*. :-)
It still has problems in a product suite environment, due to forced aggregation of the interfaces, but there may be ways around that.
That's because they have had to converge to make it work. As long as you don't get subtle with multiple inheritance, method pointers or exceptions, those compilers will all produce the same low-level binary stuff to make sure it'll work with the other compilers. This is also the foundation of COM. Any option that influences the way the compiler lays out vtables will break it, though. They work "just fine" because people before you suffered.What you want would work in C++, because C++ doesn't do runtime checks of any kind. Even then, it would only work if the compilers produced compatible object files. If not, then prepare for crashes.
? I'm not sure what you mean, as GCC, Intel, and Microsoft's compilers all produce compatible plugins for several products in our product suite. They work just fine.
Your argument doesn't make sense to me. You're trying to say its a bad approach because it has forced compiler writers to agree to calling conventions and function table layouts? No offense, but there are a myriad of other reasons why these things have occurred and why it is important that they produce compatible code and none of them have to do with plugins, primarily the compiler's ability to produce code that can be use in a DLL. Nothing to do with type safety.
More to the point, in C++ you've got no way of ensuring that it'll actually work. You're counting on the compilers to produce binary-compatible object files. If for any reason they don't, you won't get a ClassCastException but an access violation (or data corruption). The high priority the .NET designers put on avoiding this sort of thing was one impetus for a simple, easily verified type system.
Again, you're creating what, as far as I can tell, is a specious argument. I don't have to ensure it will work, I don't have to count on the compiler to produce binary compatible code (even though they have since the introduction of DLLs many many years ago - and somewhat before that relating to calling conventions and linkers.) The only difference between the C++ exception and the C# exception is that .NET defines the exception for me, doing it in C++ to handle this case is trivial, but I certainly don't have a problem telling plugin developers - "uh, please actually run your code once in order to see if it works."
Personally I think the .NET designers simply avoided the issue out of the idea that they had more important concerns to address first. I doubt it was a philosophical decision to make two items which are identical in memory incompatible just because the definitions of those types are contained in different places (leading to different fully qualified names), unlike the decision to avoid multiple inheritance (except that it is support for interfaces...)
WTH
.
- Follow-Ups:
- Re: C# Plugin system - same interface in two different assemblies...
- From: Jeroen Mostert
- Re: C# Plugin system - same interface in two different assemblies...
- References:
- C# Plugin system - same interface in two different assemblies...
- From: WTH
- Re: C# Plugin system - same interface in two different assemblies...
- From: Jeroen Mostert
- Re: C# Plugin system - same interface in two different assemblies...
- From: WTH
- Re: C# Plugin system - same interface in two different assemblies...
- From: Jeroen Mostert
- C# Plugin system - same interface in two different assemblies...
- Prev by Date: My silliest extention made yet 2008...
- Next by Date: Re: My silliest extention made yet 2008...
- Previous by thread: Re: C# Plugin system - same interface in two different assemblies...
- Next by thread: Re: C# Plugin system - same interface in two different assemblies...
- Index(es):
Relevant Pages
|