如何获取实例变量的最顶层类型?

Big*_*sby 5 c# validation postsharp system.reflection

假设我有一个被声明为给定基类的实例变量。我想找到该对象实际上是什么原始的、最上面的类型,而不是基类。我该怎么做呢?

我有一个类似于 PostSharp 的验证属性,因此反射命中是在编译时发生的,因此由于该CompileTimeValidation方法而没有实际意义。我只是不知道该怎么做。进行IsSubclassOf扫描没有帮助,因为我会得到多个误报。

为了提供上下文,我有一个基本Entity类型。我从这个类型派生出所有类型的定义Entity。我Entity使用策略属性来装饰这些类型,包括基本类型。PostSharp 方面在编译时验证某些策略约束。我希望能够仅使用Entity方面验证来装饰基类型,以便Entity验证其所有派生类型。我可以看到验证已经发生。但是,它被作为 anEntity和 not处理DerivedEntity。为了评估 的策略DerviedEntity,我需要专门装饰该类。如果可能的话我想不这样做,而只是装饰Entity

本质上,我想将验证集中在基类上,因为所有派生类的验证架构都是相同的。但是,派生类中的值可能会更改,我需要进行一些边界检查。

编辑:让我们添加一些代码。

[EnforceMaxLifetimePolicy]
[LifetimePolicy]
public class Entity<T>
{
    public string Key { get; set; }
    public T Object { get; set; }

    public TimeSpan EntityLifetime
    {
        get
        {
            var lifetimePolicy =
                Attribute.GetCustomAttribute(GetType(), typeof(LifetimePolicyAttribute)) as LifetimePolicyAttribute;

            return new TimeSpan(lifetimePolicy.Hours, lifetimePolicy.Minutes, 0);
        }
    }
}

[Serializable]
[AttributeUsage(AttributeTargets.Class)]
internal class LifetimePolicyAttribute : Attribute
{
    public readonly short Hours;
    public readonly short Minutes;

    public LifetimePolicyAttribute(short hours, short minutes)
    {
        Hours = hours;
        Minutes = minutes;
    }

    public LifetimePolicyAttribute()
    {
        Minutes = 1;
    }
}

[Serializable]
[AttributeUsage(AttributeTargets.Class)]
internal class EnforceMaxLifetimePolicyAttribute : OnMethodBoundaryAspect
{
    public override bool CompileTimeValidate(MethodBase method)
    {
        var type = method.GetType();

        var lifetimePolicy = GetCustomAttribute(type, typeof(LifetimePolicyAttribute)) as LifetimePolicyAttribute;

        if (lifetimePolicy != null && lifetimePolicy.Hours + lifetimePolicy.Minutes / 60 > 24)
        {
            throw new InvalidAnnotationException($"Lifetimes can not exceed 24 hours. The lifetime on {type.FullName} is invalid.");
        }

        return true;
    }
}

[LifetimePolicy(hours: 24, minutes: 0)]
internal class ShoppingCartEntity : Entity<ShoppingCart>
{
}
Run Code Online (Sandbox Code Playgroud)

[EnforceMaxLifetimePolicy]如您所见,ShoppingCartEntity上没有。它位于基类上Entity。但是,我仍然希望 Enforce 属性实体也适用于派生类型,这就是我将该标志保留Inherited为默认值 (true) 的原因。

Big*_*sby 1

显然,PostSharp 消除了这种需要。它支持通过多播自动应用到派生类型。因此,生命周期属性如下所示:

[Serializable]
[AttributeUsage(AttributeTargets.Class)]
[MulticastAttributeUsage(Inheritance = MulticastInheritance.Multicast)]
internal class EnforceMaxLifetimePolicyAttribute : OnMethodBoundaryAspect
{
    public override bool CompileTimeValidate(MethodBase method)
    {
        var type = method.DeclaringType;

        var lifetimePolicy = GetCustomAttribute(type, typeof(LifetimePolicyAttribute)) as LifetimePolicyAttribute;

        if (lifetimePolicy.Hours + lifetimePolicy.Minutes / 60 > 24)
        {
            throw new InvalidAnnotationException($"Lifetimes can not exceed 24 hours. The lifetime on {type.FullName} is invalid.");
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

[MulticastAttributeUsage(Inheritance = MulticastInheritance.Multicast)]行将让 PostSharp 自动将其应用到ShoppingCartEntity和其他行。