Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在一个服务主机内托管多个服务?_C#_.net_Wcf_Soap_Service - Fatal编程技术网

C# 在一个服务主机内托管多个服务?

C# 在一个服务主机内托管多个服务?,c#,.net,wcf,soap,service,C#,.net,Wcf,Soap,Service,我有两个完全独立的服务(以及它们的合同),它们具有完全不同的依赖性和完全不同的责任。然而,他们的共同点是: 它们需要一起打开/关闭 它们共享相同的基址 它们具有相同的绑定/传输 虚拟合同: public class IFoo { void Foo(); } public class IBar { void Bar(); } [ServiceBehavior] public partial class IntegratedService { // You can i

我有两个完全独立的服务(以及它们的合同),它们具有完全不同的依赖性和完全不同的责任。然而,他们的共同点是:

  • 它们需要一起打开/关闭
  • 它们共享相同的基址
  • 它们具有相同的绑定/传输
虚拟合同:

public class IFoo {
    void Foo();
}

public class IBar {
    void Bar();
}
[ServiceBehavior]
public partial class IntegratedService
{
    // You can implement "base" methods here
}
现在,我想做的是将它们都托管在同一个服务主机中。我知道可以将这两个服务公开为端点,并在相同的服务类型中实现它们,如下所示:

public class FooBar : IFoo, IBar { }

var host = new ServiceHost(typeof(FooBar));
public class FooImpl : IFoo { }

public class BarImpl : IBar { }

var host = new ServiceHost();
host.AddEndpoint(typeof(FooImpl);
host.AddEndpoint(typeof(BarImpl);
host.Open();
然而,我正在寻找一种方法来做这样的事情:

public class FooBar : IFoo, IBar { }

var host = new ServiceHost(typeof(FooBar));
public class FooImpl : IFoo { }

public class BarImpl : IBar { }

var host = new ServiceHost();
host.AddEndpoint(typeof(FooImpl);
host.AddEndpoint(typeof(BarImpl);
host.Open();
因此,我可以保持我的服务实现整洁,每个实现都有自己的依赖项,而不是一个上帝对象


有人知道如何实现这一点吗?

您可以在同一个服务类中实现两个接口,并拥有一个端点,但使用单独的契约:

public class IFoo {
    void Foo();
}

public class IBar {
    void Bar();
}
[ServiceBehavior]
public partial class IntegratedService
{
    // You can implement "base" methods here
}
然后,实现每个接口:

public partial class IntegratedService : IFoo
{
   // Implement IFoo interface
}

public partial class IntegratedService : IBar
{
   // Implement IBar interface
}

希望有帮助。

您可以托管多个ServiceHosts,每个ServiceHosts都有自己的服务和端点,所有这些都共享相同的基址和端口。以下是我的实现,封装到ServiceHosting类中:

public class ServiceHosting<T1, T2>
{
    //Declaration
    protected ServiceHost SelfHost;
    protected string BaseUrlString;
    protected int Port;
    protected string HostUrlString = "";
    protected bool ExtendedBinding;

    //Constructor
    public ServiceHosting(string url, int port, bool extendedBinding = false)
    {
        BaseUrlString = url;
        Port = port;
        ExtendedBinding = extendedBinding;
    }

    //Properties
    protected int Max => int.MaxValue;

    public virtual bool StartService(int port)
    {
        try
        {
            var hostName = System.Net.Dns.GetHostName();

            HostUrlString = $@"net.tcp://{hostName}:{port}{BaseUrlString}"; //GM 10.09.2012: 

            try
            {
                SelfHost = new ServiceHost(typeof(T1), new Uri(HostUrlString));

                var smb = SelfHost.Description.Behaviors.Find<ServiceMetadataBehavior>() ??
                          new ServiceMetadataBehavior() { };
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;

                SelfHost.Description.Behaviors.Add(smb);

                var throttleBehavior = new ServiceThrottlingBehavior();
                SelfHost.Description.Behaviors.Add(throttleBehavior);

                var mexUrlString = String.Format(@"net.tcp://{0}:{1}{2}/mex", hostName, port, BaseUrlString);

                // Add MEX endpoint
                SelfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexTcpBinding(), new Uri(mexUrlString));

                // Add binding
                var binding = ConfigureBinding();

                // Add application endpoint
                SelfHost.AddServiceEndpoint(typeof(T2), binding, "");

                if (ExtendedBinding)
                {
                    foreach (ServiceEndpoint ep in SelfHost.Description.Endpoints)
                    {
                        foreach (OperationDescription op in ep.Contract.Operations)
                        {
                            var dataContractBehavior = op.Behaviors[typeof(DataContractSerializerOperationBehavior)] as DataContractSerializerOperationBehavior;

                            if (dataContractBehavior != null)
                            {
                                dataContractBehavior.MaxItemsInObjectGraph = Max;
                            }
                        }
                    }
                }

                // Open the service host to accept incoming calls
                SelfHost.Open();
            }
            catch (CommunicationException)
            {
                // log
                SelfHost.Abort();
                return false;
            }
            catch (Exception)
            {
                // log
                SelfHost.Abort();
                return false;
            }

        }
        catch (Exception)
        {
            // log
            return false;
        }
        return true;
    }

    private NetTcpBinding BaseConfigureBinding()
    {
        return new NetTcpBinding
        { Security = { Mode = SecurityMode.None }, CloseTimeout = new TimeSpan(0, 0, 0, 5) };
    }

    protected virtual NetTcpBinding ConfigureBinding()
    {
        var binding = BaseConfigureBinding();

        if (ExtendedBinding)
        {
            binding.MaxBufferPoolSize = Max;
            binding.MaxReceivedMessageSize = Max;
            binding.MaxBufferSize = Max;
            binding.MaxConnections = 200; //rdoerig 12-03-2013 default value is 10:
            binding.ListenBacklog = 200; //rdoerig 12-03-2013 default value is 10 : buffer of pending connections 

            binding.ReaderQuotas.MaxDepth = Max;
            binding.ReaderQuotas.MaxStringContentLength = Max;
            binding.ReaderQuotas.MaxArrayLength = Max;
            binding.ReaderQuotas.MaxBytesPerRead = Max;
            binding.ReaderQuotas.MaxNameTableCharCount = Max;

            binding.CloseTimeout = new TimeSpan(0, 0, 10, 0);
            binding.OpenTimeout = new TimeSpan(0, 0, 10, 0);
            binding.ReceiveTimeout = new TimeSpan(0, 0, 10, 0);
            binding.SendTimeout = new TimeSpan(0, 0, 10, 0);

        }

        return binding;
    }

    public bool StopService()
    {
        try
        {
            SelfHost?.Close();
        }
        catch (Exception)
        {
            // log
            return false;
        }
        return true;
    }
}
为了确保托管多个服务时不会出错,您应该将服务的URI配置为不同的,例如

new ServiceHosting<LoginService, ILoginService>("/Services/LoginService", true);
new ServiceHosting<ConfigService, IConfigService>("/Services/ConfigService", true);
newservicehosting(“/Services/LoginService”,true);
新服务托管(“/Services/ConfigService”,true);

您必须在同一ServiceHost中承载这两个服务,还是接受多个ServiceHost实例,每个实例都有自己的服务和端点?@WichServicesser遗憾的是,这不是因为所有服务都需要在同一端口上运行。@artganify的可能重复项您可以在同一端口上运行多个ServiceHost。至少这是我为公开的net.tcp端点所做的。正如我在问题中所说的,这正是我不想要的。在您的示例中,您基本上只是“拆分”类,但最终还是一个类。我需要有不同的类型,因为我需要为每个服务注入不同的依赖关系。@artganify每个端点只允许一个服务,您想要的是在IIS中有两个具有相同dns和相同端口的不同站点,您不能。我只是建议使用该实现,因为在“基类”中,您可以根据需要为这两个服务提供控制,比如同时启动一些代码,如果不是您想要的,很抱歉。@artganify我必须同意李嘉图在这一点上的意见。根据您的需求,共享单个实现是WCF提供给您的唯一受支持的路由。您声明这些服务在思想上是完全独立的,但您对它们施加了人为的限制,例如它们需要一起打开/关闭等。无论您的托管机制如何,这些服务都是独立的服务,应该被视为独立的服务。您可以单独托管它们,然后作为单独的关注点解决外围设备需求。不确定这如何解决OPs问题-仍然只有一个服务主机它没有-直接解决。从他的评论中,我了解到OP认为他不能为同一地址+端口托管多个ServiceHosts。我的示例表明这实际上是可能的。当您尝试在相同的物理地址和端口上打开第二个服务主机时,是否会出现错误?如果这能奏效,我会非常惊讶