对象图中具有分层数据的WCF数据协定

时间:2012-10-08 12:45:37

标签: c# wcf hierarchical-data datacontract datamember

我正在编写WCF服务以从Active Directory返回有关某人的信息。除了返回此人的详细信息,我还希望它返回其经理的用户名和全名。

我开始将其编码为:...

[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

2 个答案:

答案 0 :(得分: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; }
}

我会使用AD中的一些()G / UUID,并使用该ID将它们重新链接到客户端。然后,员工A将不再具有public ADPerson Manager属性(或者至少不会与序列化程序相关),但public UUID ManagerID可以像这样实现:

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

这限制了您返回一个人,因为如果有人与所请求的人相关,您将不得不发送ADPersons的列表,以便能够查找它们。

答案 1 :(得分:1)

在我看来,根据给出的信息,最好的解决方案是让您想要序列化的属性在手头的类中可见,并从管理器中删除DataMember属性,如下所示:

[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