ali*_*hoo 3 .net c# load appdomain assembly-loading
我试图找到一种在运行时编译程序集并加载它们的方法.基本意图是将它们存储在不在光盘上的数据库中.所以我写了一些代码,但看到了一个有趣的情况.这是我的代码:
//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();
}
}
Run Code Online (Sandbox Code Playgroud)
代码运行完美,删除行被注释掉,如果我取消注释它,应用程序域加载程序集,AssemblyLoadEvent()方法运行,我在控制台上看到一个数字9,但是当方法结束时apd.Load()抛出一个错误:"无法加载档案或集会." 这是完全合理的.
问题是:如何AssemblyLoadEvent()在没有光盘上的汇编文件的情况下运行方法?
如果该方法以某种方式在原始二进制数据的帮助下运行,那么appdomain是否有Load()成功完成该方法的方法?
它将程序集正常加载到"newdomain"中并调用仍在newdomain中的事件处理程序(如果在事件处理程序中打印当前域,则可以验证这一点).最后,它创建了要传回的返回值.您忽略示例代码中的返回值,但仍然创建它.在跨域编组期间发生异常,因为反序列化也希望将程序集加载到默认域中.
这是来自mono的异常调用堆栈:
at System.AppDomain.Load (System.String assemblyString, System.Security.Policy.Evidence assemblySecurity, Boolean refonly) [0x00000] in <filename unknown>:0
at System.AppDomain.Load (System.String assemblyString) [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) System.AppDomain:Load (string)
at System.Reflection.Assembly.Load (System.String assemblyString) [0x00000] in <filename unknown>:0
at System.UnitySerializationHolder.GetRealObject (StreamingContext context) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.ObjectRecord.LoadData (System.Runtime.Serialization.ObjectManager manager, ISurrogateSelector selector, StreamingContext context) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.ObjectManager.DoFixups () [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000] in <filename unknown>:0
at System.Runtime.Remoting.RemotingServices.DeserializeCallData (System.Byte[] array) [0x00000] in <filename unknown>:0
at (wrapper xdomain-invoke) System.AppDomain:Load (byte[])
at (wrapper remoting-invoke-with-check) System.AppDomain:Load (byte[])
at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0
Run Code Online (Sandbox Code Playgroud)
编辑:这是来自MSDN的确认:
尝试在不是当前应用程序域的目标应用程序域上调用Load将导致在目标应用程序域中成功加载程序集.由于装配体不MarshalByRefObject的,当这种方法尝试对加载的程序集回到大会的当前应用程序域,公共语言运行时会尝试将程序集加载到当前应用程序域和负载可能会失败.如果两个应用程序域的路径设置不同,则加载到当前应用程序域的程序集可能与首先加载的程序集不同.