无法在代码中注册具有多个ServiceHost实例的MEX端点

时间:2014-02-11 21:51:28

标签: c# wcf

我写了一个用于创建和打开每个服务的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();

1 个答案:

答案 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之前再次检查,看看您是否正在处理现有行为(然后再次添加!)或新的行为