Getting the concrete class of a method called inside a delegate in C# - c#

My situation is as follows - a delegate of the form
() => _instanceOfMyClassWhichImplementsInterfaceIX.MyMethod()
is passed as a parameter to a certain method. Inside that method I need to get both the name of the method called in the delegate (in this case "MyMethod") and the actual class of the object (in this case "MyClass") _MyInstanceOfClassWhichImplementsInterfaceIX . Using the method described by user Stipo in his answer to Find the name of the invoked method of a Func delegate I was able to get the name of the method and the name of the interface ("IX" in case), but not the name of the concrete class of the object. Its to done by calling the method "GetCalledMethods" in his code, which returns a liste of MethodBase and calling methodBaseInstance.ReflectedType.Name on it.
How can i do it?

You are better off making the method accept an expression, it will make it easier to gather the info you need. Here is a way you could do that, the interface can be gotten just as easy as here I am getting the actual MethodInfo class, and the actual type it belongs to.
void Main()
{
var _instanceOfMyClassWhichImplementsInterfaceIX = new MyClass();
Expression<Func<bool>> y = () => _instanceOfMyClassWhichImplementsInterfaceIX.MyMethod();
var methodInfo = ((MethodCallExpression)y.Body).Method;
var methodName = methodInfo.Name;
var methodDeclaringType = methodInfo.DeclaringType;
Console.WriteLine(methodName);
Console.WriteLine(methodDeclaringType);
Console.WriteLine(y.Compile().Invoke());
Console.WriteLine(methodDeclaringType.GetInterface(nameof(IMyClass)));
}
public class MyClass : IMyClass
{
public bool MyMethod() => true;
}
public interface IMyClass { }
EDIT: Added to better answer the users question
// If you want to make the expression while referencing as a interface it will stick
// to the expression, meaning we cant get the underlying type from it.
// The easy way around this is trivial just pass the underlying type as a generic with a constraint.
// If you MUST not pass in type T you can do this same method,
// but it cant be inferred when using the method is all.
public void MethodDoThis<T>(IMyClass myclass)
where T : IMyClass
{
Expression<Func<bool>> y = () => myclass.MyMethod<MyClass>();
var methodInfo = ((MethodCallExpression)y.Body).Method;
var methodName = methodInfo.Name;
var methodDeclaringType = methodInfo.DeclaringType;
Console.WriteLine("Method Name: " + methodName);
Console.WriteLine("Method Declaring Type: " + typeof(T));
Console.WriteLine("Method Return Value: " + y.Compile().Invoke());
Console.WriteLine("Method Defined Interface: " + typeof(T).GetInterface(nameof(IMyClass)));
}

Related

C# Determine Generic Type Parameter at Runtime

If a named class exists, I want to pass that class as the type parameter to a generic method. Otherwise I want to pass a different type. I cannot figure out how to pass the type parameter to the generic method.
// Does this type exist?
Type objType = Type.GetType(typeof(ModelFactory).Name + "." + content_type + "Model");
// if not, use this type instead
if (objType == null)
{
objType = typeof(GenericModel);
}
// what to pass as the generic type argument?
var other = query.Find<objType>().ContinueWith((t) =>
Is it possible? What do I pass to Find in the last line instead of objType?
Thanks & regards,
-John
You must use the Reflection API. Once you get the argument type for your Find method, you need to get a MethodInfo from the Find method and pass an instance of the class that defines that method and the necessary parameters for the method, an example:
public class GenericModel {}
// This class simulates the class that contains the generic Find method
public class Query {
public void Find<T>() {
Console.WriteLine("Invoking Find method...");
}
}
class Program {
static async Task Main(string[] args) {
var theType = typeof(GenericModel);
// Obtaining a MethodInfo from the Find method
var method = typeof(Query).GetMethod(nameof(Query.Find)).MakeGenericMethod(theType);
var instanceOfQuery = Activator.CreateInstance(typeof(Query));
var response = method.Invoke(instanceOfQuery, null); // Cast the method to your return type of find.
Console.ReadLine();
}
}

How can get the type of nested generic type

There is a third-party component library like this:
public static class GenericExcuteTestClassExtension
{
public static void Excute<T>(this GenericExcuteTestClass clazz,
string parameter, Action<ReturnClass<T>> callback)
{
ReturnClass<T> rClazz = new ReturnClass<T>(parameter);
rClazz.Property5 = typeof(T).ToString();
callback.Invoke(rClazz);
}
public static void Excute<T>(this GenericExcuteTestClass clazz,
string parameter, Action<ReturnClass> callback)
{
ReturnClass rClazz = new ReturnClass(parameter);
rClazz.Property5 = typeof(T).ToString();
callback.Invoke(rClazz);
}
}
I want to reflect to invoke the methodExcute<T>(this GenericExcuteTestClass clazz, string parameter, Action<ReturnClass<T>> callback).
I use thetypeof(GenericExcuteTestClassExtension).GetMethod("Excute", new Type[] { typeof(GenericExcuteTestClass), typeof(string), typeof(Action<ReturnClass<>>)}), but the compiler get the error "Type expected". How can I get type of (Action<ReturnClass<>>), Action<> can compliled, but it's not my expected.
I want to pass the a custom action<ReturnClass<>> like (result)=>{....} to the method, how can I do it?
Please help ,thanks.
Why I use reflect to execute this ?
Because this method must execute in aop intercept
this real situation is like this:
I want to use restsharp in my app, and I write an interface like
[RestfulService(Constants.BASE_URL + "/login")]
public interface UserService
{
[Request("/login")]
void Login([Paramter] string name, [Paramter] string password, Action<T> callBack);
}
and Intercept the interface to get the parameter to execute restsharp ExecuteAsync<T>(this IRestClient client, IRestRequest request, Action<IRestResponse<T>> callback) to get data.
So I need to pass the T in UserService to ExecuteAsync<T> in Intercept method public void Intercept(IInvocation invocation) of castle.windsor, in this method body, we only can get GenericType's Type cannnot get T, so if I directly call ExecuteAsync, I cannot pass the GenericType T to this method. I must use like this:...GetMethod("...").MakeGenericType(new Type[]{piLast.ParameterType.GenericTypeArguments})
The whole problem comes from the fact, that nested generic types are not well handled by the reflection system in .NET.
The simplest solution in your case is to filter the methods yourself. A quick&dirty snippet:
MethodInfo method = null;
foreach (var m in typeof(GenericExcuteTestClassExtension)
.GetMethods(BindingFlags.Public | BindingFlags.Static))
{
var parameters = m.GetParameters();
if (!parameters.Any())
continue;
var lastParameterType = parameters.Last().ParameterType;
var genericArgument = lastParameterType
.GetGenericArguments()
.SingleOrDefault();
// you can/should add more checks, using the Name for example
if (genericArgument != null && genericArgument.IsGenericType)
{
method = m;
break;
}
}
You should probably make an utility method from this. A general approach allowing to search for any method with nested generics can be found here. There is also another possibility using Expressions here.

What is the simplest and cheapest way to dynamicly get method name in C#?

I would like to put a mathod name into a string but I also don't want use hard-coded value. Instead, I'd like to obtain the name dynamicly by reflection. I've used the following, working statement:
"The method is called " + new Action(MyMethod).Method.Name;
I think that creating an Action delegate is semantically inappropriate. It suggest that there will be a method invocation but instead, there will be a reflection. I'm looking for something like typeof operator or GetType for class but on method level.
Is the pattern Delegate.Method.Name act as the best and standard approach to achieve my goal?
I meant not current method.
MethodInfo.CurrentMethod should give you the name of current method
"The method is called " + MethodInfo.GetCurrentMethod().Name;
use MethodBase.GetCurrentMethod()
Currently the best solution:
Create static class ReflectionExtensionMethods:
public static class ReflectionExtensionMethods
Add several methods for Action, Action<T>, etc., Func<T>, Func<T1, T2> etc. Here is an example of an Action:
public static string GetMethodName(this Type #this, Expression<Action> expression)
{
return GetMethodNameInternal(#this, expression);
}
The internal part that checks whether given expression and its body is valid:
private static string GetMethodNameInternal(Type #this, MethodCallExpression bodyExpression)
{
if (bodyExpression == null)
throw new ArgumentException("Body of the exspression should be of type " + typeof(MethodCallExpression).Name);
var member = bodyExpression.Method;
if (member.MemberType != MemberTypes.Method)
throw new ArgumentException("MemberType of the exspression should be of type " + MemberTypes.Method);
if (!object.Equals(#this, member.DeclaringType))
throw new ArgumentException("Invalid property owner.");
return member.Name;
}
Usage for instance member:
var owner = new Foo();
var methodName = typeof(Foo).GetMethodName(() => owner.VoidMethod());
Usage for static memeber:
var methodName = typeof(Foo).GetMethodName(() => Foo.StaticVoidMethod());
ReflectionExtensionMethods may be further complemented by methods that will return the names of properties and other memebers.
Here is the first approach.
Create a static class called MethodInfo (same name as System.Reflection.MethodInfo). Same name is reasoned due to the fact, that you rarely need to explicitly refer to the original type. However, you naturally look for the solution right there.
public static class MethodInfo
{
public static System.Reflection.MethodInfo From(Func<string, int> func)
{
return func.Method;
}
// Other members for Action<T>, Action<T1, T2> etc.
// Other members for Func<T>, Func<T1, T2> etc.
}
Consider there is a class MyClass, that has MyMethod method:
class MyClass
{
static int MyMethod(string s) { return default(int); }
}
Use the class and its members as follows (The key part):
"The method is called " + MethodInfo.From(MyClass.MyMethod).Name;
That is more self descriptive, easier to use and concise than:
"The method is called " + new Func<string, int>(MyClass.MyMethod).Method.Name

Returning System.Action from static method on generic type with types defined at runtime

Below is a very paired down example of what I am trying to achieve
public class CoolClass<T>
{
public static void DoSomethingCool()
{
// Insert cool generic stuff here.
List<T> coolList = new List<T>();
}
}
public class OtherClass
{
public Action ReturnActionBasedOnStaticGenericMethodForType(Type type)
{
// Ideally this would just be
return CoolClass<type **insert magic**>.DoSomethingCool
}
}
I know if the type is known I can do following and it will return System.Action
return CoolClass<string>.DoSomethingCool
I know if all I wanted to do was invoke the method I can do
Type baseType = typeof(CoolClass<>);
Type[] typeArguments = new [] {type}
Type constructedType = baseType.MakeGenericType(typeArguments);
MethodInfo method = constructedType.GetMethod("DoSomethingCool");
method.Invoke(null,null);
I maybe down the wrong path all together. It seems like I am trying go get method to be a reference to DoSomethingCool method. I am wishing for something like (Action) method.
You're nearly there - you just need Delegate.CreateDelegate:
Action action = (Action) Delegate.CreateDelegate(typeof(action), null, method);

Using Common Delegate to call multiple methods across different classes

I need to pass a delegate and a method name that the delegate should invoke as an argument to a class constructor how do i do this ??
i.e if
public delegate object CCommonDelegate();
is my delegate and say it can call any methods following this signature
string Method1();
object Method2();
class X
{
public X(CCommonDelegate,"MethodName to invoke"){} //how to pass the Method name here..
}
P.S : Ignore the access modifiers
A delegate is a variable that holds something that can be called. If X is a class that needs to be able to call something, then all it needs is the delegate:
public delegate object CommonDelegate();
class X
{
CommonDelegate d;
public X(CommonDelegate d)
{
this.d = d; // store the delegate for later
}
}
Later it can call the delegate:
var o = d();
By the way, you don't need to define such a delegate. The type Func<Object> already exists and has the right structure.
To construct X given your two example methods:
string Method1()
object Method2()
You could say
var x = new X(obj.Method2);
Where obj is an object of the class that has Method2. In C# 4 you can do the same for Method1. But in 3 you'll need to convert using a lambda:
var x = new X(() => obj.Method1);
This is because the return type is not exactly the same: it's related by inheritance. This will only work automatically in C# 4, and only if you use Func<object>.
why not just have your constructor take an Func< object>
public class x
{
public x(Func<object> func)
{
object obj = func();
}
}
then
x myX = new x(()=> "test");

Categories

Resources