从泛型类的特定实现中排除一个方面?

时间:2017-03-01 21:48:08

标签: c# generics postsharp

说我有一个通用类:

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

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

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

1 个答案:

答案 0 :(得分:1)

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

然而,就你所描述的情况而言,即使这样也不够。假设您已将方面应用于MyClass<T>中的方法。在编译的这一点上,T还不知道,所以不可能执行检查。当MyClass<T>的字段或变量在代码中的其他地方声明时,具体T是已知的。

在我的案例中,我能看到的最佳选择是制作方面instance-scoped并在运行时验证目标类的每个实例。您可以在下面找到此方法的示例实现。

[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)
    {
    }
}