【问题标题】:Get attributes assigned to property of a Type using an instance of that property使用该属性的实例获取分配给该类型的属性的属性
【发布时间】:2013-07-09 02:34:15
【问题描述】:

我遇到了一个问题,我需要知道属性是否放置在类的属性上,但我受到限制,因为实际上我得到的只是该属性的一个实例(类型没用在这种情况下)。

问题来自这样一个事实,即我正在使用自定义 ContractResolver 来检测此类属性,但在使用 ShouldSerialize 谓词的情况下,您从 DefaultContractResolver 获得的只是类型或实例。

我不能使用 Attribute.GetCustomAttributes(type) 因为属性不在类型上。 TypeDescriptor 也没有运气。我在想是否有可能从该实例获取成员信息,以便我可以将其传递给 GetCustomAttributes,这甚至可能吗?有没有其他办法?

顺便说一句,我想要完成的是在某些属性上放置一个标记属性,以便我的合同解析器只能序列化该类型的某些属性,而不是所有这些属性。我不想把它放在类型本身上,因为有时我想序列化整个对象。为每种类型创建一个合约解析器也是不切实际的,因为这会很庞大。

var instance = new MyClass();

instance.MyProperty = new OtherClass();

// propertyValue is all I get when I'm on the ShouldSerializeMethod
object propertyInstance = instance.MyProperty;

var attributes = Attribute.GetCustomAttributes(propertyInstance.GetType());

// this returns no attributes since the attribute is not on the type but on the property of another type
Console.WriteLine (attributes.Length);

public class MyClass
{
    [MyCustomAttribute]
    public OtherClass MyProperty { get; set; }
}

public class OtherClass
{
    public string Name { get; set; }    
}

public class MyCustomAttribute : Attribute
{    
}

【问题讨论】:

    标签: c# json.net


    【解决方案1】:

    你是如此接近...只需从类中获取属性(使用反射),然后使用来自PropertyInfoGetCustomAttributes(...)。要获取应用于属性的所有属性,请使用:

    MyClass obj = new MyClass();
    var attList = obj.GetType()
                     .GetProperty("MyProperty")
                     .GetCustomAttributes(true);
    

    或者如果你只想要一个特定的属性类型:'

    MyClass obj = new MyClass();
    var attList = obj.GetType()
                     .GetProperty("MyProperty")
                     .GetCustomAttributes(typeof(MyCustomAttribute), true);
    

    请注意,不存在应用于类的实例的属性之类的东西——属性总是在类本身上。因此,试图为实例获取自定义属性将是徒劳的。

    【讨论】:

    • 谢谢迈克尔,但是,当我使用 ShouldSerialize 方法时,我得到的只是 propertyValue 变量,它不知道它来自哪里。所以我只知道那个 propertyValue 是 OtherClass 类型,它不知道它被定义为 MyClass 的一个属性(这是定义 attrobite 的地方)。是的,属性被分配给类型、属性、字段,但在这种情况下,我所拥有的只是那个实例属性。我已经编辑了标题,希望更清楚。
    • 我不确定我是否遵循了困难...如果您有一个实例变量obj,那么只需使用obj.GetType().GetProperty...
    • OOhhhh hmm 没有办法从属性值返回到引用该对象的对象,除非它是您拥有的属性的一部分。如果那就是你需要的,那么你就不走运了。
    • 就是这样,json.net 的 JsonProperty.ShouldSerialize 谓词方法为您提供 propertyValue,它不会告诉您它属于 MyClass 或者甚至 MyClass 存在或属于正在序列化的“主”对象.这就是为什么我要问,既然我有 propertyValue 实例,我是否可以找出该实例所属的类型(在本例中为 MyClass)。有了它,你的代码就完美了
    • 不幸的是,没有办法做到这一点。一个值类型甚至不会是同一个对象,一个引用类型可能有多个对它的引用,所以这不可能发生。听起来你可能需要一些重构。
    【解决方案2】:

    正如迈克尔·布雷(Michael Bray)所提到的,这是不可能的,为什么不这样做是完全有道理的。

    然而,为了完成我打算做的事情,我设法做到了,但我没有使用自己的标记属性,然后希望使用 ContractResolver 覆盖,而是使用了 json.net 属性:

    [JsonConverter(typeof(SerializeOnlyWhatIWantOnThisPropertyConverter))]
    

    这样我们可以依靠 json.net 的代码来继续工作,同时允许我们在每个属性的基础上过滤掉我们想要序列化的内容。这样做的缺点是转换器的实现更加冗长且容易出错,并且我们不能使用 ContractResolver 提供的其他功能,例如 TypeNameHandling。我也相信 ResolveContract 路由更有效,因为它具有内置缓存,尽管我还没有进行任何基准测试。

    【讨论】:

      猜你喜欢
      • 2020-09-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-12
      • 2011-12-16
      • 1970-01-01
      • 2015-07-16
      • 2020-04-07
      • 1970-01-01
      相关资源
      最近更新 更多