【问题标题】:C# Pattern for abstract class specific code抽象类特定代码的 C# 模式
【发布时间】:2011-06-23 20:05:14
【问题描述】:

我有一个抽象的“Action”类,它具有 ActionAppointment、ActionCall、ActionEmail 和 ActionLetter 的派生类型。我正在尝试编写一个函数来干掉我们的服务层,因此我们不再编写 5 次 CRUD 调用。

我在我们的服务层中有一些更新逻辑(为简洁起见,删除了许多其他代码):

private IServiceResponse UpdateAction<T>(T action, string originalActionStatus) where T : Action
{
        if (action.GetType() == typeof(Action))
        {
            _actionRepository.Update(action);
        }
        else if (action.GetType() == typeof(ActionAppointment))
        {
            _actionAppointmentRepository.Update(action as ActionAppointment);
        }
        else if (action.GetType() == typeof(ActionCall))
        {
            _actionCallRepository.Update(action as ActionCall);
        }
        else if (action.GetType() == typeof(ActionEmail))
        {
            _actionEmailRepository.Update(action as ActionEmail);
        }
        else if (action.GetType() == typeof(ActionLetter))
        {
            _actionLetterRepository.Update(action as ActionLetter);
        }
}

不幸的是,我们的存储库是如何设置的,我必须使用专门命名的存储库(即,我无法通过 _actionRepository 更新 ActionLetter,即使它派生自 Action)

我一直在阅读不同的模式,这听起来类似于工厂模式,但我不知道如何使它工作。

我错过了什么愚蠢的东西吗?

【问题讨论】:

  • 您可以考虑 Visitor 模式 (en.wikipedia.org/wiki/Visitor_pattern)。
  • 是的,工厂模式是一种解决方案。您的存储库必须具有公共基类或实现接口。它们都必须有一个 Update 方法,该方法接受类型为 Action 的对象。工厂接受类型作为参数(以任何形式、名称、类型、枚举,如果可用)并返回正确的存储库。差不多就是这样。关于如何实现 Factory 是否有具体的混淆点?
  • 我不确定如何为此实现工厂模式,因为 IRepository 是基于每个域模型对象的通用模式。
  • 抱歉回复慢。工厂不适用于泛型,它们不是类型多态的。泛型基于参数多态性。它是一种功能范围多态性。工厂需要类范围多态性。除了基本更新等的更多类型安全性之外,我不确定我是否了解您从这个设计中得到了什么?我使用 nHibernate 无论如何它都有一个无类型的更新。我选择了一个带有通用更新的基础 Repository 类,并添加了一些最少的类型——我所有的持久对象都有一个通用的基类,所以我不能将例如网络类型作为对持久无效的对象传递。

标签: c# design-patterns repository-pattern


【解决方案1】:

您不能为每种操作类型编写该方法的重载吗?忘记 &lt;T&gt;typeof 的东西 - 你正在做的是手动实现一个内置的语言特性(方法重载),而且方式也很脆弱。

【讨论】:

  • 是的,这正是多态性和继承的意义所在。
  • 该代码以前是作为每个 Action 类型的方法编写的。我只是想把它干掉一些,但我想也许我可以干掉一些共享组件,但每个组件都有特定的存储库代码。
  • @Matt:你的 if-else 装置不会让代码变得 DRYer,这是肯定的。
【解决方案2】:

我们把这里的逻辑反过来:

abstract class Action {
    protected abstract Repository GetRepository();
    protected void Update(){
       this.GetRepository().Update(this);
    }
}

您所要做的就是在每个派生类中覆盖 GetRepository。例如:

class ActionAppointment : Action {
    protected override Repository GetRepository() {
        return _actionAppointmentRepository;
    }
}

【讨论】:

  • 让模型类了解其存储方式并不是一个好主意。
  • -1,将服务(甚至存储库)注入域对象是一种不好的做法。
  • 同意 smartcaveman。拥有这种类型的依赖关系违反了我们的规则。
猜你喜欢
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-02
  • 1970-01-01
相关资源
最近更新 更多