来自另一个 appdomain 的 CreateInstance 在控制台应用程序上工作,但在单元测试时抛出 MissingMethodException

Posted

技术标签:

【中文标题】来自另一个 appdomain 的 CreateInstance 在控制台应用程序上工作,但在单元测试时抛出 MissingMethodException【英文标题】:CreateInstance from another appdomain works on console application but throws MissingMethodException when unit testing 【发布时间】:2015-12-11 14:00:42 【问题描述】:

这是我能做的最好的得到最小、完整和可验证的例子(你可以复制/粘贴来测试):

考虑这两个类:

public class WorkerParam : MarshalByRefObject

    private readonly string s;

    public WorkerParam(string s)
    
        this.s = s;
    


public class Worker : MarshalByRefObject

    public WorkerParam T  get; 

    public Worker(WorkerParam t)
    
        this.T = t;
    

从控制台应用程序(4.5.2,AnyCPU)运行时效果很好:

class Program

    public static void Main()
    
        Worker localWorker = new Worker(new WorkerParam("some string"));

        AppDomain ad = AppDomain.CreateDomain("New domain");

        Worker remoteWorker = (Worker)ad.CreateInstanceFromAndUnwrap(
            typeof(Worker).Assembly.Location,
            typeof(Worker).FullName,
            true,
            BindingFlags.Instance | BindingFlags.Public, null, new object[]  new WorkerParam("string") ,
            CultureInfo.CurrentCulture, null);

        Console.ReadLine();
    

在单元测试(4.5.2,AnyCPU)时同样的内容抛出MissingMethodException

[TestClass]
public class UnitTest1

    [TestMethod]
    public void TestMethod1()
    
        Worker localWorker = new Worker(new WorkerParam("some string"));

        AppDomain ad = AppDomain.CreateDomain("New domain");

        // below line will throw MissingMethodException
        Worker remoteWorker = (Worker)ad.CreateInstanceFromAndUnwrap(
            typeof(Worker).Assembly.Location,
            typeof(Worker).FullName,
            true,
            BindingFlags.Instance | BindingFlags.Public, null, new object[]  new WorkerParam("string") ,
            CultureInfo.CurrentCulture, null);
    

问题是:CreateInstanceFromAndUnwrap 从单元测试(Visual Studio 单元)运行时会抛出 MissingMethodException,但在控制台应用程序上运行完美。

重要:当我从构造函数中删除参数 WorkerParam 时,它可以正常工作。

【问题讨论】:

这是一个 DLL Hell 问题,您可能正在使用包含 Worker 和 WorkerParam 类型的程序集的旧副本运行单元测试。还没有带有 WorkerParam 参数的构造函数的旧版本。 我已经清理并重建了解决方案,但它并没有解决问题。还是我需要做点别的? 如果您不知道 DLL 的来源,请使用 Fuslogvw.exe 并记录所有绑定。 我将 Worker 和 WorkerParam 类放在与 UnitTest1 相同的文件中,我删除了对旧 dll 的引用。它仍然无法正常工作。 【参考方案1】:

您需要声明程序集的位置,因为您使用的不仅仅是 Worker 类型:

        AppDomainSetup domaininfo = new AppDomainSetup();
        domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
        AppDomain ad = AppDomain.CreateDomain("New Domain", null, domaininfo);


        Worker remoteWorker = (Worker)ad.CreateInstanceFromAndUnwrap(
            typeof(Worker).Assembly.Location,
            typeof(Worker).FullName,
            true,
            BindingFlags.Instance | BindingFlags.Public,
            null,
            new object[]  new WorkerParam("string") ,
            CultureInfo.CurrentCulture, null);

【讨论】:

以上是关于来自另一个 appdomain 的 CreateInstance 在控制台应用程序上工作,但在单元测试时抛出 MissingMethodException的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个 appDomain 调用类的方法

用于将 POCO 实例公开给其他 AppDomain 的通用容器 - 它是如何工作的?

如何在另一个 AppDomain 中调用方法

防止代码被加载到另一个 AppDomain

是否可以从另一个单独的 .NET AppDomain 更改 .NET AppDomain 中的字符串属性的值

当我加载的另一个 AppDomain 引发未处理的异常时,我可以隔离我当前的 AppDomain 以防被拆除吗?