Loading Dependent Assemblies Manually

左心房为你撑大大i 提交于 2019-11-29 14:57:45

As it turns out, the key to making this work is to ensure you use Assembly.LoadFile. LoadFile is the only method that will load an assembly even if it matches an assembly that .NET thinks is already loaded. I discovered this from an article on codeproject.

Since I needed to load two different assemblies that both had identical full names (i.e. "App.Test.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") but had different contents, LoadFile was the only way to accomplish this. My initial attempts used the Load overload that accepted the type AssemblyName, but it would ignore the path defined in the AssemblyName instance and instead return the already loaded type.

To force an entire dependency graph to load from a specific location regardless of what other types are already loaded is to register for the AssemblyResolve event:

AppDomain.CurrentDomain.AssemblyResolve += ResolveDependentAssembly;

And ensure that we use LoadFile to load the dependency:

private Assembly ResolveDependentAssembly(object sender, ResolveEventArgs args)
{
    var requestingAssemblyLocation = args.RequestingAssembly.Location;

    if (thePathMatchesSomeRuleSoIKnowThisIsWhatIWantToIntercept)
    {
        var assemblyName = new AssemblyName(args.Name);
        string targetPath = Path.Combine(Path.GetDirectoryName(requestingAssemblyLocation), string.Format("{0}.dll", assemblyName.Name));
        assemblyName.CodeBase = targetPath; //This alone won't force the assembly to load from here!

        //We have to use LoadFile here, otherwise we won't load a differing
        //version, regardless of the codebase because only LoadFile
        //will actually load a *new* assembly if it's at a different path
        //See: http://msdn.microsoft.com/en-us/library/b61s44e8(v=vs.110).aspx
        return Assembly.LoadFile(assemblyName.CodeBase);
    }

    return null;
}

Yes, this code assumes that if your root assembly has dependencies, that they're all located at the same path. That's a limitation, no doubt, but you could fairly easily add additional hints for non-local dependencies. This also would only be an issue if the already loaded version of those additional dependencies wouldn't work.

Lastly, none of this would be necessary if the assembly versions were properly incremented. The Load call would not treat an already loaded Depv1 as the same as a request Depv2. In my case, that wasn't something I was willing to deal with as part of my continuous integration and deployment process.

Try Assembly.LoadFrom(path); which will resolve dependencies automatically.

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