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

Fody跨程序集属性复制异常:如何实现不同程序集间属性复制

跨程序集复制属性特性的解决方案

问题背景

我在做AOP织入处理时,逻辑是遍历类、属性及其特性:当识别到MetaAttribute(typeof(SomethingElse))特性时,找到SomethingElse类中名为Target的属性,把它的所有特性复制到当前处理模块中对应类的属性上。比如Person类的Title属性标注了[Meta(typeof(PersonTitleMeta))],而PersonTitleMeta的Target属性带有Required、MinimumLength等特性,需要把这些特性复制到Person.Title上。

当PersonTitleMeta和Person在同一程序集时,用这段代码可以正常运行:

foreach (var currentSourceAttribute in sourceAttributes) 
    property.CustomAttributes.Add(currentSourceAttribute);

但二者在不同程序集时,会报错:System.ComponentModel.DataAnnotations.RequiredAttribute::.ctor()' is declared in another module and needs to be imported。

解决思路

不能直接跨模块复制已有的CustomAttributeData实例,因为它绑定了原模块的构造函数引用。正确的做法是基于原特性的元数据,在目标模块中重新构造特性实例:

具体实现步骤

  1. 获取原特性的类型与构造函数信息:从源特性的Constructor属性拿到构造函数的MethodBase,再在目标模块可访问的范围内找到对应的构造函数(可通过Type.GetType获取特性类型后再匹配构造函数参数)。
  2. 转换构造函数参数:遍历源特性的ConstructorArguments,将参数值转换成目标模块能识别的形式——值类型直接复用,引用类型需确保目标模块已引用对应类型所在程序集。
  3. 处理命名参数:遍历源特性的NamedArguments,同样转换参数值,确保目标模块能解析这些参数对应的属性或字段。
  4. 添加新特性到目标属性:用目标模块的特性构建API(比如CustomAttributeBuilder),基于上述信息创建新特性并绑定到目标属性上。

代码示例

foreach (var sourceAttr in sourceAttributes)
{
    // 获取特性类型
    var attrType = sourceAttr.AttributeType;
    // 在目标模块中匹配对应的构造函数
    var targetCtor = attrType.GetConstructor(
        sourceAttr.Constructor.GetParameters().Select(p => p.ParameterType).ToArray());
    
    // 提取并转换构造函数参数
    var ctorArgs = sourceAttr.ConstructorArguments
        .Select(arg => arg.Value)
        .ToArray();
    
    // 处理命名参数,映射到特性类的成员
    var namedArgs = sourceAttr.NamedArguments
        .Select(arg => new KeyValuePair<MemberInfo, object>(
            attrType.GetMember(arg.MemberName).First(), 
            arg.TypedValue.Value))
        .ToArray();
    
    // 创建新特性并添加到目标属性
    var attrBuilder = new CustomAttributeBuilder(targetCtor, ctorArgs, namedArgs);
    property.SetCustomAttribute(attrBuilder);
}

关键注意事项

  • 确保目标模块已引用特性所在的程序集,否则会出现类型或构造函数找不到的错误。
  • 对于带复杂参数(如自定义类型、枚举)的特性,要保证目标模块能访问到这些参数的类型,避免加载失败。
  • 如果使用特定织入框架(如Fody、PostSharp),可直接用框架提供的跨模块特性复制工具类,这类工具会自动处理模块引用与类型解析问题。

内容的提问来源于stack exchange,提问作者Peter Morris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:52:54