【问题标题】:Check if .NET dynamic assembly is transient or persisted检查 .NET 动态程序集是暂时的还是持久的
【发布时间】:2014-06-18 12:15:04
【问题描述】:

当创建 System.Reflection.Emit.AssemblyBuilder 时,它可以是持久化的(使用 AssemblyBuilderAccess.Save 和类似的初始化)或瞬态的(AssemblyBuilderAccess.Run o 和类似的)。我将为作为输入的程序集生成器创建 ModuleBuilder。但是无法为临时组装创建持久化模块,因此我必须在创建模块之前检查组装状态。我怎样才能做到这一点? sn-p 是:

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);
    }
}

我可以通过使用反射访问其内部字段来获取程序集状态,所以这不是我要寻找的答案。

【问题讨论】:

  • 只是猜测,但是 assembly.CodeBase 给了你什么。 IIRC 它是磁盘上 exe 或 dll 文件的路径。如果没有坚持下去,可能会提供线索。
  • 为什么要与程序集分开创建模块?您几乎总是希望每个程序集中只有一个模块。
  • @simon at rcl:有趣的想法,但在这两种情况下我都会得到 NotSupportedException。
  • Assembly.Location 怎么样?抱歉,这就是我的意思;不知道为什么我想出了 CodeBase。如果这没有帮助,可能值得为您的基本 exe 文件检查 Codebase:如果这没有返回异常,那么也许您可以使用这个事实:Exception = not persisted?
  • @svick:因为 SRP。一方面,我有大量的程序集创建扩展(让它成为 N),可以扩展。另一方面 - 很多模块创建例程(M)。通过将 AssemblyBuilder 传递给这些例程,我可以混合不同的发射策略。如果我把它们放在一起,我会得到 N*M 复杂度而不是 N+M。

标签: c# .net reflection reflection.emit


【解决方案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)
            {
                    …
            }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-27
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多