C# Reflection: Replace a referenced assembly
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 开发者_C百科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
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.
精彩评论