You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否存在兼容反射的元数据读取器?适配.NET Framework 4.8

获取.NET Framework 4.8程序集声明式安全属性的优化方案

1. 用原生兼容的元数据读取类直接操作DeclSecurity表

.NET Framework 4.8可以借助NuGet包System.Reflection.Metadata和System.Reflection.PortableExecutable直接解析元数据,不用依赖第三方工具,还能和现有反射对象无缝结合:

  • 先加载目标程序集,遍历其模块;
  • 通过PEReader读取PE文件,获取MetadataReader来访问DeclSecurity表;
  • 解析表中每条记录的目标(类型、方法、字段等)和权限集Blob,再转成可识别的PermissionSet对象。

示例代码:

using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Security.Permissions;
using System.Text;

// 加载目标程序集
var targetAssembly = Assembly.LoadFrom("YourAssembly.dll");
foreach (var module in targetAssembly.Modules)
{
    // 读取模块的PE流
    using var stream = module.Assembly.GetManifestResourceStream(module.Name);
    using var peReader = new PEReader(stream);
    if (!peReader.HasMetadata) continue;
    
    var reader = peReader.GetMetadataReader();
    // 遍历DeclSecurity元数据表
    foreach (var handle in reader.DeclarativeSecurityAttributes)
    {
        var decSec = reader.GetDeclarativeSecurityAttribute(handle);
        // 获取属性关联的目标(类型、方法等)
        var targetHandle = decSec.Parent;
        var targetName = GetTargetDisplayName(reader, targetHandle);
        
        // 解析权限集Blob
        var blob = reader.GetBlobBytes(decSec.PermissionSet);
        var permissionSet = PermissionSet.FromXml(Encoding.UTF8.GetString(blob));
        
        Console.WriteLine($"目标: {targetName}, 权限内容: {permissionSet}");
    }
}

// 辅助方法:根据元数据句柄获取目标的显示名称
string GetTargetDisplayName(MetadataReader reader, EntityHandle handle)
{
    return handle.Kind switch
    {
        HandleKind.TypeDefinition => reader.GetTypeDefinition((TypeDefinitionHandle)handle).Name.ToString(),
        HandleKind.MethodDefinition => 
        {
            var method = reader.GetMethodDefinition((MethodDefinitionHandle)handle);
            var declaringType = reader.GetTypeDefinition(method.GetDeclaringType());
            return $"{declaringType.Name}.{method.Name}";
        },
        HandleKind.FieldDefinition =>
        {
            var field = reader.GetFieldDefinition((FieldDefinitionHandle)handle);
            var declaringType = reader.GetTypeDefinition(field.GetDeclaringType());
            return $"{declaringType.Name}.{field.Name}";
        },
        _ => handle.Kind.ToString()
    };
}

2. 简化dnlib与反射的结合

如果想用dnlib,不用完全切换到它的类体系,通过元数据令牌就能关联dnlib对象和反射对象:

  • dnlib里的类型、方法等都有MDToken属性,反射对象的MetadataToken和这个值完全对应;
  • 用dnlib读取DeclSecurity表,拿到元数据令牌后,直接用反射解析对应的成员。

示例代码:

using dnlib.DotNet;
using System.Reflection;

// 加载程序集(dnlib和反射各加载一次)
var dnlibModule = ModuleDefMD.Load("YourAssembly.dll");
var reflectionAssembly = Assembly.LoadFrom("YourAssembly.dll");

foreach (var decSec in dnlibModule.DeclarativeSecurityAttributes)
{
    // 通过元数据令牌关联反射成员
    var mdToken = decSec.Parent.MDToken.Raw;
    var reflectionMember = reflectionAssembly.GetType().Module.ResolveMember((int)mdToken);
    
    // 直接获取dnlib解析好的权限集
    var permissionSet = decSec.PermissionSet;
    Console.WriteLine($"关联反射成员: {reflectionMember?.Name}, 权限集: {permissionSet}");
}

3. 优化现有反射遍历方案

如果不想直接操作元数据表,也可以优化当前的反射逻辑,提升效率:

  • 直接用GetCustomAttributes的重载指定CodeAccessSecurityAttribute类型,避免遍历所有自定义属性再判断类型;
  • 分层次获取程序集、类型、成员级别的属性,逻辑更清晰。

示例代码:

using System.Reflection;
using System.Security.Permissions;

var targetAssembly = Assembly.LoadFrom("YourAssembly.dll");

// 程序集级安全属性
foreach (CodeAccessSecurityAttribute attr in targetAssembly.GetCustomAttributes(typeof(CodeAccessSecurityAttribute), true))
{
    Console.WriteLine($"程序集属性: {attr.GetType().Name}");
}

// 类型级安全属性
foreach (var type in targetAssembly.GetTypes())
{
    foreach (CodeAccessSecurityAttribute attr in type.GetCustomAttributes(typeof(CodeAccessSecurityAttribute), true))
    {
        Console.WriteLine($"类型 {type.Name} 属性: {attr.GetType().Name}");
    }
    
    // 成员级安全属性
    foreach (var member in type.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
    {
        foreach (CodeAccessSecurityAttribute attr in member.GetCustomAttributes(typeof(CodeAccessSecurityAttribute), true))
        {
            Console.WriteLine($"成员 {type.Name}.{member.Name} 属性: {attr.GetType().Name}");
        }
    }
}

内容的提问来源于stack exchange,提问作者Сергей Гущин

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:30:58