【问题标题】:Adding additional attributes to each property of a class为类的每个属性添加附加属性
【发布时间】:2011-11-30 19:34:05
【问题描述】:

假设我有一个具有任意类型的任意数量属性的类

public class Test
{
public string A {get;set;}
public object B {get;set;}
public int C {get;set;}
public CustomClass D {get;set;}
}

我希望此类中的所有对象都具有“错误”和“警告”的概念。例如,基于另一个类中的某些条件,我可能想在属性 A 上设置警告,然后在 GUI 中显示该信息。 GUI 不是我关心的问题。而我应该如何设置这个警告?我希望能够做类似的事情:

对于类中的每个属性,添加一个“警告”和“错误”属性,这样我就可以做到了..

Test t = new Test();
t.A.Warning = "This is a warning that the GUI will know to display in yellow".
t.B.Error = null;

执行此操作的最佳方法是什么?如果我可以为类的每个属性添加一个自定义属性来添加这些附加属性并允许我以清晰的方式访问它们,那就太好了。

我已经看到将字典添加到父类(测试)的解决方案,然后传入与属性名称匹配的字符串,或者使用反射来获取属性名称并将其传入,但我更喜欢更干净的东西。

【问题讨论】:

    标签: c# .net c#-4.0 attributes


    【解决方案1】:

    您可以向属性添加您想要的自定义属性,然后在对象上使用扩展方法来访问这些属性。

    这样的东西应该可以工作

    首先你需要创建你的属性类

    [AttributeUsage(AttributeTargets.All/*, AllowMultiple = true*/)]
    public class WarningAttribute : System.attribute
    {
       public readonly string Warning;
    
       public WarningAttribute(string warning)
       {
          this.Warning = warning;
       }    
    }
    

    更多阅读Here

    这样使用它

    [WarningAttribute("Warning String")]
    public string A {get;set;}
    

    然后访问它MSDN Article

    public static string Warning(this Object object) 
    {
        System.Attribute[] attrs = System.Attribute.GetCustomAttributes(object);
    
        foreach (System.Attribute attr in attrs)
            {
                if (attr is WarningAttrbiute)
                {
                    return (WarningAttribute)attr.Warning;
                }
            } 
    }
    

    然后,如果您有想要访问警告的项目,您可以简单地调用

    test.A.Warning;
    

    如果您想设置警告字符串,您可以更简洁地实现某种设置器。可能通过设置辅助对象或属性类型。


    执行此操作的另一种方法是,您可以创建自定义泛型类型来处理该属性设置,而不是仅使用 stringobject

    类似

    public class ValidationType<T>
    {
       public T Value {get; set;}
       public string Warning {get; set;}
       public string Error {get; set;}
    
       public ValidationType(T value)
       {
          Value = value;
       }
    }
    

    使用喜欢

    var newWarning = new ValidationType<string>("Test Type");
    newWarning.Warning = "Test STring";
    Console.WriteLine("newWarning.Value");
    

    【讨论】:

    • 感谢您的回复。我想我会实现这一点。我不喜欢使用 newWarning.Value 来实际访问字符串属性,但似乎我必须在某处牺牲一些便利。
    【解决方案2】:

    如果您可以使用方法而不是属性,那么您可以为对象创建扩展 - 但是很难将其仅用于某些类。

    类似:

    public static void Warning(this object target, string message)
    {
    ...
    }
    
    public static String GetWarning(this object target)
    {
    }
    

    当然,在对象的状态下保持这样的警告是很困难的,但是你可以使用一些字典等。

    【讨论】:

    • 感谢您的帖子,但我宁愿避免使用此解决方案。我希望实际属性知道它是否有错误,而不是父对象必须循环遍历字符串字典(例如)。
    【解决方案3】:

    我建议您将错误/警告属性的集合添加到您的业务对象从其继承的基类中,而不是尝试对属性进行归因。

    这样,您可以提供更详细的信息,当它们显示给用户时,您可以删除它们,并且,如果您通过“线路”(Web 服务、wcf 服务)发送数据,则错误可以与您的对象一起旅行,而不需要特殊处理来发送属性。

    【讨论】:

      【解决方案4】:

      首先,属性不能修改它们放置的对象。除非您将它们与 AOP 结合使用。我建议通过继承类在类周围使用包装类,前提是类不是密封的。如果它们是密封的,那么您将不得不编写一个实际的包装类,将所有操作(您添加的操作除外)传递给一个私有字段,该字段是您包装的类的实例。

      编辑: 为了便于使用,建议的扩展方法可能是最好的解决方案。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-14
        • 1970-01-01
        • 2011-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多