【问题标题】:Why Can You Expose Private Methods Publically in a WCF Service?为什么可以在 WCF 服务中公开公开私有方法?
【发布时间】:2016-01-10 07:01:47
【问题描述】:

为什么我们可以将 [OperationContract] 属性放在 wcf 服务中的私有方法上。从我开始编程的那一天开始,我就被教导私有方法是那些在课堂外无法访问的方法。现在在 WCF 服务中,您可以公开公开私有方法。

    [ServiceContract]
    public class MyServices
    {
        [OperationContract]
        private int add(int a,int b)
        {
            return a + b;
        }
    }

【问题讨论】:

  • 你可以用这个属性来标记你的方法,但是它对服务客户端是不可见的。
  • 您确认实际上可以通过 WCF 调用吗? (可能是——我没试过。)基本上没有办法说“这个属性只能应用于公共成员”。
  • @JohnSaunders 是的,完全正确。我刚刚创建了新的 WCF 服务项目,删除了 IService1 接口并将所有合同属性移动到类定义中。然后我添加了新的私有方法并用 OperationContract 标记它。然后我创建了新的控制台应用程序,添加了对我的 WCF 服务的服务引用,私有方法也被发现并添加到客户端。我成功地从控制台应用程序调用了私有方法。 WCF 服务托管在本地 IIS Express 上。
  • 嗯,问题可能不是你为什么可以这样做,而是你为什么。你是程序员,只是不要在你的私有方法上使用该属性。
  • 除了Patrick 所说的,您应该使用服务契约interfaces 并将属性放在接口方法上。创建没有接口的服务会迫使您使用服务引用,它们有自己的问题

标签: c# wcf .net-4.5


【解决方案1】:

不确定为什么它是这样设计的,但如果你检查源代码,第 336 行会说

internal const BindingFlags ServiceModelBindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;

请特别注意 NonPublic 标志。然后,当 WCF 使用反射来确定要公开哪些方法时,稍后会在第 678 行使用它:

   static List<MethodInfo> GetMethodsInternal(Type interfaceType)
   {
            List<MethodInfo> methods = new List<MethodInfo>();
            foreach (MethodInfo mi in interfaceType.GetMethods(ServiceModelBindingFlags))
            {
                if (GetSingleAttribute<OperationContractAttribute>(mi) != null)
                {
                    methods.Add(mi);
                }
                ...

我同意你的看法,这是一个奇怪的决定,但 WCF 开发人员明确决定通过包含 NonPublic 标志来实现这一点。

http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Description/ServiceReflector.cs,c1358e6f97071bfa

【讨论】:

  • 罗伯特,对于那些不明白的人,你应该解释一下 WCF 通过反射调用服务方法
  • @JohnSaunders - 调整
【解决方案2】:

有趣的是发现它有效。当然,您使用私有访问修饰符来拒绝您的类的消费者访问标记的成员。但是 WCF 将使用 OperationContract 属性标记的每个方法都公开。正如 Robert Levy 发现的那样,它是这样实现的。同样的,你可以在这个presentation about WCF中找到一些信息,尤其是slide no. 36

当您检查MSDN article about implementing WCF service 时,您可能会注意到他们在私有方法上使用了 OperationContract 属性。但这似乎是一个错字,因为该类必须实现其接口的方法。

无论如何,作为开发人员,最安全的方法是在服务类接口中使用ServiceContractOperationContract 属性,例如:

[ServiceContract]
public interface IMyService 
{
    [OperationContract]
    string GetData();
}

public class MyService : IMyService 
{
    public string GetData() { ... }
    private string ComputeData() { ... } // this one is not visible to clients
}

【讨论】:

    【解决方案3】:

    2 美分:

    WCF 使用的 SOAP 不遵循 C# 的 OOP 概念。另一个“异常”是方法重载,这是一个非常有用且广泛使用的 C# 功能。虽然我们可以在 Service 类中重载方法,但我们不能有两个具有相同名称(即使具有不同签名)的 OperationContract,这意味着我们不能通过 SOAP 公开重载方法。这样一来,这表明由于范围说明符不是 SOAP 功能,WCF 会忽略它并通过 OperationContract 和 DataMember 属性来决定合同。

    Following 也作为 DataContract 的 DataMember 公开:

    [DataMember]
    private int _personAge;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多