【问题标题】:C# Dependent properties, dependency on correct order of setter executionC# 依赖属性,依赖于 setter 执行的正确顺序
【发布时间】:2015-06-22 18:15:58
【问题描述】:

我想知道如何在 C# 中处理依赖属性。我有以下简化类(我正在使用DevExpress XAF):

public class Company
{
    public ContactMethods? PreferredContactMethod { get; set; }
    // Missing: Collection of Employees...
}

public class Employee
{
    private Company company;

    public Company Company
    {
        get
        {
            return this.company;
        }
        set
        {
            company = value;
            if (company != null && PreferredContactMethod == null)
            {
                PreferredContactMethod = company.PreferredContactMethod;
            }
        }
    }

    public ContactMethods? PreferredContactMethod { get; set; }
}

将Company分配给Employee时,我将Employee.PreferredContactMethod设置为Company的PreferredContactMethod(只是为了方便,以后可以更改)。


更新:

我想在初始化新员工时使用 Company.PreferredContactMethod 作为默认值。每个员工都独立于公司存储自己的 ContactMethod。以后对 Company.PreferredContactMethod 的更改不应更新 Employee.PreferredContactMethod。 Employee.PreferredContactMethod 为 null 是完全合法的(例如,如果明确设置为用户)。


相当简单的代码,当然这工作得很好。但我认为它违反了Microsoft's Property Design Guidelines

请允许以任何顺序设置属性,即使这会导致 临时无效对象状态。

Company = A, PreferredContactMethod = null 给出的结果与PreferredContactMethod = null, Company = A 不同。

我认为我不能依赖属性设置器的“正确”顺序(例如,如果使用 Automapper/Reflection),您如何处理这种情况?我认为这并不少见。

谢谢!

【问题讨论】:

  • 您希望员工的 PreferredContactMethod 始终与公司的一致吗?如果调用 Employee.PreferredContactMethod 的 setter 会发生什么,这会影响 Company.PreferredContactMethod 的值吗?也许您可以为 Employee 使用自定义 getter,即 Employee.PreferredContactMethod 返回 Employee.company.PreferredContactMethod?
  • 我更新了我的要求。我希望现在更清楚了。我经常在我的业务对象中使用类似的代码
  • 我认为我的要求(为方便起见将属性初始化为默认值)在某种程度上与 UI 相关。也许使用一些 UI-Controller 代码是更好的方法?你怎么看?

标签: c# oop properties xaf


【解决方案1】:

您希望确保 Employee 具有与该公司自己相同的 PreferredContactMethod 的不变量,除非他自己具有指定的 PreferredContancMethod。扩展您的解决方案的一种方法是实现这一点,即像这样更新这个值:

public class Employee
{
    private Company company;
    public Company Company
    {
        get { return this.company; }
        set
        {
            this.company = value;
            UpdateCompanyPreferredContactMethod();
        }
    }

    private ContactMethods? preferredContactMethod;
    public ContactMethods? PreferredContactMethod 
    {
        get { return this.preferredContactMethod; }
        set
        {
            this.preferredContactMethod = value;
            UpdateCompanyPreferredContactMethod();
        }
    }

    private void UpdateCompanyPreferredContactMethod()
    {
        if (PreferredContactMethod == null)
        {
            PreferredContactMethod = company != null ?company.PreferredContactMethod : null;
        }
    }
}

但是,此解决方案很脆弱,因为您每次更改时都必须更新此值。相反,我实际上会这样做:

public class Employee
{
    public Company Company { get; set; }

    private ContactMethods? preferredContactMethod;
    public ContactMethods? PreferredContactMethod 
    {
        get 
        { 
            if (this.preferredContactMethod != null)
            {
                return this.preferredContactMethod;
            }
            else if (this.Company != null)
            {
                return this.Company.PreferredContactMethod;
            }
            else
            {
                return null;
            }
        }
        set { this.preferredContactMethod = value; }
    }
}

【讨论】:

  • 我喜欢你的后一个例子,但我想强调的是,OP 应该考虑他/她的设计要求。特别是Employee.PreferredContactMethod什么时候应该对应Company.PreferredContactMethod?
  • 谢谢 golergka,很好的解决方案。但我认为它不符合我的(更新的)要求。
【解决方案2】:

你说你想在初始化一个新员工时使用 PreferredContactMethod 作为默认值。如果是这种情况,您应该将 Company 传递给 Employee 的构造函数,然后设置它:

public Employee(Company company) {
    // Null checks as appropriate
    this.company = company;
    this.PreferredContactMethod = company.PreferredContactMethod;
}

如果您还想以您的方式更改 PreferredContactMethod,并且您唯一担心的是违反设计准则,那么除了仅更改 @987654323 之外,还可以使用方法 Employee.SetCompany 来指示该操作有副作用@属性。

【讨论】:

  • 不幸的是我不能使用构造函数方法。在我使用的框架中(XAF),不存在真正的 ViewModel。 GUI 会自动创建并绑定到持久类。将生成一个员工列表视图以及一个“新员工”操作以在 DetailView 中构造一个新的空员工。在 DetailView 中,为所有公共属性创建了编辑器(但不是为方法创建的,所以我不能轻易使用 SetCompany() 方法)。为 Employee 创建了两个编辑器:“Company”查找和“PreferredContactMethod”查找。我想没有某种 ViewModel 就没有好的解决方案?!
【解决方案3】:

我认为您需要在保存 Employee 对象之前分配它,因此任何订单都会给出相同的结果。

试试这个;

if (IsNewRecord && Company != null && PreferredContactMethod == null)
    PreferredContactMethod = Company.PreferredContactMethod;

【讨论】:

  • 嗯,不确定我是否理解您的回答。在 XAF/XPO 中有一个虚拟 OnSaving() 方法。我应该覆盖它并添加您的代码吗?但是如果有人将 'PreferredContactMethod' 显式设置为 null,您的代码将覆盖它...
  • 没错,因此您需要针对这种情况进行额外控制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-07
相关资源
最近更新 更多