Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对象引用用作客户端和WCF服务器上字典中的键_C#_.net - Fatal编程技术网

C# 对象引用用作客户端和WCF服务器上字典中的键

C# 对象引用用作客户端和WCF服务器上字典中的键,c#,.net,C#,.net,我正在使用WCF编写客户机和服务,但是我怀疑目前存在多个问题 从下面的代码中可以看到,流程如下:客户机请求一些数据,服务生成这些数据并在DTO对象中返回。然后,客户端尝试在返回的字典中进行查找,但这会引发KeyNotFoundException 此外,在此之前,服务器上的测试失败(如果未注释),因为输入参数列表AllBranchs不再包含Branch currentBranch,它在方法调用的客户端执行了此操作 有人能告诉我这段代码中发生了什么,以及为什么它首先在服务器端爆炸,然后在客户端爆炸

我正在使用WCF编写客户机和服务,但是我怀疑目前存在多个问题

从下面的代码中可以看到,流程如下:客户机请求一些数据,服务生成这些数据并在DTO对象中返回。然后,客户端尝试在返回的字典中进行查找,但这会引发KeyNotFoundException

此外,在此之前,服务器上的测试失败(如果未注释),因为输入参数列表AllBranchs不再包含Branch currentBranch,它在方法调用的客户端执行了此操作

有人能告诉我这段代码中发生了什么,以及为什么它首先在服务器端爆炸,然后在客户端爆炸

Shared class definitions
------------------------

[DataContract(IsReference = true)]
public class Branch
{
    public Branch(int branchId, string name)
    {
        BranchId = branchId;
        Name = name;
    }

    [DataMember]
    public int BranchId { get; set; }

    [DataMember]
    public string Name { get; set; }
}

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

    // a few other properties, both primitives and complex objects
}

[DataContract]
public class MyDto
{
    [DataMember]
    public IDictionary<Branch, List<Department>> DepartmentsByBranch { get; set; }

    [DataMember]
    public Branch CurrentBranch { get; set; }

    // lots of other properties, both primitives and complex objects
}

Server-side
--------------------------------
public CreateData(List<Branch> allBranches, Branch currentBranch)
{
    // BOOM: On the server side, currentBranch is no longer contained in allBranches (presumably due to serialization and deserialization)
    if (!branches.Contains(branchToOpen))
    {
        throw new ArgumentException("allBranches no longer contain currentBranch!");
    }

    // Therefore, I should probably not do the following, expecting to use currentBranch as a key in departmentsByBranch later on
    var departmentsByBranch = branches.ToDictionary(branch => branch, branch => new List<Department>());

    return new MyDto
    {
        DepartmentsByBranch = departmentsByBranch,
        CurrentBranch = departmentsByBranch,
    };
}

Client-side (relevant code only)
--------------------------------
var service = new ServiceProxy();   // using a binding defined in app.config

var allBranches = new List<Branch>
{
    new Branch(0, "First branch"),
    new Branch(1, "Second branch"),
    // etc...
};
var currentBranch = allBranches[0];

MyDto dto = service.CreateData(allBranches, currentBranch);

var currentDepartments = dto.DepartmentsByBranch[currentBranch];    // BOOM: Generates KeyNotFoundException

代码失败的原因是您的客户端中有两个独立的
分支
实例:一个是您在本地创建的(
currentBranch
),另一个是从服务器接收并由WCF隐式创建的(在
dto.DepartmentsByBranch
内部)。您没有指定这两个实例是“同一件事”,因此就词典而言,它从未见过您所谈论的
currentBranch

您需要为
Branch
提供
IEquatable
的正确实现,这同样适用于用作字典键的所有类

请注意,“适当实施”

如果您实现了
IEquatable
,您还应该覆盖基 类
Object.Equals(Object)
GetHashCode
的实现,以便 他们的行为与
IEquatable.Equals的行为一致
方法


客户端和服务器在不同的机器上运行,它们不共享内存。客户机上的引用始终与服务器上的任何引用不同。@JohnSaunders是的,我意识到了这一点,但我(天真地)希望当执行在服务器上输入CreateData时,WCF会确保currentBranch仍然是与AllBranchs中的一个元素相同的对象。。。我觉得很傻。Jons在下面的回答确保Branch.Equals不再测试引用相等,而是我自己版本的Equals(它只是测试属性相等)。谢谢你的提示!为什么不在DataContract属性中简单地使用IsReference来避免服务器上CreateData中的ArgumentException?@larslovlie:该属性确定序列化程序的功能(它将为每个序列化的图形创建一个对象实例)。它不会(也不能)让序列化程序意识到应用程序内存中已经存在一个等效实例,并与之协调。
public bool Equals(Branch other)
    {
        return other != null && ((BranchId == other.BranchId) && (Name == other.Name));
    }