问题
Demorepo:
https://github.com/gabbersepp/csharp-dynamic-replace-class
How to use:
- Checkout
- Compile
- Delete TestLib.dll & TestLib.pdb from console/bin/Debug
- Execute console.exe through cmd
Read first:
I have something in mind I want to achieve at work and I think that this would be the best solution. So please do not discuss if I can solve this with another way. If I would like to discuss about this, I will create a new SO post.
Given:
A class in a lib:
namespace Test.TestLib
{
public class Class1
{
}
}
And a second class which creates an instance of it:
namespace console
{
public class AnotherClass
{
public void Create()
{
new Class1();
}
}
}
And a console app that calls create
:
static void Main(string[] args)
{
//...
new AnotherClass().Create();
}
Please keep in mind that only Class1
is in an extra lib. The other two classes are in the same.
What I want to do:
Replace the Type Class1
at runtime:
AssemblyName dynamicAssemblyName = new AssemblyName("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
dynamicAssembly =
AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
var dynamicModule = dynamicAssembly.DefineDynamicModule("TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
var modelType = dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class).CreateType();
This works. If i am using the Activator: Activator.CreateInstance(modelType);
I get a new instance of this type.
But:
When the line with new Class1
is reached, an exception is thrown:
Unbehandelte Ausnahme: System.MethodAccessException: Fehler beim Versuch der Methode "console.AnotherClass.Create()", auf Methode "Test.TestLib.Class1..ctor()" zuzugreifen. bei console.AnotherClass.Create()
Something like:
Unhandled exception: System.MethodAccessException: An error occurred while trying to access the method "console.AnotherClass.Create ()" method "Test.TestLib.Class1..ctor ()". at console.AnotherClass.Create ()
Question:
Is this possible?
Sidenote:
The deletion of the TestLib files from the /debug folder is required because otherwise the AsemblyResolve
Event (please see the repo for a full example) is not raised
回答1:
add TypeAttributes.Public
to DefineType, it will execute successfully
Check this: https://github.com/aIjundi/csharp-dynamic-replace-class
回答2:
The constructor of your newly created Type is not public, hence the MethodAccessAcception
.
You can create a public default constructor using the following call on the TypeBuilder
instance:
var modelTypeBuilder = dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class);
modelTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var modelType = modelTypeBuilder.CreateType();
Otherwise you could use modelTypeBuilder.DefineConstructor()
to set more possible options.
来源:https://stackoverflow.com/questions/56939542/replace-existing-class-definition-at-runtime-with-newly-created-type