Question

I'm looking for a way to accomplish the behavior illustrated in source code below. I've create WCF service proxies with the "Always generate message contracts" option. All of my request and response message contracts implement a common interface and I'd like to execute them using the same function. It seems to me that there should be a generic way to send messages through the client proxy, but I can't find it anywhere. Any help would be greatly appreciated!

// I can do this
private IPagedResponse GetAllFoods()
{
    NutrientDBClient client = new NutrientDBClient();
    GetAllFoodsRequest request = new GetAllFoodsRequest();
    GetAllFoodsResponse response = client.GetAllFoods(request);

    return response;
}
// I'd like to do this
private IPagedResponse ExecutePagedRequest(IPagedRequest request)
{
    NutrientDBClient client = new NutrientDBClient();
    IPagedResponse response = (IPagedResponse)client.Execute(request);

    return response;
}

I've currently added an ExecutePagedRequest(IPagedRequest) method to NutrientDBClient and manually execute the correct service operation based on the concrete type of IPagedRequest. I'm looking for a more elegant way so that I can simply implement IPagedRequest on a message contract and it auto-magically works.

Was it helpful?

Solution 2

Below is how I solved this problem. My message contracts, implement IPagedRequest & IPagedResponse. NutrientDBClient is my code-generated client proxy (ClientBase). ExecutePagedRequest() does the message routing based on the concrete type of request.

public interface IPagedRequest
{
    PagingContext PageInfoState { get; set; }
}

public interface IPagedResponse
{
    PagingContext PageInfoState { get; }
    IEnumerable ResultItems { get; }
}

public partial class NutrientDBClient : IHasPagedServiceOperations
{
    public IPagedResponse ExecutePagedRequest(IPagedRequest request)
    {
        if (request == null) { throw new ArgumentNullException("request"); }

        if (typeof(GetAllFoodsRequest).IsAssignableFrom(request.GetType()))
        {
            return GetAllFoods((GetAllFoodsRequest)request);
        }

        // Other Service Operations that take IPagedRequest and 
        // return IPagedResponse removed for example


        throw new NotSupportedException(
            string.Format("Paged requests of type {0} are not supported.",
                request.GetType().Name));
    }
}

OTHER TIPS

Not 100% sure what you really want to achieve, but let me explain a few basics about WCF.

A lot of programmers mistakenly take WCF to be some sort of a .NET remoting - e.g. they believe you're basically reaching out to a remote object on a server far away, calling a method on a "remoted" .NET object somewhere. This is absolutely not the case!

WCF is about messaging - your client and server exchange nothing but serialized messages (and possibly headers) - but that's it.

That said: those message exchange mechanisms are designed to be interoperable with a lot of non .NET platforms - Java, Ruby - you name it. They leverage the WSDL and XSD mechanisms to exchange descriptions of operations (WSDL) and the data structures being exchanged (XSD).

WSDL and XSD are all about well defined, explicit calls and data structures. The functionality offered by those standards is the lowest common denominator between all SOA platforms - and as such, it's quite a bit more limited than what you might have grown accustomed to using pure .NET. The SOA world and the OOP world don't always match very well.

So in the end, what you really need to understand and program against, are the standards as defined by WSDL/XSD - and as such, you need to forget about all .NET niceties like generics, interfaces and classes implementing those interfaces really quickly. They simply don't work over the WCF messaging infrastructure.

All you can exchange between a WCF client and a WCF server is whatever you can describe and express in XML schema - concrete types made up of basic data types like strings, integers, and so forth. XSD supports a bit of inheritance, but it doesn't know squat about generics, and it doesn't deal with interfaces and non-concrete classes at all.

So out of the box, I don't think your approach with a generic interface and messages implementing that interface and WCF figuring out what real method to call based on that class will fly. It's just not the way WCF was architected and designed to work.

You might be able to create a custom (but concrete) base class, and you might be able to extend the WCF operation dispatcher on the server side to call different methods based on your classes being passed in (or some extra info in the headers coming along for the ride) - but I neither think that'll be easy, nor really the way WCF is intended to work - no guarantees that you'll really be able to pull it off.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top