#c# #.net #reflection #reflection.emit
#c# #.net #отражение #reflection.emit
Вопрос:
Когда система.Reflection.Emit.AssemblyBuilder создан, его можно сохранить (инициализировать с помощью AssemblyBuilderAccess .Сохранить и тому подобное) или переходный (AssemblyBuilderAccess.Запустите o и аналогичные). Я собираюсь создать ModuleBuilder для assembly builder, который у меня есть в качестве входных данных. Но постоянный модуль не может быть создан для переходной сборки, поэтому я должен проверить статус сборки перед созданием модуля. Как я могу это сделать? Фрагмент является:
public ModuleBuilder Handle(AssemblyBuilder assembly, string name)
{
if (assembly.IsPersisted) // IsPersisted is a kind of property I'm looking for
{
return assembly.DefineDynamicModule(name, name ".dll");
}
else
{
return assembly.DefineDynamicModule(name);
}
}
Я могу получить статус сборки, получив доступ к ее внутренним полям с помощью отражения, так что это не тот ответ, который я ищу.
Комментарии:
1. Просто предположение, но что делает сборка. Кодовая база дает вам. IIRC это путь к файлу exe или dll на диске. Если она не сохраняется, это может дать подсказку.
2. Почему вы создаете модули отдельно от сборок? Вы почти всегда хотите иметь ровно один модуль в каждой сборке.
3. @simon в rcl: интересная идея, но в обоих случаях я получаю исключение NotSupportedException.
4. Как насчет сборки. Местоположение? Извиняюсь, это было свойство, которое я имел в виду; не уверен, почему я придумал CodeBase. Если это не поможет, возможно, стоит проверить кодовую базу для вашего базового exe-файла: если это не возвращает исключение, то, возможно, вы могли бы использовать этот факт: Exception = not persisted?
5. @svick: из-за SRP. С одной стороны, у меня есть множество расширений для создания сборок (пусть это будет N), которые можно расширить. С другой стороны — множество процедур создания модулей (M). Передавая AssemblyBuilder этим подпрограммам, я могу смешивать различные стратегии эмиссии. Если я соберу их вместе, я получу сложность N * M вместо N M.
Ответ №1:
Только что столкнулся с этой точной ситуацией — единственный реальный способ справиться с этим, не передавая переменную состояния, указывающую, должна ли сборка быть постоянной, это:
try
{
return assembly.DefineDynamicModule(name, name ".dll");
}
catch(NotSupportedException)
{
return assembly.DefineDynamicModule(name);
}
Не очень — но реальной альтернативы нет.
Ответ №2:
Вы можете сделать это с помощью отражения, но вы должны обернуть свою конкретную реализацию для обработки угрожающих исключений, поскольку это зависит от внутренней реализации, так что нет гарантии на постоянство API.
if (assembly.IsDynamic)
{
Type assemblyType = assembly.GetType();
Type assemblyBuilderDataType = Assembly.GetAssembly(assemblyType)
.GetType("System.Reflection.Emit.AssemblyBuilderData");
object assemblyBuilderData = assemblyType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Single(fi => fi.FieldType == assemblyBuilderDataType)
.GetValue(assembly);
object assemblyBuilderAccess = assemblyBuilderDataType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Single(fi => fi.FieldType == typeof(AssemblyBuilderAccess))
.GetValue(assemblyBuilderData);
switch (assemblyBuilderAccess)
{
…
}
}