Replace existing class definition at runtime with newly created type

China☆狼群 提交于 2019-12-13 02:56:14

问题


Demorepo:

https://github.com/gabbersepp/csharp-dynamic-replace-class

How to use:

  1. Checkout
  2. Compile
  3. Delete TestLib.dll & TestLib.pdb from console/bin/Debug
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!