我写了一个用于创建和打开每个服务的ServiceHost实例的类。我想允许他们添加MEX端点。下面是Register方法的代码,它创建所有主机。当我稍后循环访问主机列表并在所有主机上调用Open时,要打开的第二个主机错误输出“附加信息:带有合同的'_THE_MEX_ADDRESS'的ChannelDispatcher'”IMetadataExchange“'无法打开其IChannelListener“。如果我删除MEX代码它运行正常并打开每个主机。我该如何解决这个问题?
编辑:添加完整课程
Edit2:请记住,这完全在代码中,而不在app.config
中public class ServiceHostMgr
{
#region Constructor
public ServiceHostMgr(string ip, int httpport, int nettcpport, bool discoverable)
{
_hosts = new List<ServiceHost>();
_ip = ip;
_httpport = httpport;
_nettcpport = nettcpport;
_discoverable = discoverable;
}
#endregion
#region Fields
private string _ip;
private int _httpport;
private int _nettcpport;
private bool _discoverable;
private bool _disc = false;
#endregion
#region Properties
private List<ServiceHost> _hosts;
public List<ServiceHost> Hosts
{
get { return _hosts; }
}
#endregion
#region Methods
public ServiceHostMgr Register(Type serviceType, Type implementedContract, string path)
{
string nettcpuri = "net.tcp://" + _ip + ":" + _nettcpport.ToString();
string httpuri = "http://" + _ip + ":" + _httpport.ToString();
List<Uri> baseAddresses = new List<Uri>();
baseAddresses.Add(new Uri(nettcpuri));
if (_discoverable)
baseAddresses.Add(new Uri(httpuri));
ServiceHost host = new ServiceHost(implementedContract, baseAddresses.ToArray());
/*
if (_discoverable)
{
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
}
*/
if (_discoverable)
{
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, create new one, set values, add to collection
if (smb == null)
{
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
// add to behaviors collection
host.Description.Behaviors.Add(smb);
// add service endpoint
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
}
}
NetTcpBinding nettcpbinding = new NetTcpBinding();
host.AddServiceEndpoint(serviceType, nettcpbinding, nettcpuri + "/" + path);
_hosts.Add(host);
return this;
}
public ServiceHostMgr Open()
{
foreach (ServiceHost h in _hosts)
h.Open();
return this;
}
public ServiceHostMgr Close()
{
foreach (ServiceHost h in _hosts)
h.Close();
return this;
}
#endregion
}
这是调用代码:
ServiceHostMgr hostMgr = new ServiceHostMgr("localhost", 8012, 8002, true)
.Register(typeof(IPurchaseOrderSvc), typeof(PurchaseOrderSvc), "PurchaseOrder")
.Register(typeof(ILoginSvc), typeof(LoginSvc), "Login")
.Open();
Console.WriteLine("Running...");
Console.ReadLine();
hostMgr.Close();
答案 0 :(得分:0)
好吧,你正在检查行为是否已经存在 - 这很好。
但即使它确实已经存在 - 你试图再次添加它 - 这就是你的问题。
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// assume you found the ServiceMetadataBehavior... - you set new values
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
// and now you're ADDING the already existing "smb" to the behaviors collection!
host.Description.Behaviors.Add(smb);
所以我相信你真正想要的更像是这样:
ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, create new one, set values, add to collection
if (smb == null)
{
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
// add to behaviors collection
host.Description.Behaviors.Add(smb);
// add service endpoint
host.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
}
或者,如果您确实要将现有行为的值设置为特定值,则必须在调用.Behaviors.Add(smb);
之前和host.AddServiceEndpoint
之前再次检查,看看您是否正在处理现有行为(然后不再次添加!)或新的行为