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

How to get the top most type of an instance variable?

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

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

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

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

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

[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]。它位于 class Entity 基地。但是,我仍然希望 Enforce 属性实体也适用于派生类型,这就是为什么我将 Inherited 标志保留为默认值 (true) 的原因。

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

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

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

2。如果对象派生自某种类型(使用 "is" 运算符):

if (obj is Entity) { ... }

您可以遍历每个基地 class 直到跌至谷底。在您要查找的属性第一次出现时停止:

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

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

[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;
    }
}

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