2009-04-17 13 views
0

Я пытаюсь получить объект из другого приложения с помощью WCF. Со встроенными классами он отлично работает, но я сталкиваюсь с проблемами при попытке вернуть пользовательский тип интерфейса из операции WCF.Проблема выявления пользовательских сложных типов интерфейса в службах WCF

Включает ли я интерфейс в обоих приложениях отдельно или специфицирует его как общую сборку, я получаю тот же результат: сообщение CommunicationException с сообщением «Произошло сообщение об ошибке с недопустимой ошибки 109».

Интерфейс выглядит следующим образом:

[ServiceContract] 
public interface IBase { 
    int IntTest { 
     [OperationContract] 
     get; 
    } 
    String StringTest { 
     [OperationContract] 
     get; 
    } 
    IOther OtherTest { 
     [OperationContract] 
     get; 
    } 
} 

[ServiceContract] 
public interface IOther { 
    String StringTest { 
     [OperationContract] 
     get; 
    } 
} 

Мой сервер выглядит следующим образом:

public partial class MainWindow : Window { 
    private Base fb; 
    private ServiceHost host; 

    public MainWindow() { 
     InitializeComponent(); 
     fb = new Base(); 
     host = new ServiceHost(fb, new Uri[] { new Uri("net.pipe://localhost") }); 
     host.AddServiceEndpoint(typeof(IBase), new NetNamedPipeBinding(), 
      "PipeReverse"); 
     host.Open(); 
    } 

    private void Window_Closing(object sender, CancelEventArgs e) { 
     host.Close(); 
    } 
} 

А вот моя реализация интерфейса:

[Serializable] 
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] 
public class Base : MarshalByRefObject, IBase { 
    public int IntTest { 
     get { return 4; } 
    } 

    public string StringTest { 
     get { return "A string from Base"; } 
    } 

    public IOther OtherTest { 
     get { return new Other(); } 
    } 
} 

[Serializable] 
[DataContract] 
public class Other : MarshalByRefObject, IOther { 
    [DataMember] 
    public string StringTest { 
     get { return "A string from Other"; } 
    } 

} 

Клиент выглядит это:

public partial class Form1 : Form { 

    IBase obj; 

    public Form1() { 
     InitializeComponent(); 
     ChannelFactory<IBase> pipeFactory = new ChannelFactory<IBase>(
      new NetNamedPipeBinding(), new EndpointAddress(
      "net.pipe://localhost/PipeReverse")); 

     obj = pipeFactory.CreateChannel(); 
    } 


    private void button2_Click(object sender, EventArgs e) { 

     Console.WriteLine("Returns: " + obj.StringTest + " " + 
      obj.StringTest.Length); 
     Console.WriteLine("Returns: " + obj.IntTest); 
     Console.WriteLine(obj.OtherTest); 

    } 
} 

Все работает как шарм, кроме этой линии:

Console.WriteLine(obj.OtherTest); 

Это дает мне CommunicationException с сообщением «Была ошибка чтения из трубы: Непризнанная ошибка 109». Насколько я могу судить, это сломанная труба из-за неисправного состояния, но я не могу понять, почему, или что еще более важно, как ее исправить. Есть идеи?

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

+0

Я запустил этот код на своей машине. Хотя, нет ошибок, возвращаемых для методов IntTest и StringTest, данных нет. Что-то еще может быть неправильным. –

ответ

2

Возвращенное свойство OtherTest должно быть конкретным типом, а не интерфейсом, иначе сериализация не будет работать.

+0

Вот и все! Благодарю. Фактически это означает, что мне придется иметь бизнес-объекты в общей сборке. Я надеялся, что смогу просто дублировать интерфейс, но я полагаю, что это нужно сделать. Еще раз спасибо за помощь. – Farawin

0

Это, как правило, ошибка сериализации. Посмотрите на атрибут [KnownType]. Самый простой способ проверить это - напрямую обратиться к DataContractSerializer. Вы можете использовать методы WriteObject и ReadObject для получения истинных ошибок сериализации. Вы также можете проверить поток (FileStream обычно), чтобы убедиться, что вы правильно сериализуете.

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

  • Нет связанных вопросов^_^