2014-02-07 2 views
3

Скажет, у вас есть несколько классов, определенных какМожет ли WCF поддерживать ссылочное равенство по проводу?

[DataContract] 
public class Foo 
{ 
    [DataMember] 
    public List<Bar> Bars {get; set;} 
} 

[DataContract] 
public class Bar 
{ 
    [DataMember] 
    public string Baz { get; set; } 
} 

public class Service1 : IService1 
{ 
    public bool Send(Foo foo) 
    { 
     var bars = foo.Bars; 

     bars[0].Baz = "test2"; 
     return bars[0].Baz == bars[1].Baz; 
    } 
} 

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    bool Send(Foo composite); 
} 

Если предположить, что я использует WCF для WCF с общим контрактом данных DLL между клиентом и сервером, если я что-то вроде следующего

static void Main(string[] args) 
{ 
    using (var client = new ServiceReference.Service1Client()) 
    { 
     var bar = new Bar(); 
     bar.Baz = "Start"; 

     List<Bar> bars = new List<Bar>(); 
     bars.Add(bar); 
     bars.Add(bar); 

     var foo = new Foo(); 
     foo.Bars = bars; 

     Console.WriteLine(bars[0].Baz == bars[1].Baz); 

     bars[0].Baz = "test1"; 
     Console.WriteLine(bars[0].Baz == bars[1].Baz); 

     Console.WriteLine(client.Send(foo)); 

     Console.ReadLine(); 
    } 

} 

Я получаю True, True, False как мой результат, что означает, что bars[0] и bars[1] не указывали на тот же объект на сервере.

Я делаю что-то не так, или невозможно иметь общие ссылки на WCF?

ответ

4

Вы должны explicitly tell WCF to preserve references указав

[DataContract(IsReference = true)] 

иначе ссылки на равенство теряется в процессе строительства сообщения.

+0

Что мне нужно сделать, чтобы сделать код выше, используйте 'BinaryFormatter'? –

+0

Я не могу сказать, как использовать 'BinaryFormatter', не пробовав его сам. Но вы можете - если вы этого еще не сделали - попробуйте использовать «BinaryMessageEncoding», что также может сохранить ссылочное равенство, но я не знаю точно. –

+0

Я ошибся, это не сработает, потому что WCF сначала создает сообщение, а затем сериализует его с помощью указанного сериализатора. Но на данный момент ссылки уже потеряны по умолчанию, поэтому использование сериализатора, сохраняющего эталон, не поможет. Но решение по-прежнему существует, вы можете указать WCF сохранить ссылки при создании сообщения - см. Обновленный ответ. –

2

Аннотации DataContact указывают на сериализацию. То есть ваш объект сериализуется, передается по проводу, а затем повторно создается как новый объект на другом конце. Так что нет, невозможно поддерживать ссылочное равенство.

Обратите внимание, что, по-видимому, ваша служба WCF работает на другой машине или, по крайней мере, в другом процессе. Таким образом, служба WCF и клиент обычно не имеют доступа к одному и тому же пространству памяти, что означает, что обмен ссылками между ними теоретически непрактичен.

+0

Как вы это выражаете, я мог бы использовать что-то другое, кроме '[DataContract]', чтобы это сделать. Что мне нужно сделать вместо этого? EDIT: за последнее обновление я не забочусь о том, что клиент и сервер используют ссылку, все, что я хочу, - это два объекта, отправленных в одно и то же сообщение, чтобы по-прежнему показывать ссылочное равенство с другой стороны. –

+0

@ScottChamberlain нет, потому что он должен быть сериализован так или иначе - это единственный способ передать объект на другую сторону. – McGarnagle

+0

@ScottChamberlain по-другому, если не было сериализации, тогда WCF не понадобится - вы можете просто передать клиенту ссылку на адрес памяти. – McGarnagle

Смежные вопросы