2012-10-08 19 views
1

我在写一个WCF服务以从Active Directory返回有关某个人的信息。除了返回该人的详细信息外,我还希望它返回其经理的用户名和全名。WCF数据与对象图中的分层数据合同

我开始编码这是...

[DataContract] 
public class ADPerson 
{ 
    Guid objectGuid; 
    Guid managerObjectGuid; 
    string username; 
    string displayname; 

    [DataMember] 
    public string Username 
    { 
     get { return this.username; } 
     set { this.username = value; } 
    } 
    [DataMember] 
    public string DisplayName 
    { 
     get { return this.displayName; } 
     set { this.displayName = value; } 
    } 
    [DataMember] 
    public ADPerson Manager 
    { 
     get { return new ADPerson(this.managerObjectGuid); } 
     set { this.managerObjectGuid = value.objectGuid; } 
    } 

    /* ... */ 

} 

...但后来意识到这没有停止条件;即它将遍历对象图直到它到达没有定义管理者的用户(即CEO)。

有没有一种很好的方法可以使这个停止条件到位,同时仍然能够重用ADPerson类,或者我是否需要提供另一种获取管理器细节的方法(例如,将这些细节设置为可见到他们自己的领域并从Manager属性中删除DataMember,或者创建一个ADManager类,它提供了ADPerson字段的子集,而不是经理的经理?

这是解决问题的另一种情况,很简单,但知道问题的最佳解决办法是让我烦恼

在此先感谢,

JB

+1

将所有的经理人包括在内,并不是最差的包含模式。它应该导致可接受的数字。 –

+0

的确,在最糟糕的情况下,深度可能只有20人左右,但我喜欢将事情保持得相对紧张(即拥有80%的回报,因为冗余信息并不理想 - 我宁愿只是提出要求雇员和他们的经理如果可能的话)。 – JohnLBevan

回答

1

在我看来,根据给出的信息,最好的办法是让属性,你想手头上的序列化的类可见,并从管理工具中删除数据成员的属性,就像这样:

[DataContract] 
public class ADPerson 
{ 
    Guid objectGuid; 
    Guid managerObjectGuid; 
    string username; 
    string displayname; 

    [DataMember] 
    public string Username 
    { 
     get { return this.username; } 
     set { this.username = value; } 
    } 
    [DataMember] 
    public string DisplayName 
    { 
     get { return this.displayName; } 
     set { this.displayName = value; } 
    } 
    public ADPerson Manager 
    { 
     get { return new ADPerson(this.managerObjectGuid); } 
     set { this.managerObjectGuid = value.objectGuid; } 
    } 
    [DataMember] 
    public string ManagerUsername 
    { 
     get { return this.Manager.Username; } 
    } 
    [DataMember] 
    public string ManagerName 
    { 
     get { return this.Manager.DisplayName; } 
    } 
} 

如果你不想要他们,他们甚至不必是public

+0

感谢迈克 - 这符合我最初的假设/合理。 – JohnLBevan

+0

@JohnLBevan,我很高兴我可以帮忙! –

2

使用继承在XML势必会导致混乱,考虑到循环引用(“员工A有管理者B,打印管理者B你要打印他的就业者,其中之一是员工A. ..“)。

此代码表明,使用DataContractSerializer的,这是不行的:

[ServiceContract] 
public class NestedDataService 
{ 
    [OperationContract] 
    public Person FindPerson() 
    { 
     var person = new Person { Name = "E.M. Ployee" }; 
     var manager = new Person { Name = "M.A. Nager" }; 

     manager.Employees = new List<Person>(); 
     manager.Employees.Add(person); 

     person.Manager = manager; 

     return person; 
    } 
} 

[DataContract] 
public class Person 
{ 
    [DataMember] 
    public String Name { get; set; } 

    [DataMember] 
    public Person Manager { get; set; } 

    [DataMember] 
    public List<Person> Employees { get; set; } 
} 

我会用从公元一些(?)G/UUID和他们toghether在重新链接客户端使用该ID。然后,员工A不会有public ADPerson Manager属性了(或至少不至于串行而言),但public UUID ManagerID可以这样实现:

public UUID ManagerID 
{ 
    get 
     { 
      return Manager != null ? Manager.UUID : null; 
     } 
} 

这限制了您在返回一个人,因为如果有人与被请求的人有关的话,你必须发送一个ADPersons的清单,以便能够查看他们。

+0

任何好的串行器都会处理没有问题的周期。 –

+0

@HenkHolterman我已经遇到了这个问题几次。看到编辑的问题。显示的代码将(至少在默认设置下)在无限循环时中断XmlSerializer和DataContractSerializer。 – CodeCaster

+0

有意义,但这意味着多个WCF电话 - 即一个获得个人,一个获得他们的经理。由于网络是最慢的部分,我希望能够减少通话次数。或者,如果从一次调用中返回一个对象列表(即将序列化作为一个层次结构,我会顺序返回所有人,然后将它们绑定到客户端代码中),那么我需要放入交替逻辑来选择记录I感兴趣,这似乎增加了复杂性? – JohnLBevan