Reputation: 2431
I have a WCF service which returns data based on the user type that is passed in. The definition for this method is:
[OperationContract]
public Element GetElement(User user, int id)
The problem I have is that there a number of methods in the service and each one takes in a user and contains a switch to return the relevant information for the type of user. i.e
switch(user.GetType())
{
case typeOf(UserA):
break;
case typeOf(UserB):
break;
case typeOf(UserC):
break;
}
Is there any way to be able to implement the below structure and have WCF automatically direct to the correct method? Possibly by some sort of behaviour?
[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
}
Upvotes: 0
Views: 143
Reputation: 2431
After looking at the answers provided and do some digging I came across IOperationInvoker. This did exactly what I was after. I could change the invoke method to use reflection to lookup the correct user method based on the inputs
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ioperationinvoker.invoke.aspx
Upvotes: 0
Reputation: 2218
I would suggest the following:
Defile a class library project where define your service contracts
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"; }
}
}
}
create your service project, add reference to the class library you created on step 1
using ClassLibrary1;
namespace WcfServiceLibrary3
{
public class Service1 : IService1
{
public Element GetElement(User type)
{
if (type == null) return null;
return type.GetElement();
}
}
}
and the config file
...
<endpoint address="" binding="basicHttpBinding" contract="ClassLibrary1.IService1">
...
create test console application and write the following
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);
}
}
}
the output will be
Upvotes: 0
Reputation: 3297
You may be able to do something similar by implementing IDispatchOperationSelector. There is a nice blog post about it here.
You may run in to problems with the overloaded method names though - that sort of thing doesn't tend to work nicely over the wire.
In my opinion, you should avoid exposing any inheritance hierarchy over the public data contract. Inheritance is a very OO concept, and does not fit in to a service orientated context nicely.
Upvotes: 1