Loading a generic type using Assembly.LoadFrom

情到浓时终转凉″ 提交于 2020-01-03 17:06:57

问题


Referring to the answer by Jon Skeet here: Pass An Instantiated System.Type as a Type Parameter for a Generic Class

I need to load a Generic type based on the name of the generic type, and the name of the type that is the type parameter for the generic. So from Jon's example I would have:

string genName = "MyNamespace.Generic";
string itemName = "System.String";

I have the following code that will load a type based on the name of the type and a fully justified assembly name/path. It works fine for "simple types"

public Type GetTypeOf(string assemblyPath, string className)
{
    var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath); //open assembly
    return asmbly.GetType(className, true, true); //throws error, not case sensitive
}

I was hoping to use this as follows:

//Get the types
var genTyp = GetTypeOf(genPath,genName);
var itemTyp = GetTypeOf(itemPath,itemName);

//Put them together:
var typ = getType.MakeGenericType(itemTyp);

This falls over on the first line with a System.TypeLoadException stating:

Could not load type <TypeName here> from assembly <AssemblyName here>

I've tried a number of permutations of creating the generic, included supplying the full class name MyNamespace.Generic<System.String>. It works correctly when I specify a non-generic type to load from the same assembly that contains the generic type.


回答1:


Unfortunately, using GetType with generic types is not that readable. You have to use the full qualified type name, even for the generic parameters:. For example, TestType<object> reads like this:

TestType`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

Your sample code does not include the type declarations, so you have to play around with this. You can try this code snippet and take a look what the debugger says:

string typeName = typeof(MyNamespace.Generic<>).Name;
string fullTypeName = typeof(MyNamespace.Generic<>).FullName;

The results should help you getting the correct type name.




回答2:


Based on Carsten's answer above, I've adapted my GetTypeOf method as follows:

    public Type GetGenericTypeOf(string assemblyPath, string genericClass, string itemQualifiedClass)
    {
        string typString = String.Format("{0}`1[[{1}]]",genericClass,itemQualifiedClass)
        var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath); //open assembly
        return asmbly.GetType(typString, true, true); //throws error, not case sensitive
    }

I can then use it as follows:

var itemTyp = GetTypeOf(itemPath,itemName);
var genTyp = GetGenericTypeOf(genPath,genName,itemTyp.AssemblyQualifiedName);

//This genTyp is then good to go:
var genInst = Activator.CreateInstance(getTyp);

There's no need for MakeGenericType as the genType returned bypasses this step.

I've now done a full write up of this, including VB.Net version of the code on my blog here.



来源:https://stackoverflow.com/questions/12036247/loading-a-generic-type-using-assembly-loadfrom

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!