【问题标题】:Generically Casting object to it's 'real' type一般将对象转换为“真实”类型
【发布时间】:2015-11-23 10:57:41
【问题描述】:

我共享了很大程度上依赖于自定义属性的验证逻辑,因此我需要检查每种类型的验证逻辑。

为每个验证订阅者获取一个实例(用于检查):

var instance = this.ValidationProvider.GetInstanceForSubscriber(validationSubscriber);

其中validationSubscriber 是具有这些值的枚举:

人, 检查

此时GetInstanceForSubscriber返回一个object类型的实例:

public object GetInstanceForSubscriber(ValidationSubscribers validationSubscriber)
{
    switch (validationSubscriber)
    {
        case ValidationSubscribers.Person:
            return new Person();
        case ValidationSubscribers.Checks:
            return new Checks();
        default:
            return null;
    }
}

调用这个方法后,我检查类型:

var instanceType = instance.GetType();

然后,我阅读了(自定义)属性:

var attributes = propertyInfo.GetCustomAttributes(true);

然后,我返回一个 IEnumerable<PropertyAttribute> 列表,其中仅包含我的自定义属性,将验证规模限制在必要的范围内(仅供参考,因为与此问题不太相关)。

问题

由于instance 是对象类型,它不包含我的任何自定义属性(逻辑上),所以我需要将其转换为正确的类类型。

实现这一目标的最佳方法是什么?

【问题讨论】:

  • Enum 值和类名是否有完全匹配的名称?
  • 你为什么认为它不包含你的属性?
  • @ShantanuGupta:不,我不赞成这样做,因为这可能/将会变得难以维护(而且非常不可信)。
  • @CSharpie:var attributes = propertyInfo.GetCustomAttributes(true) 行返回一个 0 项列表,而对于实际类型来说它工作得很好。这是有道理的,因为object 没有我的自定义属性。
  • 如果你使用 instance.GetType() 它不应该返回 typeof(object)

标签: c# .net generics


【解决方案1】:

我建议通过引入界面来修改您的设计。

public interface ICustomAttribute
{
    IEnumerable<PropertyAttribute> GetCustomAttributes(true);
}

class Person:ICustomAttribute
{
    IEnumerable<PropertyAttribute> GetCustomAttributes(true)
    {
         //Validation logic here for Person entity.
         //Encapsulate your entity level logic here.
          return propertyInfo.GetCustomAttributes(true);
    }
}

class Check:ICustomAttribute
{
    IEnumerable<PropertyAttribute> GetCustomAttributes(true)
    {
         //Validation logic here for CHECK entity
         //Encapsulate your entity level logic here.
          return propertyInfo.GetCustomAttributes(true);
    }
}

public ICustomAttribute GetInstanceForSubscriber(ValidationSubscribers validationSubscriber)
{
    //Use dependency injection to eliminate this if possible
    switch (validationSubscriber)
    {
        case ValidationSubscribers.Person:
            return new Person();
        case ValidationSubscribers.Checks:
            return new Checks();
        default:
            return null;
    }
}

现在,当您从该方法接收到对象时,您将始终拥有正确的对象。

var instanceType = instance.GetCustomAttributes(true); //will give you all attributes

您可以通过利用泛型类型进一步增强此逻辑。见this。但是,这取决于您如何设计实体,因此您可以提出更好的解决方案。

【讨论】:

    【解决方案2】:

    一种方法是为您要验证的每种类型制作重载

    void ValidateWithAttributes(Person p, Attribute[] attr) {
        ...
    }
    void ValidateWithAttributes(Checks c, Attribute[] attr) {
        ...
    }
    // Add an overload to catch unexpected types
    void ValidateWithAttributes(Object obj, Attribute[] attr) {
        throw new InvalidOperationException(
            $"Found an object of unexpected type {obj?.GetType()}"
        );
    }
    

    现在您可以将对象转换为dynamic,并让运行时执行调度:

    object instance;
    ValidateWithAttributes((dynamic)instance, attributes);
    

    【讨论】:

      猜你喜欢
      • 2018-06-23
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2018-11-27
      • 2013-01-01
      • 1970-01-01
      相关资源
      最近更新 更多