C#为继承的类中的父属性添加自定义属性

时间:2010-03-01 11:02:21

标签: c# inheritance custom-attributes

我在通用DataGrids中显示Business Object,我想通过自定义属性设置列标题,例如:

class TestBo
 {
    [Header("NoDisp")]
    public int ID {get; set;}

    [Header("Object's name")]
    public String Name { get; set; }
}

到目前为止,这么好,但我还想通过继承将我的显示与我的数据分开:

class TestBO
{
   public int ID {get; set;}
   public String Name { get; set; }
}

class TestPresentationBO : TestBO
{
  //Question: how to simply set the Header attribute on the different properties?
}

我通过Child构造函数中的SetCustomAttribute通过反射看到了一个解决方案,但是它会很麻烦,所以这个问题有一个简单而优雅的技巧吗?

请阻止我破坏数据/演示文稿分离; o)

6 个答案:

答案 0 :(得分:6)

  
    

问题:如何在不同属性上设置Header属性?

  

无法按照建议的方式在继承的成员上设置属性,因为属性特定于某个类型。 SetCustomAttribute对你没有帮助 - 当你在运行时构造新类型时,它才有用。一旦编译了属性,就无法在运行时更改它,因为它是元数据的一部分。

如果你想保持分离,你必须找到另一种方式。

(你可以将属性设置为虚拟,在Presentation类中覆盖它们并在覆盖上添加属性,但这看起来很狡猾,并没有真正区分任何东西 - 你最终会在TestPresentationBO中找到一个完整的TestBO类。 。)

答案 1 :(得分:3)

TestBo中的属性设为虚拟,并在TestPresentationBO中覆盖它们。这样你可以添加属性。

答案 2 :(得分:2)

你可以像WCF RIA服务那样做。向TestBO添加属性,如[Presentation]将类型作为参数。这种新类型将重新定义属性,但具有表示属性。 在运行时,您必须获取新类型的标识并获取其属性的自定义属性。

或者忘记属性并使用字典映射BO和演示BO类。此演示文稿BO类与上面的内容相同,即使用自定义属性重新定义属性。

演示文稿BO类从未实例化,只是反映在获取演示文稿信息上。

答案 3 :(得分:2)

想一想,你不能用部分类和MetadatatypeAttribute解决这个问题吗? MVC2使用此模式进行模型验证。

答案 4 :(得分:2)

您使用的是MVVM(模型视图视图模型)模式吗?在我看来,部分来自其他答案,你不能用你想要的自定义属性真正做到这一点。但是,在我看来,TestPresentationBO实际上就像TestBO的“视图模型”一样。视图模型基本上是业务或逻辑类的一种包装或代理 - 这基本上是您想要的。 (这个视图模型的摘要可能不是100%准确;我刚刚开始使用MVVM。)

您可以创建TestBOViewModel来包装TestBO,然后将TestBOViewModel的集合传递给数据网格。当然,您可以使用[Header("Object's name")]等装饰公开包装类的属性。这不使用继承,但我不明白为什么在这种情况下需要使用继承。但是,使用视图模型,可以使用包装器(视图模型)将您的演示文稿(视图)与数据(模型)完全分开。

有关MVVM模式的更多信息,我发现这是一个有趣的读物:WPF Apps With The Model-View-ViewModel Design Pattern

像这样的东西。当然,您也可以在这里添加验证和其他好东西。

public class TestBOViewModel // extend from DependencyObject 
{                            // if you want to use dependency properties

    private TestBO _myBO;

    public TestBOViewModel(TestBO bo)
    {
        _myBO = bo;
    }

    [Header("NoDisp")]
    public int ID 
    {
        get { return _myBO.ID; }
        set { _myBO.ID = value; }
    }
}

答案 5 :(得分:0)

对于C#6.0,您可以轻松隐藏继承的成员并引入自己的属性。但是,这可能会隐藏原始属性的任何属性。此简化语法也使该属性成为只读属性,因此您可能需要自行管道get / set。

public class User
{
    public string Login { get; set; }
}


public class UserDetail : User
{
    [Display(Name = "Login:")]
    public new string Login => base.Login;
}