Loading Dependent Assemblies Manually

后端 未结 2 1357
野的像风
野的像风 2020-12-19 17:11

I have a project that loads multiple versions of the same assembly using either Assembly.Load or Assembly.LoadFile. I then use Assembly.CreateInstance to create a type from

相关标签:
2条回答
  • 2020-12-19 18:07

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

    0 讨论(0)
  • 2020-12-19 18:12

    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.

    0 讨论(0)
提交回复
热议问题