我有两个web服务,一个是GetCatDetails,另一个是GetDogDetails。
他们返回一个CatDetails和一个DogDetails对象。
两个对象都是相同的,除了名称之外,这些类是相同的,因为它们使用相同的数据库。
Web服务查询数据库,检索详细信息,填充所有字段并返回对象。
我是否故意将web服务设计为返回不同的对象而不是AnimalDetails。
不是复制和粘贴这个逻辑,有没有办法将一个转换为另一个?通常我会使用基类来解决这个问题,但我不希望它影响Web服务的WSDL,因为基类可能会混淆它。
有什么想法吗?也许有一种偷偷摸摸的作弊方式,因为除了名字之外它们几乎完全相同。
答案 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
{ }
然后您仍然可以拥有不同的GetDogDetails
和GetCatDetails
网络服务,同时共享一些代码来填充对象:
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)
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);
}
}