方法重载在 OOP 中很常见,但在 WCF 中可能会有些麻烦。看下面的例子。
[ServiceContract]
public interface IContract
{
void Test(int i);
void Test(string s);
}
public class MyService : IContract
{
public void Test(int i)
{
Console.WriteLine(i);
}
public void Test(string s)
{
Console.WriteLine(s);
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server1").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyService), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IContract), new BasicHttpBinding(), "");
host.Open();
});
IContract channel = ChannelFactory<IContract>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));
using (channel as IDisposable)
{
channel.Test(1);
}
}
}
public interface IContract
{
void Test(int i);
void Test(string s);
}
public class MyService : IContract
{
public void Test(int i)
{
Console.WriteLine(i);
}
public void Test(string s)
{
Console.WriteLine(s);
}
}
public class WcfTest
{
public static void Test()
{
AppDomain.CreateDomain("Server1").DoCallBack(delegate
{
ServiceHost host = new ServiceHost(typeof(MyService), new Uri("http://localhost:8080/MyService"));
host.AddServiceEndpoint(typeof(IContract), new BasicHttpBinding(), "");
host.Open();
});
IContract channel = ChannelFactory<IContract>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8080/MyService"));
using (channel as IDisposable)
{
channel.Test(1);
}
}
}
在 Host 载入时发生异常,信息如下:
未处理 System.InvalidOperationException
Message="ContractDescription 'IContract' has zero operations; a contract must have at least one operation."
Source="System.ServiceModel"
StackTrace:
在 System.ServiceModel.Description.ContractDescription.EnsureInvariants()
Message="ContractDescription 'IContract' has zero operations; a contract must have at least one operation."
Source="System.ServiceModel"
StackTrace:
在 System.ServiceModel.Description.ContractDescription.EnsureInvariants()
虽然这个异常信息有点莫名其妙,但其实问题时出在方法重载上了。SOAP Message Action 并不能区分这两个方法,因此也无法确定调用目标。解决方案很简单,使用 OperationContract.Name。
[ServiceContract]
public interface IContract
{
[OperationContract(Name="Test1")]
void Test(int i);
[OperationContract(Name="Test2")]
void Test(string s);
}
public interface IContract
{
[OperationContract(Name="Test1")]
void Test(int i);
[OperationContract(Name="Test2")]
void Test(string s);
}
这样一来,生成的客户端代理和消息中自然不会出现两个 Test 了。