tags:

views:

48

answers:

2

I have several web services which return various results. Some results are strings and some are arrays (automatically generated from the WSDL). When I call the web services, I want to get all the various results (including exceptions), and then operate on them through a common interface, but because of the type differences, I cannot get this to work. In the example below, the T is the type I want to store (for instance List or string) and U is the type returned by the service (for instance Report[] or string).

    private class Result<T, U> : ICommon
    {
        public delegate U ResultProvider();

        public readonly string ElementName = null;
        public readonly T Value = null;
        public readonly Exception Exception = null;

        public Result(string ElementName, ResultProvider Provider)
        {
            this.ElementName = ElementName;
            try
            {
                this.Value = Provider();
            }
            catch (Exception e) {
                this.Exception = e;
            }
        }
    }

If all the services returned List it would be trivial to coalesce U and T and do something like this:

    private class Result<T> : ICommon
    {
        public delegate T[] ResultProvider();

        public readonly string ElementName = null;
        public readonly List<T> Value = null;
        public readonly Exception Exception = null;

        public Result(string ElementName, ResultProvider Provider)
        {
            this.ElementName = ElementName;
            try
            {
                this.Value = new List<T>(Provider());
            }
            catch (Exception e) {
                this.Exception = e;
            }
        }
    }

But this won't work when the web method returns a non-Array. So right now I have Result and Result (effectively hand coded version of Result)

Any suggestions for this design? Any better pattern I should look at?

A: 

I think Reflection is what you want.

you can use typeof(U) to get the returned type of ResultProvder, then it's fairly easy to figure out what the return type is and handle it accordingly. You can go and do .IsArray and then .GetMethod to access the members of the returned type.

Timothy Baldridge
A: 

I'm not sure if I understand you completely, but in your first example, could you maybe create an overload of the constructor that took a Func<U, T> that would convert Us to Ts? So if the service returned a Person[], you could have

public Result(string ElementName, ResultProvider Provider, Func<U, T> converter)
{
    this.ElementName = ElementName;
    try
    {
       this.Value = converter(Provider());
    }
    catch (Exception e) {
       this.Exception = e;
    }
 }

and then call

var result = new Result<List<Person>, Person[]>(
    "name", 
    GetPerson(), 
    p => new List<Person>(p));
Graham Clark