0

对于要应用于类的属性和类中的属性,我有以下代码:

public class SerialiseAttribute : Attribute, IAspectProvider, IValidableAnnotation {

    public string ApplyToProperty { get; set; }

    public string Name { get; set; }

    public bool Ignore { get; set; }

    bool IValidableAnnotation.CompileTimeValidate(object target) { return true; }

    IEnumerable<AspectInstance> IAspectProvider.ProvideAspects(object targetElement) {
        var type = targetElement as Type;

        if (type != null && !FastSerialisationCacheAttribute.AppliedTo.Contains(type)) {
            FastSerialisationCacheAttribute.AppliedTo.Add(type);
            yield return new AspectInstance(type, new FastSerialisationCacheAttribute());
        }
    }

}

这将初始化 FastSerialisationCacheAttribute 并成功执行 CompileTimeInitialize(它派生自 TypeLevelAspect 方面)。但是,当我检查生成的 IL 时;提供的类型上没有 FastSerialisationCacheAttribute,在运行时我也找不到使用反射的类型。

如果我使用以下代码切换 ProviderAspects 函数:

IEnumerable<AspectInstance> IAspectProvider.ProvideAspects(object targetElement) {
    var type = targetElement as Type;

    if (type != null && !FastSerialisationCacheAttribute.AppliedTo.Contains(type)) {
        FastSerialisationCacheAttribute.AppliedTo.Add(type);
        var constructor = typeof(FastSerialisationCacheAttribute).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
        var objectConstruction = new ObjectConstruction(constructor);
        var introduceCacheAspect = new CustomAttributeIntroductionAspect(objectConstruction);
        yield return new AspectInstance(type, introduceCacheAspect);
    }
}

然后它将属性添加到 IL,但这不会初始化属性(执行 CompileTimeInitialize)。

4

1 回答 1

0

好吧,我认为您已经非常接近问题的解决方案。如果你想动态地引入方面和属性,那么你需要返回这两者FastSerialisationCacheAttributeCustomAttributeIntroductionAspectfromProvideAspects方法的实例。

在从程序集中读取所有先前应用的方面属性之后IAspectProvider.ProvideAspects执行该方法。如果您在第二个示例中引入另一个属性,那么它已经为时已晚,无法引起方面的引入。

IAspectProvider.ProvideAspects您通常会向目标介绍其他方面。如果你真的需要引入实际属性,那么你会使用CustomAttributeIntroductionAspect.

请注意,方面工作通常不需要添加属性,但我不知道您的代码中的逻辑是什么。

于 2013-10-07T16:18:13.470 回答