Thi*_*uda 8 .net c# remoting appdomain marshalbyrefobject
我一直在尝试使用以下代码(所有内容都在同一个程序集中定义):
namespace SomeApp{
public class A : MarshalByRefObject
{
public byte[] GetSomeData() { // }
}
public class B : MarshalByRefObject
{
private A remoteObj;
public void SetA(A remoteObj)
{
this.remoteObj = remoteObj;
}
}
public class C
{
A someA = new A();
public void Init()
{
AppDomain domain = AppDomain.CreateDomain("ChildDomain");
string currentAssemblyPath = Assembly.GetExecutingAssembly().Location;
B remoteB = domain.domain.CreateInstanceFromAndUnwrap(currentAssemblyPath,"SomeApp.B") as B;
remoteB.SetA(someA); // this throws an ArgumentException "Object type cannot be converted to target type."
}
}
}
Run Code Online (Sandbox Code Playgroud)
我要做的是将第一个AppDomain中创建的"A"实例的引用传递给子域,并让子域在第一个域上执行方法.在'B'代码的某些方面,我将调用'remoteObj.GetSomeData()'.必须这样做,因为'GetSomeData'方法中的'byte []'必须在第一个appdomain上"计算".我应该怎么做以避免异常,或者我可以做些什么来达到相同的结果?
Rus*_*ure 11
实际根本原因是您的dll从两个不同的应用程序域中的不同位置加载.这会导致.NET认为它们是不同的程序集,这当然意味着类型不同(即使它们具有相同的类名,命名空间等).
Jeff在单元测试框架中运行时测试失败的原因是单元测试框架通常会创建AppDomains,并将ShadowCopy设置为"true".但是您手动创建的AppDomain默认为ShadowCopy ="false".这将导致dll从不同的位置加载,这导致很好的"对象类型无法转换为目标类型".错误.
更新:经过进一步测试后,它似乎确实归结为两个AppDomain之间的ApplicationBase不同.如果匹配,则上述方案有效.如果它们不同则不会(尽管我已经确认使用windbg将dll从同一目录加载到两个AppDomain中)另外,如果我在两个AppDomain中打开ShadowCopy ="true",那么它会失败使用不同的消息:"System.InvalidCastException:Object必须实现IConvertible".
更新2:进一步阅读让我相信它与负载上下文有关.当您使用其中一个"From"方法(Assembly.LoadFrom或appDomain.CreateInstanceFromAndUnwrap)时,如果在其中一个正常加载路径(ApplicationBase或其中一个探测路径)中找到该程序集,那么它是否已加载到默认值中加载上下文.如果在那里找不到程序集,则将其加载到Load-From上下文中.因此,当两个AppDomain都具有匹配的ApplicationBase时,即使我们使用"From"方法,它们也会加载到各自的AppDomain的默认加载上下文中.但是当ApplicationBase不同时,一个AppDomain将在其默认加载上下文中具有程序集,而另一个AppDomain在其Load-From Context中具有程序集.
我可以重复这个问题,它似乎与 TestDriven.net 和/或 xUnit.net 有关。如果我运行 C.Init() 作为测试方法,我会收到相同的错误消息。但是,如果我从控制台应用程序运行 C.Init(),则不会出现异常。
您是否看到同样的事情,从单元测试运行 C.Init() ?
编辑:我还可以使用 NUnit 和 TestDriven.net 复制该问题。我还可以使用 NUnit 运行程序而不是 TestDriven.net 来复制错误。所以问题似乎与通过测试框架运行此代码有关,尽管我不确定为什么。