Заменить существующее определение класса во время выполнения новым созданным типом - PullRequest
0 голосов
/ 08 июля 2019

Demorepo :

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

Как использовать :

  1. Оформить заказ
  2. Компилировать
  3. Удалить TestLib.dll и TestLib.pdb из консоли / bin / Debug
  4. Выполнить console.exe через cmd

Читать первым :

Я имею в виду кое-что, чего хочу достичь на работе, и я думаю, что это было бы лучшим решением.Поэтому, пожалуйста, не обсуждайте, могу ли я решить эту проблему другим способом.Если я хотел бы обсудить это, я создам новый SO-пост.

Учитывая :

Класс в библиотеке:

namespace Test.TestLib
{
    public class Class1
    {
    }
}

И второй класс, который создает его экземпляр:

namespace console
{
    public class AnotherClass
    {
        public void Create()
        {
            new Class1();
        }
    }
}

И консольное приложение, которое вызывает create:

    static void Main(string[] args)
    {
        //...
        new AnotherClass().Create();
    }

Пожалуйста, имейте в виду, что только Class1находится в дополнительной библиотеке.Два других класса находятся в том же.

Что я хочу сделать :

Заменить Тип Class1 во время выполнения:

        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();

Это работает.Если я использую Активатор: Activator.CreateInstance(modelType);, я получаю новый экземпляр этого типа.

Но :

Когда достигается строка с new Class1,генерируется исключение:

Unbehandelte Ausnahme: System.MethodAccessException: Fehler beim Versuch der Methode "console.AnotherClass.Create ()", auf Methode "Test.TestLib.Class1..ctor ()" zuzugreifen,bei console.AnotherClass.Create ()

Что-то вроде :

Необработанное исключение: System.MethodAccessException: при попытке доступа кметод "console.AnotherClass.Create ()" метод "Test.TestLib.Class1..ctor ()".at console.AnotherClass.Create ()

Вопрос :

Возможно ли это?

Sidenote : Theнеобходимо удалить файлы TestLib из папки / debug, так как в противном случае событие AsemblyResolve (полный пример см. в репо) не вызывается

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Конструктор вашего вновь созданного Типа не является общедоступным, поэтому MethodAccessAcception.

Вы можете создать открытый конструктор по умолчанию, используя следующий вызов для экземпляра TypeBuilder:

var modelTypeBuilder = dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class);
modelTypeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
var modelType = modelTypeBuilder.CreateType();

В противном случае вы можете использовать modelTypeBuilder.DefineConstructor(), чтобы установить больше возможных вариантов.

0 голосов
/ 08 июля 2019

добавьте TypeAttributes.Public к DefineType, оно будет успешно выполнено
Проверьте это: https://github.com/aIjundi/csharp-dynamic-replace-class

...