简短的回答是,不,没有办法按照你的要求去做。
更长的答案是:有一种特殊的程序集加载方法,Assembly.ReflectionOnlyLoad()
它使用“仅反射”加载上下文。这使您可以加载无法执行但可以读取其元数据的程序集。
在您的情况下(显然,在我自己想出的每个用例中)它并没有那么有帮助。您不能从这种程序集中获取类型化属性,只有CustomAttributeData
. 该类没有提供任何过滤特定属性的好方法(我能想到的最好的方法是将其转换为字符串并使用StartsWith("[System.Diagnostics.Debuggable");
更糟糕的是,仅反射加载不会加载任何依赖程序集,但它会迫使您手动进行。这在客观上比你现在所做的更糟糕;至少现在您可以自动加载依赖项。
(另外,我之前的回答提到了 MEF;我错了,MEF 似乎包含大量自定义反射代码来完成这项工作。)
最终,一旦程序集被加载,您就无法卸载它。您需要卸载整个应用程序域,如此 MSDN 文章中所述。
更新:
如评论中所述,我能够通过仅反射加载(和正常加载)获得所需的属性信息,但缺少类型化的属性元数据使其非常痛苦。
如果加载到正常的程序集上下文中,您可以很容易地获得所需的信息:
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 属性为 false,在 2.0 版本中没有任何意义。