Ответ 1
Короткий ответ: нет, нет способа сделать то, что вы просите.
Более длинный ответ таков: существует специальный метод загрузки сборок, Assembly.ReflectionOnlyLoad()
, который использует контекст нагрузки только для отражения, Это позволяет загружать сборки, которые не могут быть выполнены, но может считывать их метаданные.
В вашем случае (и, по-видимому, в каждом случае, я мог бы придумать), это не очень полезно. Вы не можете получить типизированные атрибуты из этого типа сборки, только CustomAttributeData
. Этот класс не обеспечивает хороший способ фильтрации для определенного атрибута (лучшее, что я мог придумать, это передать его в строку и использовать StartsWith("[System.Diagnostics.Debuggable");
Хуже того, только нагрузка с отражением не загружает сборки зависимостей, но это заставляет вас делать это вручную. Это делает его объективно хуже, чем то, что вы делаете сейчас; по крайней мере теперь вы автоматически загружаете загрузку зависимостей.
(Кроме того, в моем предыдущем ответе была сделана ссылка на MEF, я ошибался, похоже, что MEF включает целую тонну кода пользовательского отражения, чтобы сделать эту работу.)
В конечном счете вы не можете выгрузить сборку после ее загрузки. Вам необходимо выгрузить весь домен приложения, как описано в этой статье MSDN.
UPDATE:
Как отмечалось в комментариях, я смог получить необходимую информацию об атрибутах через нагрузку только на отражение (и нормальную нагрузку), но отсутствие типизированных метаданных атрибутов создает серьезную боль.
Если вы загружаетесь в обычный контекст сборки, вы можете легко получить необходимую информацию:
var d = a.GetCustomAttributes(typeof(DebuggableAttribute), false) as DebuggableAttribute;
var tracking = d.IsJITTrackingEnabled;
var optimized = !d.IsJITOptimizerDisabled;
Если вы загружаетесь в контекст только для отражения, вы можете выполнить некоторую работу; вам нужно выяснить форму, которую принял конструктор атрибутов, узнать, какие значения по умолчанию, и объединить эту информацию, чтобы получить окончательные значения каждого свойства. Вы получаете необходимую информацию:
var d2 = a.GetCustomAttributesData()
.SingleOrDefault(x => x.ToString()
.StartsWith("[System.Diagnostics.DebuggableAttribute"));
Оттуда вам нужно проверить ConstructorArguments
, чтобы увидеть, какой конструктор был вызван: этот с одним аргументом или этот с двумя аргументами. Затем вы можете использовать значения соответствующих параметров, чтобы выяснить, какие значения будут иметь два свойства, которые вы заинтересовали:
if (d2.ConstructorArguments.Count == 1)
{
var mode = d2.ConstructorArguments[0].Value as DebuggableAttribute.DebuggingModes;
// Parse the modes enumeration and figure out the values.
}
else
{
var tracking = (bool)d2.ConstructorArguments[0].Value;
var optimized = !((bool)d2.ConstructorArguments[1].Value);
}
Наконец, вам нужно проверить NamedArguments
, который может переопределить те, которые установлены в конструкторе, используя, например:
var arg = NamedArguments.SingleOrDefault(x => x.MemberInfo.Name.Equals("IsJITOptimizerDisabled"));
var optimized = (arg == null || !((bool)arg.TypedValue.Value));
В последнем замечании, если вы используете это под .NET 2.0 или выше и еще не видели, MSDN указывает это на DebuggingModes
:
В .NET Framework версии 2.0 информация отслеживания JIT всегда создается, и этот флаг имеет тот же эффект, что и Default, за исключением того, что свойство IsJITTrackingEnabled является ложным, что не имеет смысла в версии 2.0.