Search code examples
c#jsonhttpwebrequestfactory-pattern

Problems with implementation of the factory pattern


I work with web service, and I'm get response from service. Response will be have different structure. For example, API getInfo return response:

{"code":0,"message":"","result":{"nickname":"UserName","age":"22"}}

API signin:

{"code":0,"message":"","result":"user_token"}

etc. I use HttpWebRequest for POST request. Request and response deserialize/serialize with DataContractSerializer.

So, I want to use factory pattern, this is my implementation:

[DataContract]
public class ResultGetInfo
{
    [DataMember(Name = "nickname")]
    public int Nickname { get; set; }
    [DataMember(Name = "age")]
    public int Age { get; set; }
}

[DataContract]
public abstract class Response
{
}

[DataContract]
public class ResponseSignin : Response
{
    [DataMember(Name = "code")]
    public int Code { get; set; }
    [DataMember(Name = "message")]
    public string Message { get; set; }
    [DataMember(Name = "result")]
    public string Result { get; set; }
}

[DataContract]
public class ResponseGetInfo : Response
{
    [DataMember(Name = "code")]
    public int Code { get; set; }
    [DataMember(Name = "message")]
    public string Message { get; set; }
    [DataMember(Name = "result")]
    public ResultGetInfo Result { get; set; }
}

public abstract class CreateResponse
{
    public abstract Response CreateResponseObj();
}

public class CreateResponseSignin : CreateResponse
{
    public override Response CreateResponseObj()
    {
        return new ResponseSignin();
    }
}

public class CreateResponseGetInfo : CreateResponse
{
    public override Response CreateResponseObj()
    {
        return new ResponseGetInfo();
    }
}

I get response in callback function:

private void getResponseCallback(IAsyncResult asynchronousResult)
{
    var request = (Request)asynchronousResult.AsyncState;
    try
    {
        HttpWebResponse response;

        // End the get response operation
        response = (HttpWebResponse)request.HttpRequest.EndGetResponse(asynchronousResult);
        Stream streamResponse = response.GetResponseStream();
        StreamReader streamReader = new StreamReader(streamResponse);
        var gyResponse = streamReader.ReadToEnd();
        streamResponse.Close();
        streamReader.Close();
        response.Close();
        Response response_obj = request.Creater.CreateResponseObj();  

        using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(gyResponse)))
        {
            var serializer = new DataContractJsonSerializer(response_obj.GetType());                                     
            response_obj = (Response)serializer.ReadObject(stream);
            if (request.CallBack != null)
            {
                request.CallBack.Invoke(response_obj, null);
            }
        }
    }
    catch (WebException e)
    {
        if (request.CallBack != null)
        {
            request.CallBack.Invoke(null, e);
        }
    }
}

For DataContractJsonSerializer I declare the type here:

var serializer = new DataContractJsonSerializer(response_obj.GetType());

Where response_obj is object, which has needed type (ResponseSignin or ResponseGetInfo).

So, I call Invoke() in my delegate.

private void ResponseHandler(Response result, Exception error)
{
    if (error != null)
    {
        string err = error.Message;
    }
    else
    {
        Response response = result;
    }
}

And here I have a problem. Variable result really contains correct answer, but I don't get properties, because abstract class Response is without properties. And I can't declare properties or override in derived classes. I'm not sure that chose the desired pattern.


Solution

  • Have you tried just casting the result variable to the type you need?

    E.g.

    private void ResponseHandler(Response result, Exception error)
    {
        if (error != null)
        {
            string err = error.Message;
            return;
        }
    
        var signInResponse = result as ResponseSignin;
        if (signInResponse != null)
        {
            HandleSignInResponse(signInResponse);
        }
    
        var infoResponse = result as ResponseGetInfo;
        if (infoResponse != null)
        {
            HandleInfoResponse(infoResponse);
        }
    }