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

C# 如何获取实例变量的最顶层类型?,c#,validation,postsharp,system.reflection,C#,Validation,Postsharp,System.reflection,假设我有一个声明为给定基类的实例变量。我想找出该对象的原始最上层类型,而不是基类。我该怎么做 我有一个validation属性a la PostSharp,因此反射命中是在编译时进行的,因此由于CompileTimeValidation方法,它是没有意义的。我简直不知道该怎么做。执行IsSubclassOf扫描没有帮助,因为我会得到多个误报 为了给出上下文,我有一个基本的实体类型。我从这个类型派生出了所有类型的实体类型。我用一个policy属性修饰这些类型,包括基本的实体。PostSharp方面

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

我有一个validation属性a la PostSharp,因此反射命中是在编译时进行的,因此由于
CompileTimeValidation
方法,它是没有意义的。我简直不知道该怎么做。执行
IsSubclassOf
扫描没有帮助,因为我会得到多个误报

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

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

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

[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>
{
}
[EnforceMaxLifetimePolicy]
[终身保单]
公共类实体
{
公共字符串密钥{get;set;}
公共T对象{get;set;}
公共时间跨度实体寿命
{
得到
{
var生存期策略=
GetCustomAttribute(GetType(),typeof(LifetimePolicyAttribute))作为LifetimePolicyAttribute;
返回新的时间跨度(lifetimePolicy.Hours,lifetimePolicy.Minutes,0);
}
}
}
[可序列化]
[AttributeUsage(AttributeTargets.Class)]
内部类LifetimePolicyAttribute:属性
{
公众阅读时间短;
公众只读短分钟;
公共生命周期策略属性(短小时、短分钟)
{
小时=小时;
分钟=分钟;
}
公共LifetimePolicyAttribute()
{
分钟=1;
}
}
[可序列化]
[AttributeUsage(AttributeTargets.Class)]
内部类强制MaxLifetimePolicyAttribute:OnMethodBoundaryAspect
{
公共重写bool CompileTimeValidate(MethodBase方法)
{
var type=method.GetType();
var lifetimePolicy=GetCustomAttribute(type,typeof(LifetimePolicyAttribute))作为LifetimePolicyAttribute;
if(lifetimePolicy!=null&&lifetimePolicy.Hours+lifetimePolicy.Minutes/60>24)
{
抛出新的InvalidAnnotationException($“生存期不能超过24小时。{type.FullName}上的生存期无效。”);
}
返回true;
}
}
[生命周期策略(小时:24分钟:0)]
内部类ShoppingCarentity:实体
{
}

如您所见,ShoppingCarentity上没有
[EnforceMaxLifetimePolicy]
。它位于基类
实体
上。但是,我仍然希望强制属性实体也应用于派生类型,这就是为什么我将
继承的
标志保留为其默认值(true)。

我不太理解您的问题,但您总能发现:

1.对象实际类型(使用obj.GetType()): 2.如果对象是从某种类型派生的(使用“is”运算符):
你可以在每个基类上循环,直到你到达最低点。在您要查找的属性首次出现时停止:

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(继承=MulticastInheritance.Multicast)]
行将让PostSharp自动将其应用于
ShoppingCarteEntity
和其他。

obj.GetType()
适用于您吗?我想您的最上面的类型总是
对象
:)@AndreiM不幸的是没有。如果我这样做,我只对基本的
实体
求值policy属性,而没有得到相应子类型的属性。@Bigsby你知道你可以随时检查
obj is Entity
或任何其他你需要的类型。你能显示一些代码吗?我很难理解实际的问题。
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);
[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;
    }
}