我已经实现了我的第一个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());
}
}
}
答案 0 :(得分:2)
如果使用界面,则必须做两件事:
让您的生活更轻松,并使用DataContract及其成员使用DataMember属性修饰实现,并使用实现而不是接口。
你可以找到很多关于这个here
的信息(并且不要以“我”开始实现名称)
这是一个没有已知类型的东西的返工,我想这会帮助你 第一步 - 不需要深入研究(Interfaces + KnownTypes)。
[DataContract]
public class ConsoleData
{
[DataMember]
public double CurrentIndicator
{
get { return 22; }
set { /* whatever */ }
}
}
[ServiceContract]
public interface IMBClientConsole
{
[OperationContract]
ConsoleData GetData();
}
答案 1 :(得分:1)
那里有几个问题。首先,您的界面应标记为[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
接口,但我只是将其删除。
但基本上要记住的事情通常是,您希望WCF服务包含方法,并且您的数据合同包含属性(或字段)。如果您从WSDL生成客户端,则DataContract中方法内的实现将不在客户端中,只有在您通过DataContracts将共享dll复制到客户端时才会有效。
希望有道理......