【问题标题】:Passing Attributes of a Auto-Implemented Property to its field将自动实现的属性的属性传递给其字段
【发布时间】:2015-09-30 18:14:06
【问题描述】:

我有以下问题:我想在第一步中为类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;
}

【问题讨论】:

  • 是否有理由需要遍历所有 字段 而不是遍历 properties?如果prop 不是自动属性,但有一些其他特殊实现,你会怎么做?有一种 hacky 方法可以完成您正在做的事情,但我建议您先探索直接访问属性设置器的可能性。
  • 不知道类,由SetFieldValues处理。所以 Foo 对我来说是一个“黑匣子”。另一种方法可能是,排除具有我迭代中的属性的字段。我想这样做的主要原因是:我有 2 个类似的对象。每个对象包含不同的信息(私有或公共原始字段,...,具有类的字段(它们也将被递归复制),...,来自自动属性的字段,...)。我想在 1 个实例中合并所有这些信息。
  • 您发布的代码并没有明确说明您可以访问哪些信息,哪些信息不能访问。您的代码是否提供了程序集?类型列表?字段列表?属性列表?如果你的代码是GetFields(),那么它可以很容易地说GetProperties(),对吧?
  • 你说得对,我可以额外使用GetProperties(),但是我也必须从我的GetFields() 迭代中排除相应的字段。否则,某些字段将使用 AND 而没有属性 Information 进行处理。
  • 您确定要访问 private 字段?能够检测私有成员的自定义属性似乎是一个非常奇怪的要求。你不能只访问公共字段和属性吗?

标签: c# properties attributes field


【解决方案1】:

你不能这样做。如果您需要在字段上具有属性,则需要自己声明该字段并且不使用自动属性。或者,您可以在查找时反映将具有该属性的属性。

【讨论】:

    【解决方案2】:

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

    <prop>k__BackingField
    

    这是一个独特的名称,不能由 C# 代码直接生成,因此如果遇到具有这样名称的字段,您可以从尖括号之间解析出属性名称,并在其上使用 GetProperty()名字。

    但是,这是一个 hacky 解决方案,因为:

    1. 用于支持字段的名称是一个实现细节,理论上可能会在未来版本的 .NET 或 Mono 等替代编译器中发生变化。
    2. 没有什么可以确保您找到的字段始终与自动属性相关联。如果遇到这种情况,您的期望是什么?

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

    我强烈建议您花更多时间分析您的实际业务需求和限制,看看是否有其他更可靠的方法来解决这个问题。

    【讨论】:

    • 感谢您的回答!我认为就我而言,如果我将 Attribute 应用于字段或属性的 CustomType 就足够了。到目前为止,这将解决我的问题。
    • 只是为了你的想象:假设我想合并两个对象Foo1Foo2的信息,它们实现了一个接口IFoo,它有几个列表属性。一些 List-Properties 允许重复的条目,而另一些则不允许。在不明确知道这些列表的情况下,如何区分这些合并行为?
    • @MarkusWeber:IFoo 上的那些属性是否有公共 getter 和 setter? IFoo 上是否有您感兴趣的所有值,或者您是否正在尝试收集与接口无关的其他字段?如果是后者……为什么?你有什么保证IFoo 属性是由自动属性隐式实现的,而不是显式或自定义属性实现?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-14
    • 2017-09-14
    • 1970-01-01
    • 2018-08-04
    相关资源
    最近更新 更多