如何获得最顶级的实例变量类型?

时间:2017-02-27 18:56:11

标签: c# validation postsharp system.reflection

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

我有一个验证属性和一个PostSharp,所以反射命中是在编译时,因此感谢CompileTimeValidation方法。我只是不知道我是怎么做到的。进行IsSubclassOf扫描没有用,因为我会得到多个误报。

为了给出上下文,我有一个基础Entity类型。我从这种类型派生出来,定义了各种Entity类型。我使用策略属性来装饰这些类型,包括基类Entity。 PostSharp方面在编译时验证某些策略约束。我希望能够仅使用方面验证来修饰基础Entity类型,以便验证Entity及其所有派生类型。我可以看到验证已经发生。但是,它被处理为Entity而不是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>
{
}

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

3 个答案:

答案 0 :(得分:1)

显然,PostSharp消除了这种需求。它支持通过多播自动应用于派生类型。所以,lifetime属性看起来像这样:

'^$carts/products/$'

[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; } } 行会让PostSharp自动将其应用于[MulticastAttributeUsage(Inheritance = MulticastInheritance.Multicast)]和其他人。

答案 1 :(得分:0)

我不太明白你的问题,但你总能找到:

1。对象实际类型(使用obj.GetType()):

if (obj.GetType() == typeof(Entity)) { ... }

2。如果object是从某种类型派生的(使用“是”运算符):

if (obj is Entity) { ... }

答案 2 :(得分:0)

你可以遍历每个基类,直到你达到最低点。在您正在寻找的属性的第一次停止:

var type = method.GetType();

do
{
    var lifetimePolicy = GetCustomAttribute(type, typeof(LifetimePolicyAttribute)) as LifetimePolicyAttribute;
    if (lifetimePolicy != null)
    {
        // process
        break; // out of the do...while
    }
} while ((type = type.BaseType) != null);