How can I get a type from an assembly that is load

2019-04-25 11:54发布

I use the following code:

Assembly.LoadFile("the assembly in another folder");
var type = Type.GetType("the full name of the type");

Even though the assembly was already loaded before this line of code, it always returns null in type.

PS: I did pass in the assembly qualified name, including namespace, type name, assembly name, version and public token.

4条回答
Summer. ? 凉城
2楼-- · 2019-04-25 12:33

Type.GetType only searches the types in the calling assembly and the types in mscorlib.dll unless you pass the assembly qualified name of the type. See here.

EDIT

It appears that Type.GetType is only able to retrieve Type instances from assemblies in the Load context. Assemblies loaded using LoadFile are in no context and those loaded using LoadFrom are in the Load From context; neither of these contexts allow you to use Type.GetType so the resolution will fail. This article shows that Type information can be retrieved for an Assembly when the directory it is in is added as a probing privatePath since it will then end up in the Load context but will fail in other contexts.

查看更多
Fickle 薄情
3楼-- · 2019-04-25 12:36

The simplest way of doing it is to simply trap the return value of Assembly.LoadFile in a variable and call GetType on it like this:

Assembly assem = Assembly.LoadFile("assemblyLocation");
assem.GetType("typeName");

You may want to consider keeping a reference to this assembly if you will want to pull types from it often, or do what others have suggested and make a more generic method that loops through all loaded assemblies.

查看更多
做自己的国王
4楼-- · 2019-04-25 12:37

The "proper" (MS recommended) way to do this, when you must use Type.GetType(string) on types in assemblies that are not in the load context but in the load-from or no-context context, is to bind to the Appdomain.AssemblyResolve event. The following code is relatively efficient:

// this resolver works as long as the assembly is already loaded
// with LoadFile/LoadFrom or Load(string) / Load(byte[])
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies()
              where a.GetName().FullName == args.Name
              select a).FirstOrDefault();

    if(asm == null)
         throw FileNotFoundException(args.Name);     // this becomes inner exc

    return asm;
}

// place this somewhere in the beginning of your app:
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;

It appears slightly more efficient to create a combination of the AssemblyLoad/Resolve events to keep a dictionary of the loaded assemblies (use the assembly-name as key).

On Assembly.LoadFile
There are some serious drawback on using this method. According to MSDN:

LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does.

So, if possible, do not use LoadFile. The resulting assembly is loaded in the no-context context, which has even more drawbacks than the load-from context. Instead, use Assembly.LoadFrom and dependencies will be automatically loaded from the load path.

查看更多
迷人小祖宗
5楼-- · 2019-04-25 12:41

you can try this....

Assembly.GetAssembly assumes you have an instance of the type, and Type.GetType assumes you have the fully qualified type name which includes assembly name.

you can give path that assembly is located .....

If you only have the base type name, you need to do something more like this:

public static String GetAssemblyNameContainingType(String typeName) 
{
    foreach (Assembly currentassembly in AppDomain.CurrentDomain.GetAssemblies()) 
    {
        Type t = currentassembly.GetType(typeName, false, true);
        if (t != null) {return currentassembly.FullName;}
    }

    return "not found";
}

This also assumes your type is declared in the root. You would need to provide the namespace or enclosing types in the name, or iterate in the same manner.

查看更多
登录 后发表回答