【问题标题】:Translating one object to another via an extension method - looking for alternate solutions通过扩展方法将一个对象转换为另一个对象 - 寻找替代解决方案
【发布时间】:2011-08-15 00:14:12
【问题描述】:

这可能是一个奇怪的问题,而我现在所拥有的东西现在可以工作,但我觉得有点奇怪,我想知道这是因为设计/架构糟糕。如有任何想法,我们将不胜感激。

最初的设计是在我从别人那里继承的代码库中。我们有一个 linq-to-sql 类(在 dbml 的设计器文件中自动生成)。


[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.ARCustomers")]
public partial class ARCustomer : INotifyPropertyChanging, INotifyPropertyChanged
{
    // variables
    // extensibility method defs
    // ctor
    // properties
    // etc.
}

然后是另一个名为ArCustomer(注意小写“r”)的类类,它是自动生成类的扩展版本。当我说扩展时,我的意思是它具有 LINQ 类的所有属性,再加上一些需要一些逻辑来填充的属性。

在代码中有很多地方我们想要将ARCustomer 转换为ArCustomer。所以我在ArCustomer 类上写了一个扩展方法(这感觉很奇怪)。


public static ArCustomer FromDatacontextObject(this ArCustomer customer, ARCustomer datacontextObject)
{
    var arCustomer = new ArCustomer();
    arCustomer.Id = datacontextObject.ProjectID;
    // more of the same

    // now populate the other fields that don't exist on the datacontextObject

    return arCustomer;
}

就是这么称呼的。


var customerfromDb = accountReceivableRepository.GetCurCustomer(arId);
ArCustomer customer = new ArCustomer();
customer = customer.FromDatacontextObject(customerfromDb);

这对我来说感觉不对,但我不知道有什么更好的选择。 (包含扩展属性的部分类会起作用吗?将它们填充到它的构造函数中?)或者也许它很好......我对一些东西感兴趣......

  1. 我觉得这是错误的/奇怪的/不好的吗?
  2. 具体来说,我实施的解决方案有哪些缺点?我觉得其中一个原因是我经常挠头,试图区分这两个类并弄清楚哪个是哪个。
  3. 他们有什么优点吗?
  4. 有更好的解决方案(以及为什么更好)?

(不相关-我希望这种问题对于堆栈溢出是可以的。我几乎觉得我在要求进行迷你代码审查,这可能是主观的;另一方面,我试图问一些具体的问题和觉得我一定不是唯一遇到这种情况的开发人员(“我有一个对象,需要把它变成另一个对象”),所以希望通过让线程保持打开状态能有所收获)。

谢谢大家!

【问题讨论】:

    标签: c# linq-to-sql architecture extension-methods object-model


    【解决方案1】:

    你的直觉很适合你。

    C# 编译器在技术上允许有两个具有相同名称的类(仅区分大小写),但这是一个坏主意。此外,它不符合 CLS。

    由于您已经陈述的确切原因,这是一个坏主意:可读性。不要低估可读性的重要性。就个人而言,这是我衡量代码质量的第一标准。可读的代码往往有更少的错误,并且更容易调试/维护。

    LINQ to SQL 生成的类已经是部分类。您可以添加一个单独的代码文件来定义您想要的任何额外部分。而且,这是完成您所描述的内容的首选方法。更容易维护和理解。

    或者,您可以创建一个包含 ARCustomer 的“ViewModel”类。 (这取决于您的架构)。

    【讨论】:

      【解决方案2】:

      如果您更改扩展方法以扩展数据库对象,您将拥有更自然的 API IMO

      public static ArCustomer ToDomainObject(this ARCustomer datacontextObject)
      {
         var arCustomer = new ArCustomer();
         arCustomer.Id = datacontextObject.ProjectID;
         // more of the same
      
         // now populate the other fields that don't exist on the datacontextObject
      
         return arCustomer;
      }
      

      那么数据访问代码如下所示

      var customerfromDb = accountReceivableRepository.GetCurCustomer(arId);
      ArCustomer customer = customerfromDb.ToDomainObject();
      

      【讨论】:

        【解决方案3】:

        几天前我遇到了同样的问题。我确实找到了一些关于这个话题的讨论。 这些线程可能会有所帮助:Thread one、Thread two

        正如我所知道的,没有更好的方法来做你正在做的事情。但是,您可以尝试使用反射来遍历父对象中的所有字段,以将它们复制到子对象中的相关字段。 Some example code here,And discussion here。

        对于我的问题,最终手动逐个字段地进行,因为我需要深度克隆的一些字段,一些只能通过引用复制。

        【讨论】:

          猜你喜欢
          • 2016-06-04
          • 2021-10-30
          • 2021-08-14
          • 1970-01-01
          • 2021-09-22
          • 1970-01-01
          • 1970-01-01
          • 2017-10-15
          • 1970-01-01
          相关资源
          最近更新 更多