Type.GetType returns null when using MEF
Asked Answered
V

3

3

I'm currently using MEF for a project to import plugins, as the plugins are written in WPF they each have a view and a viewmodel. The plugins know about the viewmodel but the main shell UI will construct the view and bind the viewmodel using a convention over configuration type pattern.

I have used some code from the Build-your-own-MVVM-framework sample to do the auto view discovery:

    [ImportMany(typeof(IPlugin))]
    public IEnumerable<IPlugin> Plugins { get; set; }

   var viewTypeName = this.Plugins.First().ViewModel.GetType().AssemblyQualifiedName.Replace("Model", string.Empty);
   var viewType = Type.GetType(viewTypeName,true);

The code at the moment just gets the first plugin and takes out Model from the name, returns the view name and gets the view type so that I can construct it. So an example of what viewType would be is:

PluginTest.TestView, PluginTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

However when I call Type.GetType(viewType) I get back null, if I add the true to throw an exception I get the exception:

Could not load file or assembly 'PluginTest, Version=1.0.0.0, Culture=neutral, 
PublicKeyToken=null' or one of its dependencies. 
The system cannot find the file specified.

Even though it is already loaded using MEF.

If I do:

var types = Assembly.GetAssembly(this.Plugins.First().ViewModel.GetType()).GetTypes();

I get back a list of all the types in the assembly of the plugin, so far there is just PluginTest.TestView and PluginTest.TestViewModel

Can anyone help me with this one?

EDIT: Sorry didn't mention before, the plugins are in different assemblies to my main shell app.

Vishnu answered 29/6, 2010 at 5:49 Comment(0)
S
4

It's probably easiest to do something like this:

var modelType = this.Plugins.First().ViewModel.GetType();
var viewTypeName = modelType.FullName.Replace("Model", string.Empty);
var viewType = modelType.Assembly.GetType(viewTypeName);

I'm not sure why Type.GetType isn't working for you - assembly resolution is a tricky beast - but if you know the assembly the type should be defined in anyway, I'd definitely go via Assembly.GetType instead.

Selfsustaining answered 29/6, 2010 at 5:54 Comment(4)
@Nathan: So what is viewTypeName when you try the above code?Selfsustaining
ahh no sorry, it works :) Did you always have modelType.FullName there I swear it was modelType.Name which is why my code didn't work. Thanks.Vishnu
@Nathan: I had Name very briefly - but I edited it within about 30 seconds of posting that...Selfsustaining
and I was just to quick on the ctl+c, never mind it's working perfectly now.Vishnu
B
1

The assembly was probably loaded in the Load-From context, and Type.GetType() doesn't work with assemblies loaded in that context. MEF tries to load assemblies in the default context, but if that doesn't work it loads them in the Load-From context.

More about assembly load contexts in .NET

Baggywrinkle answered 29/6, 2010 at 16:55 Comment(0)
A
0

This question has long been answered, but just in case someone stumbles upon this, here is my solution.

As the other answers have noted, the problem is that though the assembly has been loaded through MEF, it gets loaded again once you use GetType(). Unfortunately, I had no control over the code calling GetType(), so Jon Skeet's solution wouldn't work in my case.

In my case, the problem could be solved by adding the location of the plugin assembly to the probing path of the application.

An alternative solution (which is what I eventually did) is to implement the AssemblyResolve event, and to load the assembly manually. This solution is very flexible, contrary to the probing path solution it also works if you don't know the installation directory of the plugin in advance.

Also: if your plugin has any dependent assemblies, you have to use one of these two solutions, for otherwise you get a FileNotFound exception on your first use of these dependencies.

Arcograph answered 28/7, 2015 at 13:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.