Проблема выставления пользовательских сложных типов интерфейса в сервисах WCF - PullRequest
0 голосов
/ 17 апреля 2009

Я пытаюсь достать объект из другого приложения, используя 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». Насколько я могу судить, это сломанная труба из-за неисправного состояния, но я не могу понять, почему или, что более важно, как это исправить. Есть идеи?

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

Ответы [ 2 ]

2 голосов
/ 18 апреля 2009

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

0 голосов
/ 18 апреля 2009

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

...