使用多个合约运行 WCF ServiceHost

发布于 2024-07-09 20:06:38 字数 814 浏览 9 评论 0 原文

使用单个合约运行 ServiceHost 工作得很好,如下所示:

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();

现在我想添加第二个(第三个、第四个……)合约。 我的第一个猜测是添加更多像这样的端点:

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();

但是当然这不起作用,因为在创建 ServiceHost 时我可以传递 MyService1 作为参数或 MyService2 - 所以我可以向我的服务添加很多端点,但是所有人都必须使用相同的合同,因为我只能提供一种实现?
我感觉我没有抓住要点。 当然,必须有某种方法来为我添加的每个端点合约提供实现,或者不是?

Running a ServiceHost with a single contract is working fine like this:

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.Open();

Now I'd like to add a second (3rd, 4th, ...) contract. My first guess would be to just add more endpoints like this:

servicehost = new ServiceHost(typeof(MyService1));
servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
servicehost.Open();

But of course this does not work, since in the creation of ServiceHost I can either pass MyService1 as parameter or MyService2 - so I can add a lot of endpoints to my service, but all have to use the same contract, since I only can provide one implementation?
I got the feeling I'm missing the point, here. Sure there must be some way to provide an implementation for every endpoint-contract I add, or not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

棒棒糖 2024-07-16 20:06:39

您需要在同一个类中实现这两个服务(接口)。

servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open(); 

public class WcfEntryPoint : IMyService1, IMyService2
{
    #region IMyService1
    #endregion

    #region IMyService2
    #endregion
}

仅供参考:我经常使用部分类来使我的主机类代码更易于阅读:

// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
    // IMyService1 methods
}

// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
    // IMyService2 methods
}

You need to implement both services (interfaces) in the same class.

servicehost = new ServiceHost(typeof(WcfEntryPoint));
servicehost.Open(); 

public class WcfEntryPoint : IMyService1, IMyService2
{
    #region IMyService1
    #endregion

    #region IMyService2
    #endregion
}

FYI: I frequently use partial classes to make my host class code easier to read:

// WcfEntryPoint.IMyService1.cs
public partial class WcfEntryPoint : IMyService1
{
    // IMyService1 methods
}

// WcfEntryPoint.IMyService2.cs
public partial class WcfEntryPoint : IMyService2
{
    // IMyService2 methods
}
孤芳又自赏 2024-07-16 20:06:39

我目前面临同样的问题,并决定采用下面的实现。 我不确定拥有这么多服务合同是否存在任何性能问题,但在我的最终实现中,我可能会有大约 10 - 15 个服务合同,因此大约有 10-15 个 ServiceHost。

我将所有 WCF 服务托管在一个 Windows 服务中。

private void PublishWcfEndpoints()
{
    var mappings = new Dictionary<Type, Type>
    {
       {typeof (IAuthenticationService), typeof (AuthenticationService)},
       {typeof(IUserService), typeof(UserService)},
       {typeof(IClientService), typeof(ClientService)}
    };


    foreach (var type in mappings)
    {
        Type contractType = type.Key;
        Type implementationType = type.Value;

        ServiceHost serviceHost = new ServiceHost(implementationType);
        ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
                                                                  Properties.Settings.Default.ServiceUrl  + "/" + contractType.Name);
        endpoint.Behaviors.Add(new ServerSessionBehavior());

        ServiceDebugBehavior serviceDebugBehaviour =
            serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
        serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;

        log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);

        serviceHost.Open();
        serviceHosts.Add(serviceHost);
    }

}

请随意评论这种类型的设置,以及是否有任何问题,尤其是与性能相关的问题。

I'm currently faced with the same problem, and have decided to go with the implementation below. I'm not sure if there are any performance issues with having this many service contracts, but in my final implementation I will probably have about 10 - 15 service contracts, thus about 10-15 ServiceHosts.

I am hosting all my WCF services inside a single Windows Service.

private void PublishWcfEndpoints()
{
    var mappings = new Dictionary<Type, Type>
    {
       {typeof (IAuthenticationService), typeof (AuthenticationService)},
       {typeof(IUserService), typeof(UserService)},
       {typeof(IClientService), typeof(ClientService)}
    };


    foreach (var type in mappings)
    {
        Type contractType = type.Key;
        Type implementationType = type.Value;

        ServiceHost serviceHost = new ServiceHost(implementationType);
        ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(contractType, ServiceHelper.GetDefaultBinding(),
                                                                  Properties.Settings.Default.ServiceUrl  + "/" + contractType.Name);
        endpoint.Behaviors.Add(new ServerSessionBehavior());

        ServiceDebugBehavior serviceDebugBehaviour =
            serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>();
        serviceDebugBehaviour.IncludeExceptionDetailInFaults = true;

        log.DebugFormat("Published Service endpoint: {0}", Properties.Settings.Default.ServiceUrl);

        serviceHost.Open();
        serviceHosts.Add(serviceHost);
    }

}

Feel free to comment on this type of set up, and if there are any issues with it, especially performance-related.

仅一夜美梦 2024-07-16 20:06:39

这个答案是对 chilltemp 已接受答案中评论的进一步回应。

Sam,您确实应该确定为什么需要 10-50 个合同,并尝试寻找其他解决方案。 我查看了 Juval Lowy 的 WCF 编码标准(可在 http://www.idesign.net/ 上找到)并找到了以下参考资料:

3 份服务合同

[...]

  • 避免与一名成员签订合同。
  • 力争每个服务合同有三到五名成员。
  • 每个服务合同的成员数量不得超过 20 名。 十二可能是实际限制。
  • 他没有提到合同实施的限制(我可以找到),但我无法想象他将一项服务上的 50 个合同视为最佳实践。 我发现一种行之有效的解决方案是使用成员共享来实现类似的功能。

    例如,如果您使用 WCF 服务对 2 个值执行数学运算,则服务端可能有 4 个成员:Add(x,y)Subtract(x,y)< /code>,乘(x,y)除(x,y)。 如果将它们组合成更通用的成员并使用对象传递所需的数据,您可以轻松减少成员数量并提高可扩展性。 示例:PeformCalculation(obj),其中 obj 具有 x、yaction(加、减、乘、除)属性。

    希望这可以帮助。

    This answer is a further response to the comment in the accepted answer from chilltemp.

    Sam, You really should determine why you need 10-50 contracts and try to find another solution. I looked over Juval Lowy's WCF Coding Standards (found on http://www.idesign.net/) and found the following references:

    3 Service Contracts

    [...]

    1. Avoid contracts with one member.
    2. Strive to have three to five members per service contract.
    3. Do not have more than twenty members per service contract. Twelve is probably the practical limit.

    He doesn't mention a limit on contract implementations (that I can find) but I can't imagine him viewing 50 contracts on a service as anything resembling a best practice. One solution I have found that works well is to use member sharing for similar functions.

    For instance, if you are using the WCF service to perform mathematics on 2 values you might have 4 members on the service side: Add(x,y), Subtract(x,y), Multiply(x,y), Divide(x,y). If you combine these into a more generic member and use an object to pass the needed data you can easily reduce your member count and increase scalability. Example: PeformCalculation(obj) where obj has x, y, and action (add, subtract, multiply, divide) properties.

    Hope this helps.

    (り薆情海 2024-07-16 20:06:39

    我通过使用 RoutingService 找到了解决此问题的另一种解决方案 类。 每个合约仍必须托管在其自己的 ServiceHost 中,但可以有一个 RoutingService 位于所有合约之上 - 并通过统一的“端点”呈现它们。 我还写了一篇关于它的 codeproject 文章。 示例代码也可以在 Bitbucket 上找到。

    I found another solution to for this issue by using a the RoutingService class. Each contract must still be hosted in it's own ServiceHost, but there can be a RoutingService sitting on top of all of them - and presenting them over an unified "endpoint". I've also written a codeproject article about it. The example code is also available on Bitbucket.

    无尽的现实 2024-07-16 20:06:39

    如果您同意该服务共享的合同,辣椒的答案将会起作用。 如果您希望将它们分开,请尝试以下操作:

    host1 = new ServiceHost(typeof(MyService1));
    host2 = new ServiceHost(typeof(MyService2));
    
    host1.Open();
    host2.Open();
    
    public class MyService1 : IMyService1
    {
        #region IMyService1
        #endregion
    }
    
    public class MyService2 : IMyService2
    {
        #region IMyService2
        #endregion
    }
    

    编辑:正如马特发布的那样,这将需要每个服务/合同有多个端点

    chili's answer will work if you are ok with the contracts being shared by the service. If you want them to be separated try this:

    host1 = new ServiceHost(typeof(MyService1));
    host2 = new ServiceHost(typeof(MyService2));
    
    host1.Open();
    host2.Open();
    
    public class MyService1 : IMyService1
    {
        #region IMyService1
        #endregion
    }
    
    public class MyService2 : IMyService2
    {
        #region IMyService2
        #endregion
    }
    

    Edit: As Matt posted, this would require multiple endpoints for each service/contract

    §普罗旺斯的薰衣草 2024-07-16 20:06:39

    没有人记录指出。 当使用多个(作为一组,来自公共 url,例如 http)时,必须使用相同的绑定实例(而不是更多),即

    您的示例:

    servicehost = new ServiceHost(typeof(MyService1));
    servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
    servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
    servicehost.Open();
    

    应该只有一个 new Binding(),我通过 http 进行了测试。

    servicehost = new ServiceHost(typeof(MyService1));
     BasicHttpBinding binding = new BasicHttpBinding();
    servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
    servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
    servicehost.Open();
    

    我完全同意部分类在几个文件中实现几个合同。

    No-one documented enpoints. Whe used more than one (as a group, from common url, for example http) must use the same binding instance (not more), i.e.

    Your sample:

    servicehost = new ServiceHost(typeof(MyService1));
    servicehost.AddServiceEndpoint(typeof(IMyService1), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService1");
    servicehost.AddServiceEndpoint(typeof(IMyService2), new NetTcpBinding(), "net.tcp://127.0.0.1:800/MyApp/MyService2");
    servicehost.Open();
    

    should be only one new Binding(), I tested over http.

    servicehost = new ServiceHost(typeof(MyService1));
     BasicHttpBinding binding = new BasicHttpBinding();
    servicehost.AddServiceEndpoint(typeof(IMyService1),binding , "http://127.0.0.1:800/MyApp/MyService1");
    servicehost.AddServiceEndpoint(typeof(IMyService2), binding, "http://127.0.0.1:800/MyApp/MyService2");
    servicehost.Open();
    

    I agree totally with partial class implementing few contracts in few files.

    GRAY°灰色天空 2024-07-16 20:06:39

    将其与基地址和其下的多个服务/合同分开怎么样?
    我现在不在developmachine后面,而是类似:

    http://myserver/myservices/serviceA
    http://myserver/myservices/serviceB
    http://myserver/myservices/serviceC

    每个服务实现自己的 ServiceContract。

    你可以改变
    公共类WcfEntryPoint:IMyService1,IMyService2

    公共分部类 WcfEntryPoint : IMyService1
    公共分部类WcfEntryPoint:IMyService2

    示例

    What about splitting it up with a base address and multiple services/contracts below it?
    I am not behind a developmachine right now but something like:

    http://myserver/myservices/serviceA
    http://myserver/myservices/serviceB
    http://myserver/myservices/serviceC

    Each service implementing its own ServiceContract.

    You can change
    public class WcfEntryPoint : IMyService1, IMyService2
    to
    public partial class WcfEntryPoint : IMyService1
    public partial class WcfEntryPoint : IMyService2

    Example

    梦中楼上月下 2024-07-16 20:06:39

    我错过了什么吗,或者这里没有提到最简单的解决方案? 最简单的解决方案是:不要对 Web 服务使用多个接口。

    但这并不意味着您仍然可以将接口分开。 这就是为什么我们有接口继承。

    [ServiceContract]
    public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
    {
    }
    

    Meta 接口继承自所有其他接口。

    [ServiceContract]
    public interface ISomeOjectService1
    {
        [OperationContract]
        List<SomeOject> GetSomeObjects();
    }
    
    [ServiceContract]
    public interface ISomeOjectService2
    {
        [OperationContract]
        void DoSomethingElse();
    }
    

    那么服务就只有Meta接口了。

    public class SomeObjectService : IMetaSomeObjectService
    {
       public List<SomeOject> GetSomeObjects()
       {
           // code here
       }
    
       public void DoSomethingElse()
       {
           // code here
       }
    }
    

    Did I miss something, or is the simplest solution not mentioned here? The simplest solution is this: Don't use multiple interfaces for the Web Service.

    But that doesn't mean you can still have your interfaces separated. This is why we have Interface inheritance.

    [ServiceContract]
    public interface IMetaSomeObjectService : ISomeObjectService1, ISomeObjectService2
    {
    }
    

    The Meta interface inherits from all the other interfaces.

    [ServiceContract]
    public interface ISomeOjectService1
    {
        [OperationContract]
        List<SomeOject> GetSomeObjects();
    }
    
    [ServiceContract]
    public interface ISomeOjectService2
    {
        [OperationContract]
        void DoSomethingElse();
    }
    

    Then the service just has the Meta interface.

    public class SomeObjectService : IMetaSomeObjectService
    {
       public List<SomeOject> GetSomeObjects()
       {
           // code here
       }
    
       public void DoSomethingElse()
       {
           // code here
       }
    }
    
    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文