WCF 服务内部方法重载

本文关键字:重载 方法 内部 服务 WCF | 更新日期: 2023-09-27 18:35:31

我有一个 WCF 服务,它根据传入的用户类型返回数据。此方法的定义是:

[OperationContract]
public Element GetElement(User user, int id)

我遇到的问题是服务中有许多方法,每个方法都接受一个用户并包含一个开关来返回用户类型的相关信息。

switch(user.GetType())
{
    case typeOf(UserA):
     break;
    case typeOf(UserB):
     break;
    case typeOf(UserC):
     break;
}

有没有办法实现以下结构并让 WCF 自动定向到正确的方法?可能是通过某种行为?

[OperationContract]
public Element GetElement(User user, int id)
{
     //DO NOTHING
}
public Element GetElement(UserA user, int id)
{
     //Process for typeof UserA
}
public Element GetElement(UserB user, int id)
{
     //Process for typeof UserB
}
public Element GetElement(UserC user, int id)
{
     //Process for typeof UserC
}

WCF 服务内部方法重载

您可以通过实现 IDispatchOperationSelector 来做类似的事情。 这里有一篇很好的博客文章。

不过,您可能会遇到重载方法名称的问题 - 这种事情往往不能很好地通过网络工作。

在我看来,您应该避免在公共数据协定上公开任何继承层次结构。 继承是一个非常面向对象的概念,并且不适合面向服务的上下文。

我会提出以下建议:

取消属性定义服务协定的类库项目

namespace ClassLibrary1
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        Element GetElement(User type);
    }
    [DataContract]
    public class Element
    {
        [DataMember]
        public string Name { get; internal set; }
    }

    [KnownType(typeof(UserA))]
    [KnownType(typeof(UserB))]
    [KnownType(typeof(UserC))]
    public class User
    {
        public Element GetElement()
        {
            return new Element() { Name = TypeName };
        }
        protected virtual string TypeName
        {
            get { return "base"; }
        }

    }
    public class UserA : User
    {
        protected override string TypeName
        {
            get { return "A"; }
        }
    }
    public class UserB : User
    {
        protected override string TypeName
        {
            get { return "B"; }
        }
    }
    public class UserC : User
    {
        protected override string TypeName
        {
            get { return "C"; }
        }
    }
}

创建服务项目,添加对在步骤 1 中创建的类库的引用

使用 ClassLibrary1;

namespace WcfServiceLibrary3
{
    public class Service1 : IService1
    {
        public Element GetElement(User type)
        {
            if (type == null) return null;
            return type.GetElement();
        }
    }
}

和配置文件

...
            <endpoint address="" binding="basicHttpBinding" contract="ClassLibrary1.IService1">
...

创建测试控制台应用程序并编写以下内容

using ClassLibrary1;
using ConsoleApplication10.ServiceReference1;
namespace ConsoleApplication10
{
    class Program
    {
        static void Main(string[] args)
        {
            var myService = new Service1Client();
            Console.WriteLine(myService.GetElement(new UserA()).Name);
            Console.WriteLine(myService.GetElement(new UserB()).Name);
            Console.WriteLine(myService.GetElement(new UserC()).Name);
        }
    }
}

输出将是

  • 一个
  • C

在查看了提供的答案并进行了一些挖掘后,我遇到了IOperationInvoker。这完全符合我的追求。我可以更改调用方法以使用反射根据输入查找正确的用户方法

http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ioperationinvoker.invoke.aspx