C# 反射:替换引用的程序集

发布于 2024-11-19 13:11:33 字数 1081 浏览 8 评论 0原文

我目前正在编写一个 MutationTesting 框架。代码几乎完成了,但是有一点(在花了半天时间之后)我无法弄清楚:

通过反射,我想执行类“TestClass”内的方法“TestMethod”。 “TestClass”所在的项目引用了一个集合,我们将其称为“Proband.dll”。

“TestMethod”在 Proband.dll 中创建某种类型的对象,并在该对象上执行方法。

为了澄清一点: TestClass - 是包含单元测试的类。 TestMethod - 是单个单元测试。 Proband.dll - 包含要测试的方法/类。

在执行TestMethod之前,我已经成功地反汇编、变异并重新组装了Proband.dll。所以现在我有一个新的“Proband.dll”,它将由 TestClass 代替!

问题是 TestClass 已经在执行中。我在想是否可以创建一个 AppDomain,在其中加载新的 Proband.dll,并在新的 AppDomain 内执行 TestMethod。

我已经创建了这个 AppDomain 并成功地将新的 Proband.dll 加载到其中,但是,我不知道如何在这个新的 AppDomain 中执行 TestMethod。另外我不知道这是否会“取代”旧的 Proband.dll 的测试方法。

这是我的测试类:

[TestClass()]
public class TestClass
{
    [TestInitialize()]
    public void MyTestInitialize()
    {
        // code to perform the mutation.
        // From here, the "TestMethod" should be called with 
        // the new "Proband.dll".
    }

    [TestMethod()]
    public void TestMethod()
    {
        // test code calling into Proband.dll
    }
}

有人知道如何实现这一点吗?或者有什么线索或者关键词吗?

谢谢, 基督教

I am currently writing a framework for MutationTesting. The code is almost complete, but there is a tiny bit which (after spending half a day on it) I cannot figure out:

via reflection I would like to execute a method "TestMethod" which is inside the class "TestClass". The project in which "TestClass" is, references an essembly, lets call it "Proband.dll".

The "TestMethod" creates an object of some type inside the Proband.dll and executes a method on that object.

In order to clarify a little:
TestClass - is a class that contains unit tests.
TestMethod - is a single unit test.
Proband.dll - contains the method/class to test.

Before executing the TestMethod, I already successfully disassembled, mutated and reassembled the Proband.dll. So now I have a new "Proband.dll" which shall be taken by the TestClass instead!

The problem is that the TestClass is already in the middle of execution. I was thinking whether it is possible to create an AppDomain in which the new Proband.dll will be loaded and inside the fresh AppDomain, the TestMethod will be executed.

I have already created this AppDomain and successfully loaded the new Proband.dll into it, however, I do not know how to execute the TestMethod inside this new AppDomain. Also I do not know whether this is going to "replace" the old Proband.dll for the test method.

Here is my TestClass:

[TestClass()]
public class TestClass
{
    [TestInitialize()]
    public void MyTestInitialize()
    {
        // code to perform the mutation.
        // From here, the "TestMethod" should be called with 
        // the new "Proband.dll".
    }

    [TestMethod()]
    public void TestMethod()
    {
        // test code calling into Proband.dll
    }
}

Does anyone have an idea of how this could be achieved? Or any clue or keyword?

Thanks,
Christian

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

‖放下 2024-11-26 13:11:33

这可能有点矫枉过正,但请查看我的答案:

AppDomain 中的静态字段

'需要在已加载 Proband.dll 的 AppDomain 中创建 TestClass,并使用MarshalByRef 将类保留在 AppDomain 中(以便稍后可以卸载它)。

以下是关于我所做的更多信息(不准确,因为我正在更改它以匹配您需要的更多内容)。

// Create Domain
_RemoteDomain = AppDomain.CreateDomain(_RemoteDomainName,
   AppDomain.CurrentDomain.Evidence, 
   AppDomain.CurrentDomain.BaseDirectory, 
   AppDomain.CurrentDomain.BaseDirectory, 
   true);

// Load an Assembly Loader in the domain (mine was Builder)
// This loads the Builder which is in the current domain into the remote domain
_Builder = (Builder)_RemoteDomain.CreateInstanceAndUnwrap(
    Assembly.GetExecutingAssembly().FullName, "<namespace>.Builder");

_Builder.Execute(pathToTestDll)


public class Builder : MarshalByRefObject 
{ 
    public void Execute(string pathToTestDll)
    {
        // I used this so the DLL could be deleted while
        // the domain was still using the version that
        // exists at this moment.
        Assembly newAssembly = Assembly.Load(
           System.IO.File.ReadAllBytes(pathToTestDll));

        Type testClass = newAssembly.GetType("<namespace>.TestClass", 
           false, true);

        if (testClass != null)
        {
           // Here is where you use reflection and/or an interface
           // to execute your method(s).
        }
    }
}

这应该为您提供所需的解决方案。

This is probably overkill, but check out my answer:

Static Fields in AppDomain

You'll want to create the TestClass in the AppDomain that you've loaded the Proband.dll in, and use a MarshalByRef to keep the class in the AppDomain (so you can unload it later).

Here is more about what I did (not exact, as i'm changing it to match more what you need).

// Create Domain
_RemoteDomain = AppDomain.CreateDomain(_RemoteDomainName,
   AppDomain.CurrentDomain.Evidence, 
   AppDomain.CurrentDomain.BaseDirectory, 
   AppDomain.CurrentDomain.BaseDirectory, 
   true);

// Load an Assembly Loader in the domain (mine was Builder)
// This loads the Builder which is in the current domain into the remote domain
_Builder = (Builder)_RemoteDomain.CreateInstanceAndUnwrap(
    Assembly.GetExecutingAssembly().FullName, "<namespace>.Builder");

_Builder.Execute(pathToTestDll)


public class Builder : MarshalByRefObject 
{ 
    public void Execute(string pathToTestDll)
    {
        // I used this so the DLL could be deleted while
        // the domain was still using the version that
        // exists at this moment.
        Assembly newAssembly = Assembly.Load(
           System.IO.File.ReadAllBytes(pathToTestDll));

        Type testClass = newAssembly.GetType("<namespace>.TestClass", 
           false, true);

        if (testClass != null)
        {
           // Here is where you use reflection and/or an interface
           // to execute your method(s).
        }
    }
}

This should provide you the solution you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文