Assembly compatibility verification.

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

Recommended Posts

I am currently attempting to make a project modular using the managed extension framework, however it allows third party mods where the plugin might not be designed for the current project version.

Backwards compatibility fixes a lot of this, however I need a way to tell if there is some of the plugins are incompatible, and then remove that plugin before attempting to import the needed data.

This also can't be done one on one, as if one plugin requires another, and together they would work, but testing independently shows them as missing a link.

So, I currently need a way to verify if a set of assemblies can work properly, and prune out any that are incompatible.

Edited by Earthmark

Share on other sites

if you change your interface from one version to the other, the plugins that use the old interface won't load. at least they shouldn't.

if you're really that worried, you can always create an attribute that describes for what version of your project the plugin is made, and exige that each plugin uses that attribute on the assembly, then on load you check if that version is still compatible.

you can use the same approach for plugins that require another, but they really should use MEF features to do that...

anyway, it seens that 2 simple attributes can solve your problem, they don't even need code, you can just check if they are present.

Share on other sites

The issue is if you do an update that does not change the interface then the plugin will be rejected for a different version number. Currently with MEF when you try to import information it will throw an exception if one of the assemblies are not compatible (aka some interface changed), so I am trying to find out how it is doing that check and do it manually.

Otherwise that would mean you would need to keep an attribute for every interface version, and that seems like a large overhead to throw onto plugin makers and hard to keep updated to start with.

Also as I understand it, one could try each plugin one at a time as assemblies can't do circular references (at least visual studio yells when you try).

Share on other sites

have you tried the update that does not change the interface? because MEF shouldn't refuse to load based on this...

unless...

is your interface defined on the same assembly that uses it? i would advise to move it to a different assembly, an API. this way, you only update that assembly when you do make a update that changes the interface.

as for the attribute method, you can use it as follows:

 [CompatibleWith(Version=1.0)]
public class Component : IComponent
{
...
}


then in your project, you can store with is the earlyest version that is still compatible and use that version to check.

you can combine the 2 methods (the API assembly and the attribute) to load only parts of a plugin that are compatible with your current version.

you also can write you custom "MEF" to do the loading, then you can apply more filters and advanced options on the loading stage, you basically just search for assemblies and use reflection to load them, if you do choose this path, i can help you.

sadly i'm at work, otherwise i could upload a sample...

anyway, keep me informed in your progress and i'll help the most i can, this is a subject that i really like

Share on other sites

As it stands MEF only has issues if an interface (or reference of any kind) changed and was used in the plugin, if you change a system that is unrelated but inside the main assembly it has no issues (Yay for versioning). However for this reason some plugins will be compatible as long as the api sections that the plugin uses don't change.

So just saying it is compatible with a specific version would not work entirely when it could also work with future versions depending on if there are api changes to specific systems.

If this was to be implemented for every possible interface though, you would be checking every possible link, meaning in large plugins there could be hundreds of these attributes, and the assembly size would increase dramatically. As well as it would become a nightmare for plugin makers to keep track of the version numbers for every reference.

Also I am not sure about this, but I was under the impression linking had to occur before you could traverse the assembly, so it would crash before this point from a missing reference or mismatched reference.

Share on other sites

As it stands MEF only has issues if an interface (or reference of any kind) changed and was used in the plugin, if you change a system that is unrelated but inside the main assembly it has no issues (Yay for versioning). However for this reason some plugins will be compatible as long as the api sections that the plugin uses don't change.

So just saying it is compatible with a specific version would not work entirely when it could also work with future versions depending on if there are api changes to specific systems.

i see, i think i was misunderstanding you, you are worried that a new version of your project may change behavior that the plugin expects, without changing something that the plugin direct uses...

i don't think there's any automated way you can use to ensure that unless you force a recompile of the plugin for each new version (assuming each recompile comes with tests...)

i think that the only way to ensure that everything works just right is to update the plugin every time the main application updates, there's not much more to do...

Share on other sites

The each method should have the same behavior as defined in the documentation, so that changing over versions should not be an issue.

The issue is currently if any assembly loaded from mef does not link properly (a reference changed) the whole things thrown an exception and denies loading. I just want to check if the assemblies work (as in linking was successful) and if it was not successful then remove the problematic assemblies and try again.

Edited by Earthmark

Share on other sites

Not really, the issue is not the importer itself it is that an exception is being thrown as the dll is linked, before the objects are imported.

Example of the exception

System.Reflection.ReflectionTypeLoadException was unhandled
HResult=-2146232830
Message=Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

[LoaderExceptions information, specific names removed and replaced with <t>]
{System.TypeLoadException: Could not load type '<class name>' from assembly '<Assembly name>, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.}



The issue also only happens when the CompositionContainer attempts to import data.

Edited by Earthmark

Share on other sites

I think I found a way around it, seems like getting all of the types inside an assembly will force checking.

Current code, wish it didn't involve exceptions:

var dlls = new List<Assembly>(dllNames.Select(Assembly.LoadFile));

foreach (var assem in dlls)
{
try
{
assem.GetTypes();
}
{
dlls.Remove(assem);
}
}


1. 1
2. 2
Rutin
19
3. 3
4. 4
5. 5

• 14
• 30
• 13
• 11
• 11
• Forum Statistics

• Total Topics
631781
• Total Posts
3002316
×