Demorepo :
https://github.com/gabbersepp/csharp-dynamic-replace-class
Как использовать :
- Оформить заказ
- Компилировать
- Удалить TestLib.dll и TestLib.pdb из консоли / bin / Debug
- Выполнить console.exe через cmd
Старый пост SO:
Заменить существующее определение класса во время выполнения на вновь созданный тип
Задано :
Класс вlib:
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
находится в дополнительной библиотеке.Два других класса находятся в одном и том же.
Что я хочу сделать :
Заменить сборку во время выполнения:
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");
Но яхочу не указывать тип на данный момент.Вместо этого я использую:
AppDomain.CurrentDomain.TypeResolve += CurrentDomain_TypeResolve;
private static Assembly CurrentDomain_TypeResolve(object sender, ResolveEventArgs args)
{
Console.WriteLine("resolve type");
if (args.Name.Contains("TestLib"))
{
dynamicModule.DefineType("Test.TestLib.Class1", TypeAttributes.Class | TypeAttributes.Public).CreateType();
return dynamicAssembly;
}
return null;
}
Проблема :
Событие не вызывается при выполнении строки new AnotherClass().Create();
.Вместо этого выдается исключение:
System.TypeLoadException: Der Тип "Test.TestLib.Class1" в сборке "TestLib, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = null" konnte nichtgeladen werden
что-то вроде:
System.TypeLoadException: тип "Test.TestLib.Class1" в сборке "TestLib, версия = 1.0.0.0, Culture =нейтральный, PublicKeyToken = null "не может быть загружен
Пожалуйста, посмотрите репозиторий для полного примера.
// Edit: Демонстрационный проектнаписано с VS2019 für .net461.Я думаю, что основные понятия одинаковы для ядра dotnet.Дайте мне знать, если вы предпочитаете работать с ядром dotnet, чтобы я мог предоставить проект для обеих платформ.
// Edit2:
Я отладил в коде ILи увидел, что все работает нормально, пока не будет вызван конструктор Class1
: Так что лично я не думаю, что обработчик событий подключен слишком поздно, как заявлено Бруно.
Официальная документация гласит, что это событие вызывается, если сборка неизвестна:
https://docs.microsoft.com/de-de/dotnet/api/system.appdomain.typeresolve?view=netframework-4.8 Событие TypeResolve наступает, когда общеязыковая среда выполнения не может определить сборку, котораяможно создать запрошенный тип
Я раньше этого не читал.Надеюсь, кто-нибудь может мне помочь: -)
// Edit3 - возможное решение :
Обходным путем может быть создание типов на основе списка имен классов.Чтобы не потерять безопасность компиляции, я могу использовать nameof
, который не производит код IL.Пример можно найти в репо в ветке resolveType-solution1
.Но, конечно, не решение, которое я ищу: - (