为什么可以在WCF服务中公开显示私有方法?

时间:2014-12-18 17:52:27

标签: c# wcf .net-4.5

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

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

3 个答案:

答案 0 :(得分:6)

不确定为什么这是以这种方式设计的,但如果你检查来源,第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

答案 1 :(得分:4)

发现它有用很有意思。当然,您使用私有访问修饰符来拒绝您的类的消费者访问标记的成员。但是WCF会将您使用OperationContract属性标记的每个方法公开给public。正如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
}

答案 2 :(得分:0)

2美分:

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

以下内容也作为DataContract的DataMember公开:

[DataMember]
private int _personAge;