【问题标题】:2 objects, exactly the same (except namespace) c#2个对象,完全相同(命名空间除外)c#
【发布时间】:2011-04-16 20:57:06
【问题描述】:

我正在使用第 3 方的一组 Web 服务,但遇到了一个小问题。在我手动创建将每个属性从源复制到目标的方法之前,我想我会在这里寻求更好的解决方案。

我有 2 个对象,一个是 Customer.CustomerParty 类型,一个是 Appointment.CustomerParty 类型。 CustomerParty 对象实际上是完全一样的属性和子对象。但我不能从 1 转换到另一个。

所以,我需要从网络服务中找到某个人。我可以通过调用 Customer.FindCustomer(customerID) 来做到这一点,它会返回一个 Customer.CustomerParty 对象。

我需要找到我找到的那个人,然后在“CreateAppointment”请求中使用他们几行。 Appointment.CreateAppointment 接受一个约会对象,该约会对象包含一个 CustomerParty 对象。

但是,它想要的 CustomerParty 对象实际上是 Appointment.CustomerParty。我有一个 Customer.CustomerParty。

明白我的意思了吗?有什么建议吗?

【问题讨论】:

  • 因为类来自不同的命名空间,这意味着从 CLR 的角度来看它们完全不同。这就是为什么你不能从另一个中投射一个。

标签: c# namespaces casting


【解决方案1】:

映射类型的一种简单且非常快速的方法是使用 MiscUtil 库中的 PropertyCopy<TTarget>.CopyFrom<TSource>(TSource source) 方法,如 here 所述:

using MiscUtil.Reflection;

class A
{
    public int Foo { get; set; }
}

class B
{
    public int Foo { get; set; }
}

class Program
{
    static void Main()
    {
        A a = new A();
        a.Foo = 17;
        B b = PropertyCopy<B>.CopyFrom(a);

        bool success = b.Foo == 17; // success is true;
    }
}

【讨论】:

    【解决方案2】:

    您是否考虑过将 转换运算符 添加到域类之一以定义显式强制转换。 See the msdn documentation here.

    享受吧!

    【讨论】:

      【解决方案3】:

      这种情况在编写域模式时很常见。您基本上需要在两个对象之间编写域转换器。您可以通过多种方式执行此操作,但我建议在目标类型中使用重写的构造函数(或静态方法),该构造函数采用服务类型并执行映射。由于它们是两种 CLR 类型,因此不能直接从一种转换为另一种。您需要逐个成员复制。

      public class ClientType
      {
          public string FieldOne { get; set; }
          public string FieldTwo { get; set; }
      
          public ClientType()
          {
          }
      
          public ClientType( ServiceType serviceType )
          {
              this.FieldOne = serviceType.FieldOne;
              this.FieldTwo = serviceType.FieldTwo;
          }
      }
      

      或者

      public static class DomainTranslator
      {
          public static ServiceType Translate( ClientType type )
          {
              return new ServiceType { FieldOne = type.FieldOne, FieldTwo = type.FieldTwo };
          }
      }
      

      【讨论】:

      • 我想我将不得不走这条路。 :( 感谢您的回答。不幸的是,StackOverflow 不会让我对您的帖子进行投票。OpenID 在我的工作计算机上的 StackOverflow 上不起作用——其他 openid 网站可以,只是 StackOverlow 不行。
      • @Matt:你应该知道有一些简单的方法,比如动态方法,不需要你自己编写映射代码。
      • 您也可以覆盖显式转换。
      • @JordanParmer 我认为这几乎是最糟糕的解决方案。虽然在浅表情况下可行,1 个类包含 2 个属性 - 正如您所展示的那样,在任何更复杂的(即“现实生活”)场景中,它都是绝对可憎的。
      • @ver - 您提出了哪些替代方案?我同意 AutoMapper 是一个不错的解决方案,但只有在保证属性相同的情况下才会简单。当您将单个域连接到多个持久源时,情况并非总是如此。我的方法(虽然简单)是明确的,几乎没有混淆的余地。
      【解决方案4】:

      在两个不同的命名空间中具有完全相同签名的两个类是两个不同的类。如果它们没有明确说明如何使用隐式或显式运算符将它们从一个转换为另一个,您将无法在它们之间进行隐式转换。

      您可以通过序列化来做一些事情。一侧的 WCF DataContract 类不必与另一侧的 DataContract 具有完全相同的类型;它们只需要具有相同的签名并进行相同的装饰即可。如果您的两个对象都是这样,您可以使用 DataContractSerializer 通过它们的 DataContract 装饰来“转换”类型。

      如果您可以控制一个类或另一个类的实现,您还可以定义一个隐式或显式运算符,该运算符将定义如何将另一个类转换为您的类。这可能会简单地返回您类型中另一个对象的深层副本的新引用。因为是这种情况,所以我将其定义为显式,以确保仅在您需要时执行转换(它将在您显式转换的情况下使用,例如 myAppCustomer = (Appointment.CustomerParty)myCustCustomer;)。

      即使您不控制任何一个类,您也可以编写扩展方法或第三个类来执行此转换。

      【讨论】:

        【解决方案5】:

        为什么不使用AutoMapper?然后你可以这样做:

        TheirCustomerPartyClass source = WebService.ItsPartyTime();
        
        YourCustomerPartyClass converted = 
            Mapper.Map<TheirCustomerPartyClass, YourCustomerPartyClass>(source);
        
        TheirCustomerPartyClass original = 
            Mapper.Map<YourCustomerPartyClass, TheirCustomerPartyClass>(converted);
        

        只要属性相同,您就可以像这样创建一个非常简单的地图:

        Mapper.CreateMap<TheirCustomerPartyClass, YourCustomerPartyClass>();
        Mapper.CreateMap<YourCustomerPartyClass, TheirCustomerPartyClass>();
        

        【讨论】:

        • 我会看看我们是否可以将它添加到我们的项目中。不确定此时是否值得开销,但感谢您的建议。我相信它会解决我的问题。不幸的是,StackOverflow 不会让我为你的帖子投票。 OpenID 在我的工作计算机上的 StackOverflow 上不起作用——其他 openid 网站可以,只是 StackOverlow 不行。
        • @Matt - 几乎没有开销。 AutoMapper 非常轻量级。绝对值得一试。
        • 对我来说效果很好。 Mapper.CreateMap(); Entities.CorporateDelayTracking.Delay convertDelay = Mapper.Map(delay);
        【解决方案6】:

        我正在使用第 3 方的 网络服务...

        假设您无法修改类,我不知道您可以通过任何方式更改转换行为。至少,没有办法比编写 CustomerToAppointmentPartyTranslator() 映射函数复杂得多...... :)

        假设您使用的是最新版本的 C#(我相信是 3.5?),这可能是 extension method 的一个很好的候选者。

        【讨论】:

          猜你喜欢
          • 2017-08-09
          • 1970-01-01
          • 2016-09-16
          • 1970-01-01
          • 1970-01-01
          • 2011-03-18
          • 2012-05-15
          • 1970-01-01
          • 2013-08-14
          相关资源
          最近更新 更多