我的第一个WCF服务器-工作与"字符串"但不适用于自定义界面
本文关键字:quot 字符串 不适用 适用于 自定义界面 第一个 WCF 工作 我的 服务器 | 更新日期: 2023-09-27 18:08:29
我实现了我的第一个WCF应用程序。我需要一个方法IConsoleData GetData();
客户端收到CommunicationException "There was an error reading from the pipe: The channel was closed. (109, 0x6d)."
当我将IConsoleData GetData();
替换为string GetData();
时,应用程序变得可用。
我应该如何修复代码使用IConsoleData GetData()
?
//public interface IConsoleData
//{
// double GetCurrentIndicator();
//}
//public class IConsoleDataImpl : IConsoleData
//{
// public double GetCurrentIndicator()
// {
// return 22;
// }
//}
[ServiceContract]
public interface IMBClientConsole
{
[OperationContract]
//IConsoleData GetData();
string GetData();
}
public class MBClientConsole : IMBClientConsole
{
//public IConsoleData GetData()
//{
// return new IConsoleDataImpl();
//}
public string GetData()
{
//return new IConsoleDataImpl();
return "hello";
}
}
class Log
{
private ServiceHost _host;
public void initialize()
{
_host = new ServiceHost(typeof (MBClientConsole),
new Uri[]
{
new Uri("net.pipe://localhost")
});
_host.AddServiceEndpoint(typeof(IMBClientConsole),
new NetNamedPipeBinding(),
"PipeReverse");
_host.Open();
System.Threading.Thread.Sleep(1000000);
// TODO: host.Close();
}
}
客户://public interface IConsoleData
//{
// double GetCurrentIndicator();
//}
[ServiceContract]
public interface IMBClientConsole
{
[OperationContract]
//IConsoleData GetData();
string GetData();
}
class Program
{
static void Main(string[] args)
{
ChannelFactory<IMBClientConsole> pipeFactory =
new ChannelFactory<IMBClientConsole>(
new NetNamedPipeBinding(),
new EndpointAddress(
"net.pipe://localhost/PipeReverse"));
IMBClientConsole pipeProxy =
pipeFactory.CreateChannel();
while (true)
{
string str = Console.ReadLine();
Console.WriteLine("pipe: " +
//pipeProxy.GetData().GetCurrentIndicator());
pipeProxy.GetData());
}
}
}
如果你使用一个接口,你必须做两件事:
- 实现需要是可序列化的(使用DataContract - Attribute)
- 你必须告诉服务的已知类型如果你使用接口(这里是IConsoleDataImpl)
让你的生活更轻松,用DataContract装饰实现,用DataMember属性装饰它的成员,使用实现而不是接口。
你可以在这里找到很多关于这个的信息
(实现名称不要以"I"开头)
这是一个没有已知类型的东西的返工,我想这将有助于你的第一步-还没有必要深入挖掘(接口+ KnownTypes)。
[DataContract]
public class ConsoleData
{
[DataMember]
public double CurrentIndicator
{
get { return 22; }
set { /* whatever */ }
}
}
[ServiceContract]
public interface IMBClientConsole
{
[OperationContract]
ConsoleData GetData();
}
这里有几个问题。首先,你的接口应该被标记为[DataContract]
[DataContract]
public interface IConsoleData
{
double GetCurrentIndicator();
}
现在,当WCF通过网络发送IConsoleData时,它将在类中序列化数据,发送它,并在客户端上反序列化它。您的实现的问题在于它不包含任何可以序列化的内容。
public class IConsoleDataImpl : IConsoleData
{
public double GetCurrentIndicator()
{
return 22;
}
}
如果要使用上面的svcutil.exe
构建客户端,它将创建IConsoleDataImpl类,但GetCurrentIndicator
方法不会做任何事情。这里的重要区别是:WCF将传输DATA,而不是IMPLEMENTATION。
你可能想要的更像是:
[DataContract]
public interface IConsoleData
{
[DataMember]
double CurrentIndicator { get; set; }
}
public class ConsoleDataImpl : IConsoleData
{
public double CurrentIndicator { get; set; }
}
[ServiceContract]
[KnownType(typeof(ConsoleDataImpl))]
public interface IMBClientConsole
{
[OperationContract]
IConsoleData GetData();
}
public class MBClientConsole : IMBClientConsole
{
public IConsoleData GetData()
{
return new IConsoleDataImpl() { CurrentIndicator = 22 };
}
}
虽然在这一点上,IConsoleData
接口不是真的需要,我只是删除它。