我对c#和.NET很陌生,并试图创建一个动态加载程序集的asp.net Web应用程序。
最初,我使用Activator.CreateInstance
动态加载程序集,但它似乎锁定了程序集DLL文件。因为我经常对装配进行更改,所以变得非常痛苦。我还需要与其他应用程序共享程序集,因此以后可能会成为一个问题。
似乎大多数人都建议创建一个单独的AppDomain并将程序集加载到其中,然后在我完成后卸载appdomain。但是,我的应用程序和程序集也依赖于会话上下文,一旦我将其发送到应用程序域,所有会话都将丢失;程序集崩溃,因为它无法找到会话上下文。
有没有办法将我的会话上下文传递给AppDomain?或者有没有办法加载程序集而不锁定DLL文件?我已尝试按照一些建议流式传输文件,但它仍然锁定了DLL。
编辑:我尝试过以下代码,如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);
}
}
答案 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并传递byte []
编辑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;
}