How can get the type of nested generic type - c#

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.

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

Faster calling of methods using reflection

I'm porting over some old code from AS3 (via Haxe) to C#.
Parts of the code are transpiled, others I have manually rewritten in C#. One of these parts is the event dispatching.
I have event listeners registering to an event dispatcher, all listeners have a signature like this:
public void handleSomething(Event e)
// they may also use a subclass of Event as a parameter
public void handleAnother(MouseEvent e)
The events keep a small amount of data and a type:
public class Event {
public const string ENTER_FRAME = "enter_frame";
public const string RESIZE = "resize";
public const string CHANGE = "change";
readonly string type;
public Event(string type) {
this.type = type;
}
}
I keep a list keyed on the particular event type (a string, due to legacy reasons), once an event is dispatched I find the appropriate handlers keyed with that string and call the them with the event data.
I am currently using reflection to do this, but it is proving to be prohibitively slow. I have found several threads that share this problem.
My particular issue is that the method signature varies, if it was always an Event as a parameter I could use the solutions provided, but alas.
I'd be fine with trading some memory/time at setup to get subsequent calls to be faster. I can get a reference to the method and work out what type it expects, but I'm unsure how to store and call this later?
You can create and compile LINQ expression for each handler method and cache it for future use.
public class CompiledDelegate
{
// Assume that there is one one method per handler class type, add method name to dictionary key if necessary
private static Dictionary<Type, CompiledDelegate> _Cache = new Dictionary<Type, CompiledDelegate>();
public static CompiledDelegate Get(Type handlerType, string methodName)
{
CompiledDelegate result;
if (!_Cache.TryGetValue(handlerType, out result))
{
var method = handlerType.GetMethod(methodName);
// determine type of single method parameter
var paramType = method.GetParameters().Single().ParameterType;
// create expression tree (object h, object p) => ((handlerType)h).MethodName((paramType)p)
var exprHandler = Expression.Parameter(typeof(object), "h");
var exprParam = Expression.Parameter(typeof(object), "p");
var lambda = Expression.Lambda(
Expression.Call(
Expression.TypeAs(exprHandler, handlerType), // instance, cast object to handlerType
method, // method
Expression.TypeAs(exprParam, paramType) // parameter, cast object to paramType
),
exprHandler, exprParam // lamda params
);
result = new CompiledDelegate()
{
Method = method,
// compile expression
Compiled = (Action<object, object>)lambda.Compile()
};
_Cache.Add(handlerType, result);
}
return result;
}
public MethodInfo Method { get; private set; }
public Action<object, object> Compiled { get; set; }
}
Once you have hander instance, you can call its method via compiled delegate:
CompiledDelegate.Get(handler.GetType(), "handlerSomething").Compiled(handler, mouseEvent)
You can pre-generate CompiledDelegate for each of handlers and add to the dispatch table together with handlers themselves.
Calling method via compiled delegate (once it's compiled of course) is approximately 10 times faster then calling same method via reflection.

Generic class where type can Parse strings

I want to create a generic class where the type of the class can Parse strings.
I want to use this class for any class that has a static function Parse(string),
like System.Int32, System.Double, but also for classes like System.Guid. They all have a static Parse function
So my class needs a where clause that constraints my generic type to types with a Parse function
I'd like to use it like this:
class MyGenericClass<T> : where T : ??? what to do ???
{
private List<T> addedItems = new List<T>()
public void Add(T item)
{
this.AddedItems.Add(item);
}
public void Add(string itemAsTxt)
{
T item = T.Parse(itemAsTxt);
this.Add(item);
}
}
What to write in the where clause?
I was not happy with the answers that would use reflection to do the Parsing.
I prefer a solution that is type safe, so the compiler would complain about the a missing Parse function.
Normally you would constraint to a class that has an interface. But as others said, there is no common interface. Come to think of it I don't need an interface, I need a function that I can call
So my solution would be to insist that creators would provide a delegate to the Parse Function that would parse a string to type T
class MyGenericClass<T>
{
public MyGenericClass(Func<string, T> parseFunc)
{
this.parseFunc = parseFunc;
}
private readonly Func<string, T> parseFunc;
public void Add(string txt)
{
this.Add(parseFunc(txt));
}
}
Usage:
MyGenericClass<Guid> x = new MyGenericClass<Guid>(txt => Guid.Parse(txt));
MyGenericClass<int> y = new MyGenericClass<int> (txt => System.Int32.Parse(txt));
The answer is simpler than I thought
I might be misunderstanding your question, but will this do the trick?
static void Main(string[] args)
{
Guid g = DoParse<Guid>("33531071-c52b-48f5-b0e4-ea3c554b8d23");
}
public static T DoParse<T>(string value)
{
T result = default(T);
MethodInfo methodInfo = typeof(T).GetMethod("Parse");
if (methodInfo != null)
{
ParameterInfo[] parameters = methodInfo.GetParameters();
object classInstance = Activator.CreateInstance(typeof(T), null);
object[] parametersArray = new object[] { value };
result = (T)methodInfo.Invoke(methodInfo, parametersArray);
}
return result;
}
You can´t do that at compile-time at all. All those methods don´t have anything in common except their names. They neither are defined in any common interface nor have they the same parameters.
Imagine you have your own method that accidently has that name, but does something completely different. In addition it´s also an instance-method:
class MyType
{
void Parse() { ... }
}
As you can see that method don´t even has any argument, making it hard to find any common logic between - say - int.Parse(myString)andmyInstanceOfMyType.Parse()`.
But even if you could do that. What would you do with the item? There´s not much as there´s nothing in common between them. In particular it´s impossible to call the methpd, as they are completely different.
You could loop all types with a similar method at runtime however:
var types = allAssemblies.SelectMany(x => x.GetTypes())
.Where(x => x.GetMethod("Parse") != null);
But be aware that this yields to an AmbiguousMatchException if more than one method per type exists with the name, this is when the method is overloaded.

Get concrete type from method expression

If I have an expression in the form of Expression<Func<Delegate>> is it possible to determine the derived type of the object used to pass in the delegate? Does the expression even contain this information, or is it exclusively representative of the delegate.
A code example should make things clearer.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Sandbox {
public interface IContract {
void Method();
}
public class Concrete : IContract {
public void Method() { }
}
public class Test {
private IContract contract = new Concrete();
private Concrete concrete = new Concrete();
public static string GetFullMethodName(Expression<Func<Action>> expression) {
var unaryExpression = (UnaryExpression)expression.Body;
var methodCallExpression = (MethodCallExpression)unaryExpression.Operand;
var methodInfoExpression = (ConstantExpression)methodCallExpression.Arguments.Last();
var methodInfo = (MemberInfo)methodInfoExpression.Value;
var type = methodInfo.DeclaringType;
var name = methodInfo.Name;
return String.Format("{0}.{1}", type, name);
}
public Test() {
var strConcrete = GetFullMethodName(() => concrete.Method); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(() => contract.Method); // Sandbox.IContract.Method
}
}
}
Is it possible to make () => contract.Method produce
Sandbox.Concrete.Method
Instead of
Sandbox.IContract.Method
Can the expression be altered to support this, or would I be forced to pass an instance of the object as a separate parameter in order to determine it's type?
No, that isn't possible.
The expression tree is built based on compile-time information, and at compile-time, the method being invoked is the virtual IContract.Method. The fact that at runtime, the Concrete.Method is actually invoked is irrelevant - that's handled in the virtual dispatch mechanism and the compiler finished its job long before any of this is decided.
The best you can do is try to emulate virtual dispatch yourself. For example, you could try enumerating the interface implementation on the this instance at runtime, and if you do find a method that matches the interface, you'd return that. However, this is certainly tricky - you need to be able to perfectly emulate the actual virtual dispatch.
Another tricky point is that the way you're trying to get the value is already broken. For example, in my environment, the methodInfoExpression is not a ConstantExpression - it's a field on a closure type. Your "parsing" is very fragile.
That said, it's also kind of unnecessary and overcomplicated - you're trying to receive an expression that returns an action and "steal" the value of the action out of the expression. There's already a simple way of doing that - pass that argument directly. No need to hide it in an expression tree:
public static string GetFullMethodName(Action action)
{
return string.Format("{0}.{1}", action.Method.DeclaringType.Name, action.Method.Name);
}
var strConcrete = GetFullMethodName(concrete.Method).Dump(); // Sandbox.Concrete.Method
var strContract = GetFullMethodName(contract.Method).Dump(); // Sandbox.Concrete.Method
You don't need expressions for things that basic reflection already gives you :)

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

Categories

Resources