将自动实现属性的属性传递到其字段

本文关键字:属性 字段 实现 | 更新日期: 2023-09-27 18:15:25

我有以下问题:我想在第一步中为类Foo的自动实现属性prop添加一个属性。在第二步中,我迭代Foo的所有字段,并将值复制到这些字段(自动实现属性的字段值也被发现并复制)。在这一部分中,我需要访问属性的信息。

class FieldSetter
{
    // This Method is called from outside and should work for any class
    private void SetFieldValues(object unknownObject)
    {
        foreach (var field in
                unknownObject.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance |
                                       BindingFlags.Static).Where((field) => !field.IsLiteral))
        {
            if (!EvalAttribute(Attribute.GetCustomAttributes(field))) // the Attribute should be accessed here
            {
                // Do something if no special Information is set
                field.SetValue(a, "default Value");
            }
            else
            {
                // Do special things
                field.SetValue(a, "special Value");
            }
        }
    }

    internal static bool EvalAttribute(Attribute[] attributes)
    {
        foreach (System.Attribute attr in attributes)
        {
            var myAttr = attr as MyAttribute;
            if (myAttr != null)
            {
                if (myAttr.SomeAttributeValues == "Specific Attribute Value")
                {
                    return true;
                }
            }
        }
        return false;
    }
}
// This class is a example for how a given Object can look like
class Foo
{
    [MyAttribute("Example Information")] // This Attribute won't be accessed via prop-Field
    int prop { get; set; }
    [MyAttribute("Another Example Information")] // This Attribute won't be accessed via prop-Field
    int field;
    //... lots of other fields and properties
}

[System.AttributeUsage(System.AttributeTargets.All)]
class MyAttribute : Attribute
{
    public MyAttribute(string someInformation)
    {
        SomeAttributeValues = someInformation;
    }
    public string SomeAttributeValues;
}

将自动实现属性的属性传递到其字段

你不能这么做。如果需要在字段上使用属性,则需要自己声明字段,而不是使用auto-properties。或者,您可以在查找具有该属性的属性时进行反射。

如果您能保证您感兴趣的属性将始终自动实现,并且您知道将使用什么编译器来编译您感兴趣的类型,那么您可以利用自动生成属性的支持字段遵循特定的命名约定这一事实。例如,您提供的代码以如下字段名结束:

<prop>k__BackingField

这是一个独特的名称,不能由c#代码直接产生,所以如果您遇到一个具有这样名称的字段,您可以从尖括号之间解析出属性名称,并对该名称使用GetProperty()

然而,这是一个很蹩脚的解决方案,因为:

  1. 用于支持字段的名称是一个实现细节,理论上可以在未来的。net版本中更改,或者用于替代编译器,如Mono。
  2. 没有什么可以确保您找到的字段总是与auto-properties绑定。如果你遇到这种情况,你的期望是什么?

    class Foo
    {
        int field;
        [MyAttribute("Example Information")]
        int prop { get{return field;} set {return field;} }
        //... lots of other fields and properties
    }
    

我强烈建议您花更多的时间分析您真正的业务需求和约束是什么,看看是否有其他更可靠的方法来解决这个问题。