从通用 class 的特定实现中排除一个方面?

Excluding an aspect from specific implementations of a generic class?

说我有一个通用的 class:

public abstract class MyClass<T> {
    // Contents
}

如何为我的 aspect 指定排除特定类型的 T?我在 AssemblyInfo.cs 中添加方面,如下所示:

[assembly: LogMethod(AttributePriority = 0,
                     AttributeTargetTypeAttributes = MulticastAttributes.Public,
                     AttributeTargetMemberAttributes = MulticastAttributes.Public,
                     AttributeTargetElements = MulticastTargets.Method)]

无法以声明方式应用通用参数过滤。对于方面目标的高级过滤,您可以覆盖方面的 CompileTimeValidate 方法并以编程方式进行过滤。

但是,对于您所描述的情况,即使这样也不够。假设您已将方面应用于 MyClass<T> 中的方法。此时在编译中 T 还未知,因此无法执行检查。当 MyClass<T> 的字段或变量在代码的其他地方声明时,具体 T 是已知的。

在您的情况下,我能看到的最佳选择是创建方面 instance-scoped 并在 运行 时间对目标 class 的每个实例进行验证。您可以在下面找到此方法的示例实现。

[PSerializable]
public class LogMethodAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect
{
    private bool disabled;

    public override void OnEntry( MethodExecutionArgs args )
    {
        if ( !this.disabled )
        {
            Console.WriteLine( "OnEntry: {0}({1})", args.Method.Name, args.Arguments.GetArgument( 0 ) );
        }
    }

    public object CreateInstance( AdviceArgs adviceArgs )
    {
        LogMethodAttribute clone = (LogMethodAttribute) this.MemberwiseClone();

        Type type = adviceArgs.Instance.GetType();
        if ( type.IsGenericType )
        {
            Type[] genericArguments = type.GetGenericArguments();
            // Filter out targets where T is string.
            if ( genericArguments[0] == typeof( string ) )
            {
                clone.disabled = true;
            }
        }

        return clone;
    }

    public void RuntimeInitializeInstance()
    {
    }
}

class Program
{
    static void Main( string[] args )
    {
        var obj1 = new Class1<int>();
        obj1.Method1(1);

        var obj2 = new Class1<string>();
        obj2.Method1("a");
    }
}

[LogMethod(AttributeTargetElements = MulticastTargets.Method)]
public class Class1<T>
{
    public void Method1(T a)
    {
    }
}