C# 如何在运行时从不同的AppDomain访问Fody/Costura嵌入式库

C# 如何在运行时从不同的AppDomain访问Fody/Costura嵌入式库,c#,dll,appdomain,fody-costura,C#,Dll,Appdomain,Fody Costura,我需要为我的解决方案创建一个新的AppDomain,以便可以从它自己的AppDomain调用该方法。我的解决方案的所有依赖.dll文件都已使用Fody/Costura嵌入到my.exe中。我创建了一个Loader:MarshalByRefObject类来调用我的方法,但是当我在运行时执行加载程序时,我得到一个异常: 无法加载文件或程序集“my.assembly,Version=19.1.7242.23931,Culture=neutral,PublicKeyToken=null”或其依赖项之一。

我需要为我的解决方案创建一个新的AppDomain,以便可以从它自己的AppDomain调用该方法。我的解决方案的所有依赖.dll文件都已使用Fody/Costura嵌入到my.exe中。我创建了一个
Loader:MarshalByRefObject
类来调用我的方法,但是当我在运行时执行加载程序时,我得到一个异常:

无法加载文件或程序集“my.assembly,Version=19.1.7242.23931,Culture=neutral,PublicKeyToken=null”或其依赖项之一。系统找不到指定的文件

代码正在查找我的AppDomain.CurrentDomain.BaseDirectory中的.dll文件,以通过加载程序执行我的方法,但它们不在那里,而是嵌入在可执行文件中。有没有办法让我的新AppDomain知道嵌入到可执行文件中的程序集,而不必从BaseDirectory加载它们

我已经找到了将其他程序集加载到新AppDomain的方法,但还没有找到这样做的方法。我还怀疑可能有Fody/Costura API可以实现这一点,但还没有发现任何适用于此场景的东西

内部类装入器:MarshallByRefObject
{
对象CallInternal(字符串dll、字符串类型名、字符串方法、对象[]参数)
{
程序集a=程序集.LoadFile(dll);
类型t=a.GetType(类型名);
MethodInfo m=t.GetMethod(方法);
Console.WriteLine(“调用”+m.Name);
返回m.Invoke(null,参数);
}
公共静态对象调用(字符串dll、字符串typename、字符串方法、params对象[]参数)
{
对象结果=空;
尝试
{
AppDomain newAppDomain=AppDomain.CreateDomain(“myNewDomain”,AppDomain.CurrentDomain.Evidence,AppDomain.CurrentDomain.SetupInformation);
Loader ld=(Loader)newAppDomain.CreateInstanceAndUnwrap(Assembly.getExecutionGassembly().FullName,typeof(Loader.FullName);//未找到DLL文件从此处引发异常
结果=(装入器)ld.CallInternal(dll、类型名、方法、参数);
卸载(newAppDomain);
}
捕获(异常ee)
{
Console.WriteLine(“异常消息[“+ee.Message+”]);
PDL.报告(ee);
}
返回结果;
}
}

我希望我的Loader类在运行时不需要从磁盘加载.dll而被实例化。Fody/Costura embedded.dll是否可以实现这一点?

我将我的.dll添加到我的Visual Studio项目中,并将构建操作设置为嵌入式资源

我正在运行以下代码以将程序集放入我的新AppDomain:

string resName = null;
foreach (string resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
   Console.WriteLine("Assembly.GetExecutingAssembly().GetManifestResourceNames() [" + resourceName + "] ");
   if (resourceName.Contains("my.Assembly"))
   {
      resName = resourceName;
      Console.WriteLine("CurrentDomain Assembly my.Assembly [" +  "] Resource name [" + resName + "]");
    }

}
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resName);
if (s != null)
{
    byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);
    Assembly a = Assembly.Load(data);
    newAppDomain.Load(data);

     foreach (Assembly cdAssem in newAppDomain.GetAssemblies())
     {
        Console.WriteLine("newAppDomain Assembly 2 [" + cdAssem.GetName().FullName + "]");
      }
}

我可以看到程序集是我的新AppDomain的一部分:

string resName = null;
foreach (string resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames())
{
   Console.WriteLine("Assembly.GetExecutingAssembly().GetManifestResourceNames() [" + resourceName + "] ");
   if (resourceName.Contains("my.Assembly"))
   {
      resName = resourceName;
      Console.WriteLine("CurrentDomain Assembly my.Assembly [" +  "] Resource name [" + resName + "]");
    }

}
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resName);
if (s != null)
{
    byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);
    Assembly a = Assembly.Load(data);
    newAppDomain.Load(data);

     foreach (Assembly cdAssem in newAppDomain.GetAssemblies())
     {
        Console.WriteLine("newAppDomain Assembly 2 [" + cdAssem.GetName().FullName + "]");
      }
}

newAppDomain程序集2[mscorlib,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089]

newAppDomain程序集2 my.Assembly版本=19.1.7243.19014,区域性=中性,PublicKeyToken=null]


但是使用CreateInstanceAndUnwrap()仍然失败,因为它无法找到my.Assembly.dll。我想知道将程序集加载到AppDomain的唯一方法是否是从基本目录加载它?

您正在加载的dll是否使用其他dll?那些DLL在基本目录中吗?Net可执行文件在与可执行文件相同的文件夹(而不是基本文件夹)中查找其他dll。要确保加载的是可执行文件的最新版本,请始终使用“添加其他dll”菜单:添加现有项,然后浏览到编译可执行文件的位置。然后使用解决方案资源管理器打开引用文件夹,右键单击现有项和复选框以复制到可执行文件夹。是的,包含我尝试调用的方法的类需要3.dll文件。这3个程序集已加载到当前AppDomain中,但在我的新AppDomain中不可用。因此,当我在新AppDomain中使用CreateInstanceAndUnwrap()时,它会抛出FileNotFound异常。我猜因为它在我的新AppDomain中没有找到程序集,所以它会在基本文件夹中查找它。CreateInstanceAndUnwrap()。如果我将这些.dll放在基本文件夹中,代码会正常工作,因为它正在那里查找.dll,但它无法实现嵌入.dll的目的,因为我将提供一个包含这些.dll的更大可执行文件(在当前AppDomain中)但是还必须将这三个.dll分别安装到基本目录中,以便.exe可以在运行时找到它们。我宁愿找到一种方法,在运行时将程序集从原始AppDomain添加到我的新AppDomain,而不必从磁盘加载程序集,这样我就可以只传递一个.exe文件。Fody/Costura有办法做到吗?不确定。是否每次启动应用程序时都要下载?您所要求的似乎是“在运行时将程序集从原始AppDomain添加到我的新AppDomain”和“我只能传递一个.exe文件”之间的冲突。在.exe中有当前AppDomain。我在同一个.exe中创建了第二个AppDomain。因为它是一个新的AppDomain,所以它没有原始AppDomain所具有的任何程序集。为了使用反射来调用我的方法,我需要新AppDomain中的一些依赖程序集。试图弄清楚如何在不必从硬盘加载.dll的情况下加载它们。所有这些都发生在同一个.exe中。当将另一个项目添加到当前项目中时,有多种方法可供选择。1) 复制第二个项目中的所有可执行文件,或在第一个项目中引用第二个项目的路径。您经常使用相对路径,如.././secondProj/bin/debug/abc.exe。请您解释一下您的答案,如您将此代码放在了哪里。它在里面吗<