当两个类相同时,是否可以将对象转换为另一个对象?

时间:2013-12-05 12:45:05

标签: c#

我有两个web服务,一个是GetCatDetails,另一个是GetDogDetails。

他们返回一个CatDetails和一个DogDetails对象。

两个对象都是相同的,除了名称之外,这些类是相同的,因为它们使用相同的数据库。

Web服务查询数据库,检索详细信息,填充所有字段并返回对象。

我是否故意将web服务设计为返回不同的对象而不是AnimalDetails。

不是复制和粘贴这个逻辑,有没有办法将一个转换为另一个?通常我会使用基类来解决这个问题,但我不希望它影响Web服务的WSDL,因为基类可能会混淆它。

有什么想法吗?也许有一种偷偷摸摸的作弊方式,因为除了名字之外它们几乎完全相同。

3 个答案:

答案 0 :(得分:3)

不,不同的类表示不同的类型,即使它们具有相同的内容。您应该在此处使用类型层次结构,并在顶部包含AnimalDetails,其中包含所有共享数据。

您仍然可以在共享代码构建它们时从Web服务返回特殊类型。例如,请考虑以下类型定义:

class AnimalDetails
{
    public string Name
    { get; set; }
    public float Height
    { get; set; }
    public float Weight
    { get; set; }
}

class DogDetails : AnimalDetails
{ }
class CatDetails : AnimalDetails
{ }

然后您仍然可以拥有不同的GetDogDetailsGetCatDetails网络服务,同时共享一些代码来填充对象:

public DogDetails GetDogDetails (int id)
{
    DogDetails dog = new DogDetails();
    QueryFromDatabase(dog, id);
    return dog;
}

public CatDetails GetCatDetails (int id)
{
    CatDetails cat = new CatDetails();
    QueryFromDatabase(cat, id);
    return cat;
}

private void QueryFromDatabase (AnimalDetails animal, int id)
{
    // fetch from database, and fill the animal object with the values
    var databaseData = FetchObject(id);
    animal.Name = databaseData.GetString("name");
    animal.Height = databaseData.GetFloat("height");
    animal.Weight = databaseData.GetFloat("weight");
}

答案 1 :(得分:2)

您可以使用AutoMapper复制两个类的实例之间的值。由于AutoMapper使用基于约定的规则,因此您可以编写很少的代码。

  

AutoMapper是一个简单的小型库,用于欺骗性地解决问题   复杂的问题 - 摆脱映射一个对象的代码   另一个。这种类型的代码相当沉闷,写起来很无聊,所以   为什么不为我们发明一个工具?

答案 2 :(得分:1)

SLC - 我感觉到你的痛苦。我最近经历了相同的思考过程,引用Web服务无法共享相同的类定义,即使它们相同但名称相同。我倾向于使用“添加服务引用”向导智能地识别出我的代码库中有一个共同的类,它适合于目的而不是复制它。我很想知道是否有办法让这个广告宣传起来。定义类层次结构对我来说也不是一个可行的解决方案 - 特别是因为我希望能够使用服务引用添加的代理类,并保留能够在不破坏代码的情况下自动更新此引用的优点。 Pengu 提到我最后使用的策略,因为我已经在使用XML序列化,所以我只是将一个新方法添加到我放在一起的XmlHelper类中。相关方法称为Reincarnate。例如,如果要将Cat类型的cat转换为Dog类型的狗,则代码为:

Dog dog = XmlHelper.Reincarnate<Cat, Dog>
                    (cat, defaultNamespace: "http://namespace");

我已经在下面包含了助手类的相关方法。我希望你觉得它很有用:

 public class XmlHelper
 {

    public static string SerializeToXmlString<T>(T objectToSerialize, Dictionary<string, string> xmlNamespaces = null,
        string defaultNamespace = null)
    {
        StringBuilder xmlStringBuilder = new StringBuilder();
        XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
        xmlWriterSettings.OmitXmlDeclaration = true;
        xmlWriterSettings.Indent = true;
        using (XmlWriter xmlWriter = XmlWriter.Create(xmlStringBuilder, xmlWriterSettings))
        {
            var xmlSerializerNamespaces = new XmlSerializerNamespaces();
            if (xmlNamespaces != null)
            {
                foreach (var xmlNamespace in xmlNamespaces)
                {
                    xmlSerializerNamespaces.Add(xmlNamespace.Key, xmlNamespace.Value);
                }
            }
            var xmlSerializer = new XmlSerializer(typeof(T));
            if (defaultNamespace != null)
                xmlSerializer = new XmlSerializer(typeof(T), defaultNamespace);
            xmlSerializer.Serialize(xmlWriter, objectToSerialize, xmlSerializerNamespaces);
        }
        return xmlStringBuilder.ToString();
    }

    public static T Deserialize<T>(string xmlText, string defaultNamespace) where T : class
    {
        using (StringReader stringReader = new StringReader(xmlText))
        {
            XmlReader xmlReader = XmlReader.Create(stringReader);
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), defaultNamespace);
            return xmlSerializer.Deserialize(xmlReader) as T;
        }
    }

    /// <summary>
    /// Convert one object type to another which has a consistent serialization.
    /// </summary>
    /// <typeparam name="T">Source Class</typeparam>
    /// <typeparam name="U">Target Class</typeparam>
    /// <param name="objectToReIncarnate">Source Object of Class Type T</param>
    /// <param name="xmlNamespaces">Namespace mappings to add to serialization, if required</param>
    /// <param name="defaultNamespace">Default namespace of serialized class</param>
    /// <returns>Target Object of Class Type U</returns>
    public static U Reincarnate<T,U>(T objectToReIncarnate, Dictionary<string, string> xmlNamespaces = null,
        string defaultNamespace = null) where U : class 
    {
        string serializedObject = SerializeToXmlString(objectToReIncarnate, xmlNamespaces, defaultNamespace);
        return Deserialize<U>(serializedObject, defaultNamespace);
    }

}
相关问题