【问题标题】:How to get the top most type of an instance variable?如何获得实例变量的最高类型?
【发布时间】:2017-02-28 03:39:58
【问题描述】:

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

我有一个 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) 的原因。

【问题讨论】:

  • obj.GetType() 适合你吗?
  • 我想你最上面的类型总是object :)
  • @AndreiM 不幸的是没有。如果我这样做,我只会评估基于 Entity 的策略属性,并且不会获得适当子类型的属性。
  • @Bigsby 你知道你可以随时查看obj is Entity 或任何其他你需要的类型。
  • 你能显示一些代码吗?我很难理解实际问题。

标签: c# validation postsharp system.reflection


【解决方案1】:

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

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

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

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

if (obj is Entity) { ... }

【讨论】:

    【解决方案2】:

    显然,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 和其他人。

    【讨论】:

      【解决方案3】:

      您可以遍历每个基类,直到跌至谷底。在您正在寻找的属性的第一次停止:

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

      【讨论】:

        猜你喜欢
        • 2011-03-27
        • 1970-01-01
        • 1970-01-01
        • 2021-03-28
        • 2013-10-22
        • 2012-08-30
        • 1970-01-01
        相关资源
        最近更新 更多