Invoke member of Userdefined Type

A

anthony.wolfe

Hello all,

I'm hoping that someone could help me with this bit of code. I am
using reflection to dynamically call a method within an HttpHandler.
When a method returns a user defined type that implements a certain
interface, I want to call that interfaces method. The problem is that
the local varaible holding the user defined type is declared an object.
The compiler will accept the invocation of the interface method on that
object. I have a feeling that I may be getting over my head a little
bit on this one. Any hekp would be greatly appreciated. Code follows:

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Reflection;
using PJC.PitchBook;
using PJC.PitchBook.Classes;
using PJC.PitchBook.Data;
using PJC.PitchBook.Web.UI.Ajax;

namespace PJC.PitchBook.Web.HttpHandlers {

public class ServerMethod:IHttpHandler {
HttpContext _context;

HttpRequest Request {
get {return _context.Request;}
}
HttpResponse Response {
get {return _context.Response;}
}
HttpContext Context {
get {return _context;}
set {_context = value;}
}
public void ProcessRequest(HttpContext context) {
Context = context;
NameValueCollection qs = Request.QueryString;
AJAXHandlerRequestStruct _values;
int i,j;
int countParams=qs.Count-1; //Will use this number later
if (countParams > -1) { //Meaning there is at least 1 (function
name) at qs[0]
_values = new AJAXHandlerRequestStruct();
_values.Args = new ArrayList();
_values.Method=qs[0]; //Function name here
for (i=1;i<countParams;i++) _values.Args.Add(qs[qs.GetKey(i)]);
//If any parameters, pick them up here
} else {
serverResponse(204);
return;
}

MethodInfo[] myMethods =
Assembly.GetExecutingAssembly().GetType("PJC.PitchBook.Web.HttpHandlers.ServerMethod").GetMethods();
MethodInfo theMethod;

//Get the method that matches in name and number of parameters
for (i=0;i<myMethods.Length;i++) {
if ((myMethods.Name==_values.Method) &&
(myMethods.GetParameters().Length==countParams)) { //This is it!
theMethod=myMethods;
Object[] args;
try {
ParameterInfo[] _params = theMethod.GetParameters();
int paramCount = _params.Length;
args = new Object[paramCount];

//Convert argument value to type specified by parameterInfo
object
for (j=0;j<paramCount;j++) args[j] =
Convert.ChangeType(_values.Args[j],_params[j].ParameterType);


Type RTYPE = theMethod.ReturnType;
object myResult = theMethod.Invoke(this,args);

// Test to see if return type implements interface
if (RTYPE.GetInterface("ToAJAX",false) != null) {
serverResponse(myResult.ToAJAX(true));
} else {
string[] myVals = new string[2];
myVals[0] = myResult.ToString();
myVals[1] = string.Empty;
serverResponse(new AJAXHandlerResponseStruct(myVals));
}

} catch (Exception) {
serverResponse(204);
break;
}
break;
}
serverResponse(204);
break;
}
return;
}
private void serverResponse (AJAXHandlerResponseStruct response) {
Response.StatusCode = 200;
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "text/html";
Response.AppendHeader("X-JSON", response.JSON);
Response.AppendHeader("Content-Length",
response.HTML.Length.ToString());
Response.Write(response.HTML);
Response.Flush();
Response.Close();
}
private void serverResponse (int responseCode) {
Response.StatusCode = responseCode;
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "text/html";
Response.AppendHeader("X-JSON", "null");
Response.AppendHeader("Content-Length", "0");
Response.Write(string.Empty);
Response.Flush();
Response.Close();
}
public bool IsReusable {
get { return true; }
}



#region Server Methods
public PJC.PitchBook.Web.UI.Ajax.PJCSectionCollection
getSectionCollection() {
return new PJC.PitchBook.Web.UI.Ajax.PJCSectionCollection();
}
// public AJAXHandlerResponseStruct
getFilteredSectionCollection(UserLevel DisplayLevel, int UserID) {
// return new
PJC.PitchBook.Web.UI.Ajax.PJCSectionCollection(DisplayLevel,
UserID).Items;
// }
// public AJAXHandlerResponseStruct
getSearchResultsSectionCollection(UserLevel DisplayLevel, int UserID,
string SearchString) {
// return new
PJC.PitchBook.Web.UI.Ajax.PJCSectionCollection(DisplayLevel, UserID,
SearchString).Items;
// }
// public AJAXHandlerResponseStruct Expand(int id) {
// return new PJC.PitchBook.Web.UI.Ajax.PJCSection(id).Items;
// }
// public AJAXHandlerResponseStruct getCanvasCollection(int
CollectionID) {
// return new
PJC.PitchBook.Web.UI.Ajax.PJCCollection(CollectionID).Items;
// }
// public AJAXHandlerResponseStruct CollectionHasVariables(int
CollectionID) {
// PJCUser theUser = (PJCUser)Context.Session["User"];
// PJC.PitchBook.Data.PJCCollectionData _data = new
PJC.PitchBook.Data.PJCCollectionData(CollectionID);
// return (_data.PageVariableIDs.Count > 0 & theUser.UserID != 0);
// }
#endregion
}
}

Sorry about the crappy formatting.

-Tony
 
T

Truong Hong Thi

When a method returns a user defined type that implements a certain
interface, I want to call that interfaces method.The problem is that
the local varaible holding the user defined type is declared an object.
The compiler will accept the invocation of the interface method on that
object.
When you call the method using reflection (MethodInfo.Invoke in your
snippet), only the runtime-type matters. If you want to call the
interface methods, use Activator.CreateInstance then cast the return
value to that interface.

Hope that helps,
Thi
 
A

anthony.wolfe

Thanks for the quick reply. Let me get this straight. If I can
determine the return type implements an interface, I can cast the
returned instance to the interface type, then call the interfaces
methods? I am sorry, I'm not at work and I see there are some errors in
the snippet I posted. Upen further review:

//This just creates an instance of the ReturnType of the method, using
the args[] for the method in the class contructor...This isn't the
intent.
Type RTYPE = theMethod.ReturnType;
if (RTYPE.GetInterface("IAJAXResponse",false) != null) {

serverResponse(((IAJAXResponse)Activator.CreateInstance(RTYPE,args)).ToAJAX(true));
} else {...}

//Would this work?
Type RTYPE = theMethod.ReturnType;
object myResult = theMethod.Invoke(this,args);
// Test to see if return type implements interface
if (RTYPE.GetInterface("IAJAXResponse",false) != null) {
serverResponse(((IAJAXResponse)myResult).ToAJAX(true));
} else {...}

-Tony
 
T

Truong Hong Thi

In this case, the call of CreateInstance is not necessary because you
already had the instance. So you could simply cast myResult to the
interface and call its ToAJAX method:
if (myResult is IAJAXResponse)
serverResponse( ((IAJAXResponse) myResult).ToAJAX(true));

That requires IJAXResponse to be known at compile time (that is, you
added a reference to it the DLL containing it). Otherwise, you could
call:
RTYPE.Invoke("ToAJAX", BindingFlags.InvokeMethod, null, myResult, new
object[] {true});

Thi
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top