根据输入请求C#设计WCF服务响应属性的动态分组

时间:2018-12-01 05:46:33

标签: c# wcf design-patterns

下面是我的Web服务的响应和等效服务合同的示例格式。

<Players>
 <Player>
     <Name>Sachin</Name>
     <Sport>Cricket</Sport>
     <SportType>Team Game</SportType>
 </Player>
 <Player>
     <Name>Ronaldo</Name>
     <Sport>Football</Sport>
     <SportType>Team Game</SportType>
 </Player>
 <Player>
     <Name>Alfred</Name>
     <Sport>Shooting</Sport>
     <SportType>Individual</SportType>
 </Player>
</Players>

现在,UI团队正在寻求新功能,他们希望在这些功能中对服务中不同字段进行分组逻辑。例如,在新暴露的“ groupBy”字段中的输入请求中,他们可以发送可以发送字段名称“ Sport”,然后他们希望以“ Sport”分组的Player元素作为响应,并且“ SportType”也可以。

<SportTypes>
    <SportType>
        <Type>Team Game</Type>
        <Players>
            <Player>
                <Name>Sachin</Name>
                <Sport>Cricket</Sport>
            </Player>
            <Player>
                <Name>Ronaldo</Name>
                <Sport>Football</Sport>
            </Player>
        </Players>
    </SportType>
    <SportType>
        <Type>Individual</Type>
        <Players>
            <Name>Alfred</Name>
            <Sport>Shooting</Sport>
        </Players>
    </SportType>
</SportTypes>

从数据库中检索字段后,对字段进行分组没有问题,但是我不知道如何为动态服务响应定义服务协定,因为响应结构会在分组后发生变化。出于某些非常奇怪(也许很愚蠢)的原因UI团队不想进行此分组,因此必须在服务中完成。 也许我以错误的方式解决了这个问题。感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

我认为您应该使用CollectionDataContract更改数据合同。 例如,

 [DataContract]
public  class Player
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public string Sport { get; set; }
}
[DataContract]
public class SportType
{
    [DataMember]
    public string Type { get; set; }
    [DataMember]
    public List<Player> Players { get; set; }
}
              // name is the root xml element, itemName is the name of item xml element
[CollectionDataContract(Name = "SportTypes", ItemName = "SportType")]
public class SportTypeCollection : IEnumerable<SportType>
{
    public IList<SportType> SportTypes { get;private set; }
    public IEnumerator<SportType> GetEnumerator()
    {
        return this.SportTypes.GetEnumerator();
    }
    public SportTypeCollection(params SportType[] sportTypes)
    {
        if (null == sportTypes)
        {
            this.SportTypes = new List<SportType>();
        }
        else
        {
            this.SportTypes = sportTypes;
        }
    }
    public SportTypeCollection()
    {
        this.SportTypes = new List<SportType>();
    }
    public void Add(SportType sportType)
    {
        this.SportTypes.Add(sportType);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.SportTypes.GetEnumerator();
    }
}

我的测试。

 static void Main(string[] args)
    {
        SportTypeCollection sportTypes = new SportTypeCollection();
        sportTypes.Add(new SportType { Type = "a", Players = new List<Player> { new Player { Name = "p", Sport = "s" } } });
        sportTypes.Add(new SportType { Type = "b", Players = new List<Player> { new Player { Name = "p", Sport = "v" } } });
        Serialize<SportTypeCollection>(sportTypes, "d:\\message.xml", null, null);
    }
    public static void Serialize<T>(T instance, string fileName, IDataContractSurrogate dataContractSurrogate, params Type[] knownTypes)
    {



        DataContractSerializer serializer = new DataContractSerializer(typeof(T), knownTypes, int.MaxValue, false, false, dataContractSurrogate);
        using (XmlWriter writer = new XmlTextWriter(fileName, Encoding.UTF8))
        {
            serializer.WriteObject(writer, instance);
        }
        Process.Start(fileName);
    }

结果。

<SportTypes xmlns:i="http://www.w3.org/2001/XMLSchema-instance"           xmlns="http://schemas.datacontract.org/2004/07/ServiceInterface.Models">
<SportType>
<Players>
<Player><Name>p</Name><Sport>s</Sport></Player>
</Players>
<Type>a</Type>
</SportType>

<SportType>
<Players>
<Player><Name>p</Name><Sport>v</Sport></Player>
</Players>
<Type>b</Type>
</SportType>
</SportTypes>

答案 1 :(得分:0)

我找到了方法。 基本上,我创建了一个通用的嵌套实体,该实体根据Player实体动态地对玩家实体进行分组。

<Group>
   <Type>SportType</Type>
   <Value>TeamGame</Value>
   <GroupSummary/> <!-- Aggregation summary of group -->
   <Group>
       <Type>Sport</Type>
       <Value>Cricket</Value>
       <ListOfEntities>
          <Player1/>
          <Player2/>
       </ListOfEntities>
       <Group/>
    <Group/>
    <ListOfEntites/>
<Group/>

然后,我们可以使用this答案中存在的GroupBy编写简单递归调用来创建嵌套的分组实体