简体   繁体   English

c#.NET加载/卸载程序集,同时保持相同的会话

[英]c# .NET Loading/Unloading assembly while keeping the same session

I am rather new to c# and .NET, and trying to create an asp.net web application that dynamically loads assembly. 我是c#和.NET的新手,并试图创建一个动态加载程序集的asp.net Web应用程序。

Initially, I've used Activator.CreateInstance to dynamically load assemblies, but it seems to lock the assembly DLL file. 最初,我使用Activator.CreateInstance动态加载程序集,但它似乎锁定程序集DLL文件。 Because I am making frequent changes to the assembly it's become quite a pain. 因为我经常对装配进行更改,所以变得非常痛苦。 I also need to share the assembly with other apps, so it may become a problem later. 我还需要与其他应用程序共享程序集,因此以后可能会成为一个问题。

It appears that most people recommend creating a separate AppDomain and loading the assembly into it, then unload the appdomain after I'm done. 似乎大多数人建议创建一个单独的AppDomain并将程序集加载到其中,然后在我完成后卸载appdomain。 However, my app and the assembly also depends on session context and all the session is lost once I send it over to the app domain; 但是,我的应用程序和程序集也依赖于会话上下文,一旦我将其发送到应用程序域,所有会话都将丢失; the assembly crashes because it cannot find session context. 程序集崩溃,因为它无法找到会话上下文。

Is there any way to pass on my session context to the AppDomain? 有没有办法将我的会话上下文传递给AppDomain? Or is there any way for me to load the assembly without locking the DLL file? 或者有没有办法加载程序集而不锁定DLL文件? I've tried streaming the file as some suggested, but it still locks the DLL. 我已尝试按照一些建议流式传输文件,但它仍然锁定了DLL。

Edit: I've tried the following code as Davide Piras suggested, but the DLL file is still locked 编辑:我已经尝试了以下代码,如Davide Piras所建议,但DLL文件仍然被锁定

    private static T CreateInstance<T>(string fileName, string typeName)
    {
        if (!File.Exists(fileName)) throw new FileNotFoundException(string.Format("Cannot find assembly '{0}'.", fileName));

        try
        {
            Assembly assembly = Assembly.LoadFrom(fileName);
            if (assembly != null)
            {
                List<Type> assemblyTypes = assembly.GetTypes().ToList();

                Type assemblyType =
                    assemblyTypes.FirstOrDefault(asmType => typeof(T).IsAssignableFrom(asmType));
                T instance = (T) Activator.CreateInstance(assemblyType);

                if (instance != null) return instance;

            }
            // Trouble if the above doesn't work!
            throw new NullReferenceException(string.Format("Could not create type '{0}'.", typeName));
        }
        catch (Exception exp1)
        {
            throw new Exception("Cannot create instance from " + fileName + ", with type " + typeName + ": " + exp1.Message + exp1.Source, exp1.InnerException);
        }

    }

to load the assemblies in the same AppDomain but not lock the files after load just use the LoadFrom method in this way: 要在同一个AppDomain中加载程序集但在加载后不锁定文件,只需使用LoadFrom方法:

Assembly asm = Assembly.LoadFrom( “mydll.dll” );

in this way you are done and Session will be available. 通过这种方式,您将完成并且会话将可用。

there will be an issue with the debugger because symbols (*.pdb) will not get loaded so no breakpoint and no debugging available, to be able to debug you should really load the .pdb files in memory as well, for example using FileStream. 调试器会出现问题,因为符号(* .pdb)不会被加载,所以没有断点和调试可用,为了能够调试你应该真正加载内存中的.pdb文件,例如使用FileStream。

Edit: The way you can do to also load symbols and not lock the files is to use proper overload of Assembly.Load, the one that gets two byte[] one for the assembly and the other for the assembly' symbols file (.pdb file): 编辑:你可以做的方法是加载符号而不是锁定文件是使用Assembly.Load的正确重载,一个获得两个字节[]一个用于程序集,另一个用于程序集'符号文件(.pdb)文件):

public static Assembly Load(
    byte[] rawAssembly,
    byte[] rawSymbolStore
)

in fact you should first load the bytes with a stream then call Assembly.Load and pass the byte[] 实际上你应该先用流加载字节,然后调用Assembly.Load并传递byte []

EDIT 2: 编辑2:

here a full example to load the assemblies in your current domain, including the symbol file and not having the files locks. 这里是一个完整的示例,用于加载当前域中的程序集,包括符号文件和没有文件锁定。

it's a full example found online, it reflect everything you need including the handling of AppDomain.AssemblyResolve... 它是在线发现的完整示例,它反映了您需要的一切,包括AppDomain.AssemblyResolve的处理......

public static void Main() {
      AppDomain currentDomain = AppDomain.CurrentDomain;

      currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolver);
   }

   static void InstantiateMyType(AppDomain domain) {
      try {
     // You must supply a valid fully qualified assembly name here.
         domain.CreateInstance("Assembly text name, Version, Culture, PublicKeyToken", "MyType");
      } catch (Exception e) {
         Console.WriteLine(e.Message);
      }
   }

   // Loads the content of a file to a byte array. 
   static byte[] loadFile(string filename) {
      FileStream fs = new FileStream(filename, FileMode.Open);
      byte[] buffer = new byte[(int) fs.Length];
      fs.Read(buffer, 0, buffer.Length);
      fs.Close();

      return buffer;
   }   

   static Assembly MyResolver(object sender, ResolveEventArgs args) {
      AppDomain domain = (AppDomain) sender;

      // Once the files are generated, this call is
      // actually no longer necessary.
      EmitAssembly(domain);

      byte[] rawAssembly = loadFile("temp.dll");
      byte[] rawSymbolStore = loadFile("temp.pdb");
      Assembly assembly = domain.Load(rawAssembly, rawSymbolStore);

      return assembly;
   }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM