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.
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);
}
}