为什么ProvideAspects方法在实例化时不会将属性添加到IL?

时间:2013-10-07 15:10:08

标签: c# postsharp

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

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)。

1 个答案:

答案 0 :(得分:0)

嗯,我认为你已经非常接近你问题的解决方案了。如果要动态引入方面和属性,则需要从FastSerialisationCacheAttribute方法返回CustomAttributeIntroductionAspectProvideAspects的实例。

方法IAspectProvider.ProvideAspects在之后执行已从程序集中读取所有先前应用的方面属性。如果你在第二个例子中引入了另一个属性,那么导致方面介绍已经太晚了。

IAspectProvider.ProvideAspects中,您通常会向目标引入其他方面。如果您确实需要引入实际属性,那么您将使用CustomAttributeIntroductionAspect

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