2011-09-08 45 views
4

我对c#和.NET颇为陌生,并试图创建一个动态加载程序集的asp.net web应用程序。c#.NET加载/卸载程序集,同时保持相同的会话

最初,我用Activator.CreateInstance动态加载程序集,但它似乎锁定程序集DLL文件。因为我经常改变大会,所以变得非常痛苦。我还需要与其他应用程序共享程序集,因此稍后可能会成为问题。

看来,大多数人建议创建一个单独的AppDomain并将程序集加载到它中,然后在完成后卸载AppDomain。但是,我的应用程序和程序集也依赖于会话上下文,一旦将它发送到应用程序域,所有会话都会丢失;程序集崩溃,因为它找不到会话上下文。

有没有办法将我的会话上下文传递给AppDomain?或者有没有什么办法可以加载程序集而不锁定DLL文件?我尝试按照某些建议的流式传输文件,但它仍然锁定DLL。

编辑:我试过下面的代码为达维德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); 
     } 

    } 
+0

看到我的编辑和更多的代码就快到了:) –

回答

4

加载组件在同一个AppDomain中,但不锁定文件后,负载只使用LoadFrom方法是这样的:

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

这样你完成和会话将可用。

调试器会出现问题,因为符号(* .pdb)不会被加载,所以没有断点也没有可用的调试,为了能够调试你应该真的在内存中加载.pdb文件,使用FileStream的例子。

编辑:你也可以用来加载符号而不锁定文件的方式是使用Assembly.Load的正确重载,一个用于装配,另一个用于装配'符号文件(.pdb文件):

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

实际上应先与流加载字节然后调用Assembly.Load并传递字节[]

编辑2:

这里是一个完整的示例,用于加载当前域中的程序集,包括符号文件并且不具有文件锁定。

是在网上找到了一个比较完整的例子,它反映了你需要包括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; 
    } 
+0

但卸载?我的意思是说,我对此感兴趣....这个怎么样,我们检查assmebly是否已经加载,如果没有,然后加载它。只要我们想要,我们可以轻松卸载。 – KMX

+0

Afaik至少在.net 2之前,没有办法一旦添加到应用程序域就卸载程序集。所以它只会在你卸载域时卸载。 –

+1

loadFile方法可以被File.ReadAllBytes()替换 – staafl