C# "can't specify constructor/static method in interface"问题所需的正确解决方案



好的,我需要一些帮助。

这是同一个古老的"不能使用接口来强制构造函数/静态方法">问题。

那么什么是正确的OO设计

我有一组数据实体(实体框架的东西(,我为它们编写了部分类方法来转换为XML(XElement对象(。

我有一个实例方法;保存";XML:

// Convert entity to XML
public XElement ToXml() {}

并且我有一个构造函数;读取";XML:

// Create entity from XML constructor.
public MyEntity(XElement) {}

或者,我可以使用静态工厂方法来";读取";XML:

public static MyEntity ParseXml(XElement) {}

困境:

  1. 我可以创建一个接口;保存";ToXml()方法,但如果它只解决了一半的问题,那又有什么好处呢?接口不能强制执行";负载";方法。

  2. 我可以依靠我自己的良好意愿,在没有任何合同的情况下创建这些方法。

  3. 我可以创建一个静态类,其中填充了XmlToEntity1()XmlToEntity2()等冗余方法。(现在我已经描述了一个很好的"泛型"问题。(然而,特定的转换代码(特定于每个实体(会为每个实体创建单独的方法或切换/case,并且似乎属于实体类内部,而不是其他类中,不是吗?

如果一个经验丰富的C#编码器能够为这个常见问题展示出一个良好的设计,我想我会从中学到很多。

七月四日快乐!

可能的解决方案1

具有两个静态泛型方法的单个XmlSerializer类:

public static T Deserialize<T>(XElement xml) {}
public static XElement Serialize<T>(T entity) {}
  • Pro:只有一个类(不需要接口(
  • Pro:将序列化责任与实体类分离
  • Con:对于支持的每个实体类型,仍然需要单独的方法或开关/用例块
  • Con:?不可扩展——每次实体更改或添加/删除时都必须修改此类

可能吸取的教训

";不能为构造函数和静态方法使用接口&;问题可能是的症状

  1. 违反SRP(单一责任负责人(
  2. 违反SoC(关注分离(原则

使用一个简单的实例方法从XML加载怎么样?你的界面会是这样的:

public interface XmlSerializableEntity
{
   XElement Serialize(); // or ToXml() if you prefer..
   void Deserialize(XElement e); // or Load() or something like that..
}

或者你可以使用一个通用的解决方案:

public interface Serializable<T>
{
   T Serialize();
   void Deserialize(T e);
}

缺点是在加载实体对象之前必须对其进行初始化,这可能意味着对象将处于无效状态。但我相信这是一种常见的模式。

无论如何,将存储/检索与实体分离是一个很好的设计。在OO术语中,这可以称为单一责任原则。您的实体存在是出于某种目的(可能与您的域有关(。该实体的存储是一项单独的责任,可以独立于域进行更改。(例如,您可以从数据库、web服务或文件系统中检索它(。

当然,静态方法并不是唯一的方法。您可以在保存/检索级别创建一个接口,并为每个实体实现该接口。然后,您可以很容易地以通用的方式使用它们,而不必担心太多类型。

添加一些示例代码:

interface EntityGateway<TEntity> {
    TEntity Load(String id);
    void Save(TEntity entity);
}
public class XEntityGateway implements EntityGateway<XEntity> {
    XEntity Load(String id) { ... implementation details } 
    void Save(XEntity entity) { ... implementation details } 
}
XEntityGateway gw = new XEntityGateway();
XEntity entity = gw.Load("SOMEID");
// modify entity
gw.Save(entity);

相关内容

最新更新