Trying to use Reflection to Invoke Method within same class - c#

I have a WCF service that accepts an object as a parameter that has a URI and Method Name.
What I am trying to do is have a method that will look # the URI, if it contains the words "localhost" it will use reflection and call a method, of the name that is passed in as a parameter, within the the same class, return a value and continue on.
public class Test
{
public GetStatResponse GetStat(GetStatRequest request)
{
GetStatResponse returnValue = new GetStatResponse();
if(Helpers.Contains(request.ServiceURI,"localhost", StringComparison.OrdinalIgnoreCase))
{
MethodInfo mi = this.GetType().GetMethod(request.ServiceMethod /*, BindingFlags.Public | BindingFlags.IgnoreCase*/);
returnValue = (GetStatResponse)mi.Invoke(this,null);
}
The above is the code segment pertaining to this question. I pull the MethodInfo no problem but I am running into issues on the mi.Invoke. The exception that I receive is "Exception has been thrown by the target of an invocation." With an Inner Exception "Object reference not set to an instance of an object". I have tried changing the code to (GetStatResponse)mi.Invoke(new Test(), null), with no luck. Test being the class.
I'm open to other suggestions as to how to resolve this, I just thought reflection might be the easiest.
The Method that I am calling with my testing is defined as
public GetStatResponse TestMethod()
{
GetStatResponse returnValue = new GetStatResponse();
Stat stat = new Stat();
Stat.Label = "This is my label";
Stat.ToolTip = "This is my tooltip";
Stat.Value = "this is my value";
returnValue.Stat = stat;
return returnValue;
}

Because you are not specifying BindingFlags in your GetMethod() call, you are only going to be returned methods matching the name containing request.ServiceMethod that are PUBLIC.
Check whether the method you are trying to invoke is public, otherwise MethodInfo will return null.
If it is not public, either make the method public or include the BindingFlags.NonPublic flag.
Also, you should always make sure that mi != null before calling mi.Invoke

Before calling the method you might want to make sure that the MethodInfo you are pulling through reflection is not null:
MethodInfo mi = this.GetType().GetMethod(
request.ServiceMethod,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase
);
// Make sure that the method exists before trying to call it
if (mi != null)
{
returnValue = (GetStatResponse)mi.Invoke(this, null);
}
After your update it seems that the exception is thrown inside the method you are calling:
GetStatResponse returnValue = new GetStatResponse();
// Don't forget to initialize returnValue.Stat before using it:
returnValue.Stat = new WhateverTheTypeIs();
returnValue.Stat.Label = "This is my label";

Related

Unit test NavigationCmdletProvider's NewDrive method

I'm attempting to create a unit test for the NewDrive method for a class that implements the NavigationCmdletProvider abstract class:
[TestMethod()]
[DeploymentItem("PsFoo.dll")]
public void NewDriveTest()
{
// arrange
FooProvider_Accessor target = new FooProvider_Accessor();
ProviderInfo providerInfo = ?;
PSDriveInfo drive = new PSDriveInfo("FOO", providerInfo, "FOO:\\", null, null);
PSDriveInfo actual;
// act
actual = target.NewDrive(drive);
// assert
Assert.IsInstanceOfType(actual,typeof(FooDriveInfo));
}
Unfortunately, I can't seem to find a way to create the ProviderInfo instance, as it's a protected property of the FooProvider.
What am I missing?
You could solve it using Reflection (untested):
// fetch the property "ProviderInfo" from the type "FooProvider".
PropertyInfo property =
typeof(FooProvider).GetProperty("ProviderInfo", BindingFlags.Instance | BindingFlags.NonPublic);
// fetch the property's value (of the object "target").
FooProvider providerInfo = (FooProvider)property.GetValue(target);
You may have to adapt the type information or property name, as I do not know how they are actually named inside your codebase.

WPF call a method that takes parameters from another dll

How can I run a method that takes parameters from another dll?
I import a UserControl from another dll as below but I now either need to call a method within that UserContol or have the ability to set a variable that's contained in that class.
Load UserControl
UserControl ucSupportButton =
new Bootstrapper().LoadUserControl("SC.Support.dll", "Button");
Code used in Bootstrapper
public UserControl LoadUserControl(string dllName, string loadType)
{
if (File.Exists(Path.Combine(applicationRoot, dllName)))
{
Assembly asm = Assembly.LoadFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), dllName));
Type[] types = asm.GetTypes();
Type type = types.Where(t => t.Name.Equals(loadType)).FirstOrDefault();
if (type != null)
{
return Activator.CreateInstance(type) as UserControl;
}
}
return null;
}
#HighCore comment seems like the best way to go. Depending on your design, reflection is another option. You can use reflection to get a method or field in that type and then call or set it.
var method = paymentObjectInstance.GetType().GetMethod("MethodNameHere",
BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (method == null)
{
return null;
}
var result = method.Invoke(paymentObjectInstance, null);
Here's a little overview of reflection courtesy of MSDN.

Call a generic non-static method with dynamic type and generic callback as parameter

Developing an app for Android (and later iOS) using Xamarin/Mono. Normally I use this code to call a non-static generic method and it works great:
serverService.GetCustomListObject<T> (firstRequestInLine,
null,
onGetCustomListObjectFromThread<T>,
onGetCustomListObjectFromThreadError);
where the callbacks are defined as:
private void onGetCustomListObjectFromThread<T> (List<T> list,
RequestStateGen<T>.SuccessfullDelegateType successDel
{ ... }
and
private void onGetCustomListObjectFromThreadError (String error,
WebRequest failedRequest)
{ ... }
However, now I need to call GetCustomListObject<t> where t is set dynamically. I am quite new to generics but have tried the following code from other examples without success:
typeof(ServerService).GetMethod ("GetCustomListObject").MakeGenericMethod (t).Invoke (serverService, new object[] {
firstRequestInLine,
null,
typeof(LocalServerService).GetMethod ("onGetCustomListObjectFromThread").MakeGenericMethod (t),
typeof(LocalServerService).GetMethod ("onGetCustomListObjectFromThreadError")
});
where LocalServerService is the class all my examples here are in and serverService is of type ServerService
I get the following error:
Error: Ambiguous matching in method resolution
Edit: GetCustomListObject in ServerService:
public void GetCustomListObject<T> (WebRequest request,
RequestStateGen<T>.SuccessfullDelegateType successDelegate,
RequestStateGen<T>.InternalSuccessDelegateType internalSuccessDelegate,
RequestStateGen<T>.ErrorDelegateType errorDelegate)
In your original code, you were calling a method passing in delegates.
In your reflection code, you appear to be passing in MethodInfo values instead - I don't believe they will automatically be converted to delegates.
Unfortunately it's hard to give a good code sample without knowing the declaration of your GetCustomListObject method, but you want something like:
Type thirdArgType = typeof(Foo<>).MakeGenericGenericType(t);
MethodInfo thirdArgMethod = typeof(LocalServerService)
.GetMethod("onGetCustomListObjectFromThread",
BindingFlags.Instance | BindingFlags.NonPublic)
.MakeGenericMethod(t);
Delegate thirdArg = Delegate.CreateDelegate(thirdArgType, this, thirdArgMethod);
MethodInfo fourthArgMethod = typeof(LocalServerService)
.GetMethod("onGetCustomListObjectFromThreadError",
BindingFlags.Instance | BindingFlags.NonPublic);
Delegate fourthArg = Delegate.CreateDelegate(typeof(Bar), this, fourthArgMethod);
MethodInfo method = typeof(ServerService).GetMethod("GetCustomListObject")
.MakeGenericMethod (t);
method.Invoke(serverService,
new object[] {firstRequestInline, null, thirdArg, fourthArg });

Beginner's reflection issues

I'm trying to learn reflection in C# and need some help with my code. I've had trouble finding good code examples/guides, so I apologize if my code is poorly done.
Essentially I'm just trying to check out a given assembly dll for a particular method name (path and method name have been redacted).
The problem occurs on the line object lateBoundObj = asm.CreateInstance(typeName); and it reads An object reference is required for the non-static field, method, or property...
I understand this has to do with static vs non-static and creating a new Assembly or something along those lines, but need some help understanding the issue and how to fix it.
Thank you!
public const string assemblyPath = #"<my file path>";
Assembly asm;
static void Main(string[] args)
{
//asm = new Assembly();
Console.Read();
MethodInfo mi;
object result = null;
object[] arguments = new object[] { "ABC123" };
try
{
Assembly assemblyInstance = Assembly.LoadFrom(assemblyPath);
Type[] types = assemblyInstance.GetTypes();
foreach (Type t in types)
{
mi = t.GetMethod("<my method name>");
if (mi != null)
{
string typeName = t.FullName;
object lateBoundObj = asm.CreateInstance(typeName);
result = t.InvokeMember("GetWeb", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, lateBoundObj, arguments);
break;
}
}
//set return for find method
}
catch (Exception ex) { }
}
The problem is that you're never assigning a value to asm, so it's got the default value of null. Perhaps you meant to use assemblyInstance instead?
In fact, I wouldn't use Assembly.CreateInstance or Type.FullName at all there - I'd use:
object lateBoundObj = Activator.CreateInstance(t);
Also note, you should always avoid code like this:
catch (Exception ex) { }
Always at least log the exception. Ideally, don't catch an exception you can't really "handle" at all.
asm variable is never assigned. You should call CreateInstance on assemblyInstance instead.

Exception from DynamicMethod.CreateDelegate, almost identical MSDN example

When i call CreateDelegate(delegateType) i get a System.ArgumentException, which according to MSDN is because the delegateType has the wrong number of parameters or the wrong parameter types.
The strange part is the code I'm using is almost all copied from MSDN. My function as whole:
public static void AssertRaisesEvent(Action action, object obj, string eventName, NumberOfTimes numberOfTimesRaised)
{
eventCounter = 0;
EventInfo eventInfo = obj.GetType().GetEvent(eventName);
Type tDelegate = eventInfo.EventHandlerType;
Type returnType = GetDelegateReturnType(tDelegate);
if (returnType != typeof(void))
throw new ApplicationException("Delegate has a return type.");
var handler =
new DynamicMethod("CompletedHandler",
typeof(int),
GetDelegateParameterTypes(tDelegate),
obj.GetType());
// Generate a method body. This method loads a string, calls
// the Show method overload that takes a string, pops the
// return value off the stack (because the handler has no
// return type), and returns.
//
ILGenerator ilgen = handler.GetILGenerator();
FieldInfo counterFieldInfo = typeof (AssertionHelpers).GetField("eventCounter",
BindingFlags.NonPublic | BindingFlags.Static);
ilgen.Emit(OpCodes.Ldfld, counterFieldInfo);
ilgen.Emit(OpCodes.Ldc_I4, 1);
ilgen.Emit(OpCodes.Add);
ilgen.Emit(OpCodes.Pop);
ilgen.Emit(OpCodes.Ret);
// Complete the dynamic method by calling its CreateDelegate
// method. Use the "add" accessor to add the delegate to
// the invocation list for the event.
//
var delParams = GetDelegateParameterTypes(tDelegate);
var handlerParams = handler.GetParameters();
Delegate dEmitted = handler.CreateDelegate(tDelegate);
eventInfo.GetAddMethod().Invoke(obj, new Object[] { dEmitted });
...
As you can see the comments are even there. As you also can see i have delParams and handlerParams variables which have the same number of parameters of the same type.
What is going on here?
MSDN: http://msdn.microsoft.com/en-us/library/ms228976.aspx
EDIT:
The event im trying to bind to:
private NullTransaction transaction;
public delegate void CompletedEventHandler(object testParam);
internal class NullTransaction : ITransaction
{
public event CompletedEventHandler Completed;
public void Dispose()
{
// no implementation
}
public void Complete()
{
// no implementation
if(Completed != null)
Completed.Invoke(this);
}
}
Most events don't return anything - in fact you assert that it has no return-type. You then declare your custom method (handler) as returning int, and try to bind it to a delegate that doesn't return an int. This won't work.
Also; your stack isn't valid for returning an int, since you "pop" the result.
i.e. I created a test with
public event EventHandler SomeEvent;
and bound to it; so then here:
Delegate dEmitted = handler.CreateDelegate(tDelegate);
you'll find that tDelegate is EventHandler. That doesn't match handler, which returns int.
Re the stack (comments); consider:
ilgen.Emit(OpCodes.Ldfld, counterFieldInfo); <=== should be ldsfld, by the way
ilgen.Emit(OpCodes.Ldc_I4, 1); // stack is now [counter] [1]
ilgen.Emit(OpCodes.Add); // stack is now [counter + 1]
ilgen.Emit(OpCodes.Pop); // stack is now empty
ilgen.Emit(OpCodes.Ret); // return
You've loaded two values, added them up, thrown the result away, and then returned. But you haven't returned the int that you claim to - this will fail IL inspection.
If you change:
var handler =
new DynamicMethod("CompletedHandler",
null,
GetDelegateParameterTypes(tDelegate),
obj.GetType());
and:
ilgen.Emit(OpCodes.Ldsfld, counterFieldInfo);
ilgen.Emit(OpCodes.Ldc_I4_1);
ilgen.Emit(OpCodes.Add);
ilgen.Emit(OpCodes.Stsfld, counterFieldInfo);
ilgen.Emit(OpCodes.Ret);
then it might work as you intend.
Also; this is simpler:
Delegate dEmitted = handler.CreateDelegate(tDelegate);
eventInfo.AddEventHandler(obj, dEmitted);

Categories