Unable to find private void generic function with GetMethod - c#

I have a function with the following signature:
private void Foo<TPoco>(IContext context, List<TPoco> pocos, DateTime modifiedDateTime)
where TPoco : MyAbstractClass
And I cannot find this function in GetMethods().
Based on this SO post ( GetMethod for generic method ), I have tried these binding flags:
GetType().GetMethods(BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance
| BindingFlags.Static
| BindingFlags.FlattenHierarchy
)
And this finds 14 other methods in the class, but not this one. It does find this method:
protected void Bar<TContext, TPoco>(List<TPoco> pocosToPersist, TContext context)
where TContext : IContext, new()
where TPoco : MyAbstractClass
So the only difference is the access level - but then I can see other private functions.
Even if I change the binding flags to something simpler (which, from what I understand, shouldn't make new items visible):
GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance )
I still don't see the function.

As the comments on the post point out, the code should have worked. The issue is that the class I am defining the function in is abstract, so I wasn't able to find the private function.
If I do this.GetType().BaseType.GetMethods( BindingFlags.NonPublic | BindingFlags.Instance), the function shows up as expected.

I wasn't having an issue with the return void type, but having the same symptoms with GetMethods() - i.e. it would not return the method.
I found GetRuntimeMethods() instead, and that included the generic method I was looking for.
In terms of wider understanding and other ways to approach this - this thread (I think) is more relevant: How do I use reflection to call a generic method?

Related

How to find private static methods in static class using reflection?

I have a static class and I want to find its private static methods using typeof(MyStaticClass).GetMethods() but it always shows me the public methods only.
How can I achieve this?
Use the overload of GetMethods that includes a BindingFlags parameter:
var methods = typeof(MyStaticClass)
.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
(I haven't included BindingFlags.Instance as you've explicitly said it's a static class; to find all methods in any class, include that as well.)

How to call a method in an abstract class

public abstract class BaseClass
{
protected virtual int getValue() { return 1; }
}
I want to call getValue method.
typeof(BaseClass)
.GetMethod("getValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.Invoke(null, new object[] { });
This code has a error.
Non static method requires a target
However, I cannot create instance of BaseClass because it is abstract class.
So, I am using dummy class which extends BaseClass.
class DummyClass : BaseClass { }
typeof(BaseClass)
.GetMethod("getValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.Invoke(new DummyClass(), new object[] { });
I don't want to create dummy class every time if possible.
Is there a better way?
I agree with the other comments that this should not be production code, but out of fun it can certainly be done:
public static T CreateAbstractInstance<T>() where T : class =>
(T)Activator.CreateInstance(
Thread.GetDomain()
.DefineDynamicAssembly(new AssemblyName("DynamicAssembly"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("DynamicModule")
.DefineType("DynamicType", TypeAttributes.Public | TypeAttributes.Class, typeof(T))
.CreateType());
private static TResult AbstractInvoke<TClass, TResult>(string methodName) where TClass : class
{
var method = typeof(TClass).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
var elegate = method.CreateDelegate(typeof(Func<BaseClass, TResult>));
return (TResult)elegate.DynamicInvoke(CreateAbstractInstance<TClass>());
}
private static void Main()
{
var result = AbstractInvoke<BaseClass, int>("getValue");
Console.WriteLine(result);
}
There is probably some method to trick the compiler and invoke it without even creating an instance, but I was getting too many Visual Studio crashes to carry on investigating other methods. Expressions seems to lead nowhere as at the end of the day, it still had to generate valid code so no way to trick an expression into an invalid lambda.
If you reuse a singleton instance from CreateAbstractInstance then you shouldn't have overheads after the first object is created (beside reflection usage if you invoke non public methods).
I thought I might add this to the answer as well:
I notice the comment about using it in a unit test; if you are using Moq (and probably most of the decent frameworks), you can do this:
var bc = new Mock<BaseClass>().Object;
// Invoke whatever you want on `bc` with reflection or not.
Although be aware that if the method is virtual it will automatically override it so you won't get by default the base class logic, but it can be solved setting up the mock.
You can try using an open instance delegate. Try this:
var method = typeof(BaseClass).GetMethod("getValue");
var func = (Func<BaseClass, int>) Delegate.CreateDelegate(typeof(Func<BaseClass, int>), method);
int result = func(null);
Note: The above technique works by omitting the hidden this parameter in the member call. This will only work if your method does not need to access the instance. If you attempt to access the instance, you will get a null reference exception.

Get protected property value of base class using reflection

I would like to know if it is possible to access the value of the ConfigurationId property which is located in the base class of the object and it's private. I have tried to do it with reflection with no luck.
To access ConfigurationId property i have used following code:
SubsetController controller = new SubsetController(new CConfigRepository(new FakeDataContextRepository()));
var myBaseClassProtectedProperty =
controller.GetType().BaseType
.GetProperty("CCITenderInfo", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(controller);
var myProtectedProperty =
CCITenderInfo.GetType()
.GetProperty("ConfigurationId", BindingFlags.Public | BindingFlags.Instance)
.GetValue(myBaseClassProtectedProperty);
Assuming the following parent and child class:
class BaseClass
{
private string privateField = "I'm Private";
}
class ChildClass : BaseClass
{
}
You can read privateField's value from a ChildClass instance using reflection like this:
ChildClass childInstance = new ChildClass();
object privateFieldValue = childInstance.GetType().BaseType
.GetField("privateField", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(childInstance);
Console.WriteLine(privateFieldValue); // I'm Private
To add to this answer - you should use the Instance and NonPublic binding flags for sure, but you should also ensure that you are actually referencing properties and not fields.
E.g. if you have
protected string Andrew;
You will not be able to get this via GetProperty, no matter what binding flags you use. Why - because it is a field, and not a property...
To fix this, just change it to
protected string Andrew {get;set;}
and then you can use the GetProperty method.
Yes, this is possible with reflection.
However, in order to look up nonpublic members, you'll need to use the reflection overload which take BindingFlags parameters. In order to look up private members, you'll also need to access via the typeof the base class, even when using BindingFlags.FlattenHierarchy. This also means you'll need to use the exact binding, however note that contradictory flags (such as using both NonPublic and Public) are valid and will return either at that point.
Be aware that the very need to look up nonpublic members could be considered code smell, and you should do so very carefully. Also be aware that nonpublic members are not guaranteed to have the same names across different versions.

Why does GetMethod need BindingFlags as mandatory information in order to find methods?

Assuming I have this class with a private method:
public class Test
{
private void Method()
{
}
}
And this code:
var method1 = typeof(Test).GetMethod("Method"); // null
var method2 = typeof(Test).GetMethod("Method", BindingFlags.NonPublic | BindingFlags.Instance); // works!!
var method3 = typeof(Test).GetMethod("Method",BindingFlags.Instance); // null
Why are method1 and method3 null?
Why do I have to be specific with the BindingFlags in order to actually get the method? If it's because I can have multiple methods with the same name then what does the GetMethods exist for?
How specific do I need to be? In this case I needed to add that I'm looking for a non-public & instance method. Since not all of the BindingFlags values are straight forward, how do I know where I need to stop?
The Private modifier means "hide this method from outsiders", so by default GetMethods() returns only the public members.
1.method1 and method3 are null because it is specifically mentioned in this MSDN link that "You must specify Instance or Static along with Public or NonPublic or no members will be returned."
2.For using reflection you must know exactly what you are looking for otherwise you might get the wrong method to invoke.
3.As I already mentioned in No.1 answer, you must at-least specify "Instance or Static along with Public or NonPublic".

GetMethod returning null

I have an asp.net web page. This is the class implementing the page:
public partial class _Default : System.Web.UI.Page
{
private readonly string delegateName = "DynamicHandler";
protected void Page_Load(object sender, EventArgs e)
{
EventInfo evClick = btnTest.GetType().GetEvent("Click");
Type tDelegate = evClick.EventHandlerType;
MethodInfo method = this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance);
Delegate d = Delegate.CreateDelegate(tDelegate, this, method);
MethodInfo addHandler = evClick.GetAddMethod();
Object[] addHandlerArgs = { d };
addHandler.Invoke(btnTest, addHandlerArgs);
}
private void DynamicHandler(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
I am trying to hook up an event handler dynamicly. For some reason method remains null and I can't figure out why. I have done this many times before and I can't figure out what I'm missing.
EDIT: I found that this.GetType() returns the type of the page ASP.default_aspx and not the actual type implementing the page. I don't really know how to get around this...
For the benefit of anyone else, GetMethod() can also return null if the arguments you passed do not match the arguments of the method you are trying to find. So, for example, if you are trying to find the method:
SomeMethod(int intParam, string stringParam)
You need to pass the parameter types to GetMethod:
type.GetMethod("SomeMethod", new[] { typeof(int), typeof(string) });
Or, if you want to specify special binding flags:
type.GetMethod("SomeMethod", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(int), typeof(string) }, null);
As you've discovered in your edit, the actually ASPX page gets compiled into a class that inherits from _Default (where your code is located). So you need to make DynamicHandler (at least) protected rather than private.
Specify BindingFlags.FlattenHierarchy also:
this.GetType().GetMethod("DynamicHandler",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
There are two things to be aware of.
(1) When you use:
this.GetType()
or equivalently just GetType(), the type which is returned is the actual run-time type of the actual instance. Since _Default is a non-sealed class, that type might very well be a more derived (more specialized type) than _Default, i.e. some class which has _Default as its direct or indirect base class.
If what you want is always the "constant" type _Default, use the typeof keyword, so use:
typeof(_Default)
instead of GetType(). This alone would solve your problem.
(2) Even if you specify BindingFlags.NonPublic, inherited private members are not returned. With your choice of binding flags, private methods declared in the same class (the derived class) are returned, but private methods inherited from base classes are not returned. However with internal and protected members, both the ones declared in the class itself and the ones declared in the base classes are returned.
This might make some sense, since a private method is not meant to be invoked from a derived class.
Changing the access level of your DynamicHandler method from private to e.g. protected (as suggested in the other answer) would be enough to solve your problem, as inherited protected members are selected when you use BindingFlags.NonPublic.
It is still interesting that you can't get the inherited private members with BindingFlags. Related thread C#: Accessing Inherited Private Instance Members Through Reflection. It is possible to write a method that searches all base types, of course, like:
static MethodInfo GetPrivateMethod(Type type, string name)
{
MethodInfo retVal;
do
{
retVal = type.GetMethod(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
if (retVal != (object)null)
break;
type = type.BaseType;
} while (type != (object)null);
return retVal;
}
That alone would also have solved your problem.

Categories