草庐IT

c# - 在不加载到当前 AppDomain 的情况下获取自定义程序集属性

coder 2024-05-24 原文

我创建了一个小应用程序,用于在提供的目录中递归加载程序集并读取它们的自定义属性集合。主要是为了读取 DebuggableAttribute 以确定 IsJITTrackingEnabled 和 IsJITOptimizerDisabled 的设置以确定程序集是否针对发布进行了优化。

我当前的代码执行 Assembly.LoadFrom 以将整个路径传递到程序集并加载它。然后对程序集执行 GetCustomAttributes 以获取可调试属性。问题是每个程序集都被加载到当前的应用程序域中。因此,如果另一个文件夹使用相同的程序集,它只使用最初加载的引用。我希望能够加载程序集,读取我需要的属性,然后卸载它。我尝试创建一个新的应用程序域并将程序集加载到其中,然后卸载程序集后记无济于事。

我知道这一定是可能的,但我不知所措。任何帮助将不胜感激。我也很乐意提供您可能需要的任何其他信息。

最佳答案

简短的回答是,不,没有办法完成您的要求。

较长的答案是这样的:有一种特殊的程序集加载方法,Assembly.ReflectionOnlyLoad() ,它使用“仅反射”加载上下文。这使您可以加载无法执行但可以读取其元数据的程序集。

在您的情况下(显然,在每个用例中我都可以自己想出)它并没有那么有用。您无法从此类程序集中获取类型化属性,只能获取 CustomAttributeData。该类没有提供任何过滤特定属性的好方法(我能想到的最好方法是将其转换为字符串并使用 StartsWith("[System.Diagnostics.Debuggable");

更糟糕的是,仅反射加载不会加载任何依赖程序集,但它会强制您手动执行。这使得它客观上比你现在做的更糟糕;至少现在你可以自动加载依赖项。

(此外,我之前的回答提到了 MEF;我错了,MEF 似乎包含大量自定义反射代码来完成这项工作。)

最终,程序集一旦加载就无法卸载。您需要卸载整个应用程序域,如this MSDN article. 中所述

更新:

如评论中所述,我能够通过仅反射加载(和正常加载)获得您需要的属性信息,但缺少类型化属性元数据使其非常痛苦。

如果加载到普通的程序集上下文中,您可以很容易地获得所需的信息:

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 以查看调用了哪个构造函数:this one使用一个参数或 this one有两个参数。然后,您可以使用适当参数的值来计算您感兴趣的两个属性的值:

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 中指出了这一点文档:

In the .NET Framework version 2.0, JIT tracking information is always generated, and this flag has the same effect as Default with the exception of the IsJITTrackingEnabled property being false, which has no meaning in version 2.0.

关于c# - 在不加载到当前 AppDomain 的情况下获取自定义程序集属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10439668/

有关c# - 在不加载到当前 AppDomain 的情况下获取自定义程序集属性的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby - 默认情况下使选项为 false - 2

    这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  6. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  7. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  8. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  9. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  10. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

随机推荐