How to add folder to assembly search path at runtime in .NET?

前端 未结 8 2081
慢半拍i
慢半拍i 2020-11-22 07:08

My DLLs are loaded by a third-party application, which we can not customize. My assemblies have to be located in their own folder. I can not put them into GAC (my applicatio

相关标签:
8条回答
  • 2020-11-22 07:53

    The best explanation from MS itself:

    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);
    
    private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
    {
        //This handler is called only when the common language runtime tries to bind to the assembly and fails.
    
        //Retrieve the list of referenced assemblies in an array of AssemblyName.
        Assembly MyAssembly, objExecutingAssembly;
        string strTempAssmbPath = "";
    
        objExecutingAssembly = Assembly.GetExecutingAssembly();
        AssemblyName[] arrReferencedAssmbNames = objExecutingAssembly.GetReferencedAssemblies();
    
        //Loop through the array of referenced assembly names.
        foreach(AssemblyName strAssmbName in arrReferencedAssmbNames)
        {
            //Check for the assembly names that have raised the "AssemblyResolve" event.
            if(strAssmbName.FullName.Substring(0, strAssmbName.FullName.IndexOf(",")) == args.Name.Substring(0, args.Name.IndexOf(",")))
            {
                //Build the path of the assembly from where it has to be loaded.                
                strTempAssmbPath = "C:\\Myassemblies\\" + args.Name.Substring(0,args.Name.IndexOf(","))+".dll";
                break;
            }
    
        }
    
        //Load the assembly from the specified path.                    
        MyAssembly = Assembly.LoadFrom(strTempAssmbPath);                   
    
        //Return the loaded assembly.
        return MyAssembly;          
    }
    
    0 讨论(0)
  • 2020-11-22 07:54

    Update for Framework 4

    Since Framework 4 raise the AssemblyResolve event also for resources actually this handler works better. It's based on the concept that localizations are in app subdirectories (one for localization with the name of the culture i.e. C:\MyApp\it for Italian) Inside there are resources file. The handler works also if the localization is country-region i.e. it-IT or pt-BR. In this case the handler "might be called multiple times: once for each culture in the fallback chain" [from MSDN]. This means that if we return null for "it-IT" resource file the framework raises the event asking for "it".

    Event hook

            AppDomain currentDomain = AppDomain.CurrentDomain;
            currentDomain.AssemblyResolve += new ResolveEventHandler(currentDomain_AssemblyResolve);
    

    Event handler

        Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            //This handler is called only when the common language runtime tries to bind to the assembly and fails.
    
            Assembly executingAssembly = Assembly.GetExecutingAssembly();
    
            string applicationDirectory = Path.GetDirectoryName(executingAssembly.Location);
    
            string[] fields = args.Name.Split(',');
            string assemblyName = fields[0];
            string assemblyCulture;
            if (fields.Length < 2)
                assemblyCulture = null;
            else
                assemblyCulture = fields[2].Substring(fields[2].IndexOf('=') + 1);
    
    
            string assemblyFileName = assemblyName + ".dll";
            string assemblyPath;
    
            if (assemblyName.EndsWith(".resources"))
            {
                // Specific resources are located in app subdirectories
                string resourceDirectory = Path.Combine(applicationDirectory, assemblyCulture);
    
                assemblyPath = Path.Combine(resourceDirectory, assemblyFileName);
            }
            else
            {
                assemblyPath = Path.Combine(applicationDirectory, assemblyFileName);
            }
    
    
    
            if (File.Exists(assemblyPath))
            {
                //Load the assembly from the specified path.                    
                Assembly loadingAssembly = Assembly.LoadFrom(assemblyPath);
    
                //Return the loaded assembly.
                return loadingAssembly;
            }
            else
            {
                return null;
            }
    
        }
    
    0 讨论(0)
提交回复
热议问题