我试图找到一种在运行时编译程序集并加载它们的方法。基本目的是将它们存储在数据库而不是光盘上。所以我写了一些代码,但是看到了一个有趣的情况。这是我的代码:
//SumLib
namespace SumLib
{
public class SumClass
{
public static int Sum(int a, int b)
{
return a + b;
}
}
}
// Console app
class Program
{
public static void AssemblyLoadEvent(object sender, AssemblyLoadEventArgs args)
{
object[] tt = { 3, 6 };
Type typ = args.LoadedAssembly.GetType("SumLib.SumClass");
MethodInfo minfo = typ.GetMethod("Sum");
int x = (int)minfo.Invoke(null, tt);
Console.WriteLine(x);
}
static void Main(string[] args)
{
AppDomain apd = AppDomain.CreateDomain("newdomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
apd.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyLoadEvent);
FileStream fs = new FileStream("Sumlib.dll", FileMode.Open);
byte[] asbyte = new byte[fs.Length];
fs.Read(asbyte, 0, asbyte.Length);
fs.Close();
fs.Dispose();
// File.Delete("Sumlib.dll");
apd.Load(asbyte);
Console.ReadLine();
}
}
代码完美运行,删除行被注释掉,如果我取消注释,应用程序域将加载程序集,
AssemblyLoadEvent()
方法运行,我在控制台上看到数字9,但是当方法结束时,apd.Load()
抛出错误:“无法加载文件或程序集。”这是完全合理的。问题是:
AssemblyLoadEvent()
方法如何在光盘上没有汇编文件的情况下运行?如果该方法以某种方式在原始二进制数据的帮助下运行,那么appdomain是否可以成功完成
Load()
方法的任何方式? 最佳答案
因此,您尝试从byte []加载程序集并调用方法。我不建议您这样做(使用AssemblyLoad事件),因为它将为每个依赖项调用。
@Jester关于使用父域中的Load()加载程序集是正确的。为了解决这个问题,我建议使用如下包装类:
// Console app
class Program
{
public class AssemblyLoader : MarshalByRefObject
{
public void LoadAndCall(byte[] binary)
{
Assembly loadedAssembly = AppDomain.CurrentDomain.Load(binary);
object[] tt = { 3, 6 };
Type typ = loadedAssembly.GetType("SumLib.SumClass");
MethodInfo minfo = typ.GetMethod("Sum", BindingFlags.Static | BindingFlags.Public);
int x = (int)minfo.Invoke(null, tt);
Console.WriteLine(x);
}
}
static void Main()
{
AppDomain apd = AppDomain.CreateDomain("newdomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
FileStream fs = new FileStream("Sumlib.dll", FileMode.Open);
byte[] asbyte = new byte[fs.Length];
fs.Read(asbyte, 0, asbyte.Length);
fs.Close();
fs.Dispose();
File.Delete("Sumlib.dll");
AssemblyLoader loader = (AssemblyLoader)apd.CreateInstanceAndUnwrap(typeof(AssemblyLoader).Assembly.FullName, typeof(AssemblyLoader).FullName);
loader.LoadAndCall(asbyte);
Console.ReadLine();
}
}