Speeding up Reflection Invoke C#/.NET - c#

There are plenty of posts on speeding up reflection invokes, examples here:
Speeding up Reflection API with delegate in .NET/C#
https://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
and here:
Example : Speeding up Reflection API with delegate in .NET/C#
My question is about speeding up generic invokes. Is this possible at all?
I've got an abstract class and a class which implements it...
public abstract class EncasulatedMessageHandler<T> where T : Message
{
public abstract void HandleMessage(T message);
}
public class Handler : EncasulatedMessageHandler<MyMessageType>
{
public int blat = 0;
public override void HandleMessage(MyMessageType message) { blat++; }
}
What I want to do is build up a list of these message handler classes and quickly invoke their HandleMessage()
At the moment, I'm doing something that's approximately this:
object handler = Activator.CreateInstance(typeof(Handler)); // Ignore this, this is done up front.
MethodInfo method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
Action<object> hook = new Action<object>(delegate(object message)
{
method.Invoke(handler, new object[] { message });
});
// Then when I want to invoke it:
hook(new MyMessageType());
That's not the whole thing, but it's the important stuff...
The method.Invoke is very slow, I'd like to keep the generic parameters on the class, I realise I could lock this down to object and cast it in the HandleMessage method, but I'm trying to avoid doing this.
Is there anything I can do to speed this up? It's currently orders of magnitude slower than direct calls.
Any help would be appreciated.

Are you using C# 4? If so, dynamic may speed things up:
Action<object> hook = message => ((dynamic)handler).HandleMessage((dynamic)message);

Using Delegate.CreateDelegate() should be a lot faster. You will end up with a pointer to the real function, not a delegate that calls Invoke().
Try this:
object handler = Activator.CreateInstance(typeof(Handler));
var handlerType = handler.GetType();
var method = handlerType.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var paramType = handlerType.GetGenericArguments()[0];
// invoke the MakeHandleMessageDelegate method dynamically with paramType as the type parameter
// NB we're only doing this once
Action<object> hook = (Action<object>) this.GetType().GetMethod("MakeHandleMessageDelegate")
.MakeGenericMethod(paramType)
.Invoke(null, new [] { handler });
In the same class add the following generic method. We invoke this dynamically above because we don't know the type parameter at compile time.
public static Action<object> MakeHandleMessageDelegate<T>(object target)
{
var d = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), target, "HandleMessage");
// wrap the delegate another that simply casts the object parameter to the required type
return param => d((T)param);
}
You then have a delegate that casts the parameter to the required type, then calls the HandleMessage method.

You can use Delegate::CreateDelegate. This is significantly faster than Invoke().
var handler = Activator.CreateInstance(typeof(Handler));
var method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var hook = (Action<object>)Delegate.CreateDelegate(typeof(Action<object>), handler, method);
// Then when you want to invoke it:
hook(new MyMessageType());
Feel free to benchmark it, but I have benched it before and it was significantly faster.
Edit: I see your problem now, you can't do it the way I suggested.
You can use Expressions to compile a delegate that does the invoke for you, this will be very fast:
var type = typeof(Handler);
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("HandleMessage", BindingFlags.Instance | BindingFlags.Public);
var originalType = type;
// Loop until we hit the type we want.
while (!(type.IsGenericType) || type.GetGenericTypeDefinition() != typeof(EncasulatedMessageHandler<>))
{
type = type.BaseType;
if(type == null)
throw new ArgumentOutOfRangeException("type");
}
var messageType = type.GetGenericArguments()[0]; // MyMessageType
// Use expression to create a method we can.
var instExpr = Expression.Parameter(typeof(object), "instance");
var paramExpr = Expression.Parameter(typeof(Message), "message");
// (Handler)instance;
var instCastExpr = Expression.Convert(instExpr, originalType);
// (MyMessageType)message
var castExpr = Expression.Convert(paramExpr, messageType);
// ((Handler)inst).HandleMessage((MyMessageType)message)
var invokeExpr = Expression.Call(instCastExpr, method, castExpr);
// if(message is MyMessageType) ((Handler)inst).HandleMessage((MyMessageType)message);
var ifExpr = Expression.IfThen(Expression.TypeIs(paramExpr, messageType), invokeExpr);
// (inst, message) = { if(message is MyMessageType) ((Handler)inst).HandleMessage((MyMessageType)message); }
var lambda = Expression.Lambda<Action<object, Message>>(ifExpr, instExpr, paramExpr);
var compiled = lambda.Compile();
Action<Message> hook = x => compiled(instance, x);
hook(new MyMessageType());
Edit: Apart from my Expression example above, the following will also work - and is what I do in these types of scenarios.
var instance = (IEncapsulatedMessageHandler)Activator.CreateInstance(typeof(Handler));
instance.HandleMessage(new MyMessageType());
public class Message { }
public class MyMessageType : Message { }
public interface IEncapsulatedMessageHandler
{
void HandleMessage(Message message);
}
public abstract class EncasulatedMessageHandler<T> : IEncapsulatedMessageHandler where T : Message
{
public abstract void HandleMessage(T message);
void IEncapsulatedMessageHandler.HandleMessage(Message message)
{
var msg = message as T;
if (msg != null)
HandleMessage(msg);
}
}
public class Handler : EncasulatedMessageHandler<MyMessageType>
{
public override void HandleMessage(MyMessageType message)
{
Console.WriteLine("Yo!");
}
}

If you know the signature, use Delegate.CreateDelegate.
If you don't know the signature, it's very tricky to get something that's fast. If you need speed, then whatever you do, try to avoid Delegate.DynamicInvoke which is extremely slow.
(Note that "slow" is very relative here. Make sure you really need to optimize this. DynamicInvoke is something like 2.5 million invocations per second (on my machine), which is very likely fast enough. The implementation below is more like 110+ million invocations per second and is faster than Method.Invoke.)
I found an article that discusses a way to do it (invoke a method fast without knowing the signature at compile time). Here is my version of the implementation. The weird issue is that you could build a lambda which represents the invocation, but you would not know the signature of that lambda and would have to call it dynamically (slowly). But instead, you can bake the strongly typed invocation into the lambda, with the lambda representing the act of invocation rather than the specific method itself. (The lambda ends up being a Func<object, object[], object> where you pass an object and some values and get back the return value.)
public static Func<object, object[], object> ToFastLambdaInvocationWithCache(
this MethodInfo pMethodInfo
) {
Func<object, object[], object> cached;
if (sLambdaExpressionsByMethodInfoCache.TryGetValue(pMethodInfo, out cached))
return cached;
var instanceParameterExpression = Expression.Parameter(typeof(object), "instance");
var argumentsParameterExpression = Expression.Parameter(typeof(object[]), "args");
var index = 0;
var argumentExtractionExpressions =
pMethodInfo
.GetParameters()
.Select(parameter =>
Expression.Convert(
Expression.ArrayAccess(
argumentsParameterExpression,
Expression.Constant(index++)
),
parameter.ParameterType
)
).ToList();
var callExpression = pMethodInfo.IsStatic
? Expression.Call(pMethodInfo, argumentExtractionExpressions)
: Expression.Call(
Expression.Convert(
instanceParameterExpression,
pMethodInfo.DeclaringType
),
pMethodInfo,
argumentExtractionExpressions
);
var endLabel = Expression.Label(typeof(object));
var finalExpression = pMethodInfo.ReturnType == typeof(void)
? (Expression)Expression.Block(
callExpression,
Expression.Return(endLabel, Expression.Constant(null)),
Expression.Label(endLabel, Expression.Constant(null))
)
: Expression.Convert(callExpression, typeof(object));
var lambdaExpression = Expression.Lambda<Func<object, object[], object>>(
finalExpression,
instanceParameterExpression,
argumentsParameterExpression
);
var compiledLambda = lambdaExpression.Compile();
sLambdaExpressionsByMethodInfoCache.AddOrReplace(pMethodInfo, compiledLambda);
return compiledLambda;
}

No, that is (sadly) not possible. Reflection is slow and MethodInfo.Invoke() is no exception. Couldn't you use (generic) Interfaces and thus direct calls?
Edit update: One thing comes to mind to really speed this up, but the coding overhead is massive: You can use dynamic code generation and compilation. That would mean dynamically building the source code that would call the method without reflection, dynamically compiling and executing this. This would mean an initially performance impact for creating and compiling the classes that do your work, but then you have direct calls for every subsequent calls.

Related

C# Compiled expression to create new instance of T and copy values to its properties from another instance of T

I would like to know if it is possible to create an instance of a type known only at runtime and assign values to the properties of this instance by using compiled expressions and if so how it is to be done.
I have a generic class with a method which accepts an instance of T and returns a copy. T is only known at runtime or rather is user/consumer defined. I know how to do so with reflection (assuming it has an empty constructor in this example and without exception handling or null checks for simplification).
public class MyClass<T>
{
public T CreateCopy(T source)
{
var type = typeof(T);
var copy = type.GetConstructor(Type.EmptyTypes).Invoke(null);
foreach(var pi in type.GetProperties())
{
pi.SetValue(copy, pi.GetValue(source));
}
return copy;
}
}
Reflection is quite expensive and after some digging i found an option to at least create an instance of T with compiled expressions.
var type = typeof(T);
Expression.Lambda<Func<T>>(Expression
.New(type.GetConstructor(Type.EmptyTypes)
?? throw new InvalidOperationException(
$"Type has to have an empty public constructor. {type.Name}")))
.Compile();
After some benchmarking i have found out that it performs around 6 times faster than the CreateCopy(...) method. The thing is that i do not know which type will be passed in as a generic and how many properties it will have.
Is there a way to do all of the operations from CreateCopy(...) method with compiled expressions?
Ihave looked into Expression.Asign, Expression.MemberInit but i am not able to find anything appropriate. The problem with Expression.MemberInit ist that it expects to have an Expresssion.Bind and Expression.Constant but i cant get the values of the properties from the passed instance of T into it. Is there a way?
Thank you.
P.S. So i am looking for something like:
var type = typeof(T);
var propertyInfos = type.GetProperties();
var ctor = Expression.New(type.GetConstructor(Type.EmptyTypes));
var e = Expression.Lambda<Func<T, T>>(Expression
.MemberInit(ctor, propertyInfos.Select(pi =>
Expression.Bind(pi, Expression.Constant(pi.GetValue(source)))))).Compile();
You are almost there. What you need is to define a parameter and then assign the properties with property access expression like below :
public static T Express<T>(T source)
{
var parameter = Expression.Parameter(typeof(T), "source");
var type = typeof(T);
var ctor = Expression
.New(type.GetConstructor(Type.EmptyTypes));
var propertyInfos = type.GetProperties();
var e = Expression
.Lambda<Func<T, T>>(
Expression
.MemberInit(ctor, propertyInfos.Select(pi =>
Expression.Bind(pi, CanBeAssigned(pi.PropertyType)
? (Expression)Expression.Property(parameter, pi.Name)
: Expression.Call(typeof(Program).GetMethod(nameof(Express))
.MakeGenericMethod(pi.PropertyType),
Expression.Property(parameter, pi.Name)
))
)),
parameter
);
var x = e.Compile();
var z = x(source);
return z;
}
public static bool CanBeAssigned(Type t)
{
return t.IsValueType || t.Name == "String"; // this might need some improvements
}

How to check method exists in C# with certain particular signature?

I want to check if the method for certain parameters is implemented. In this scenario, I have for example these method overloads:
public class Transformations
{
public string TransformFrom(string s) { return s;}
public string TransformFrom(int i) { return "00" + i.ToString();}
public string TransformFrom(DateTime dt) { return
DateTime.ToString("MM/dd/yyyy HH:mm:ss.fff");}
}
Suppose I have decimal like:
object obj = 1M;
If I now call TransformFrom(obj), I get an exception.
Other part of my program returns unfortunately only objects, which really are concrete types like int or datetime. And I want to transform some of these objects to string so that those can be written to the log. So this is a runtime problem. Also I want that my Transformations-class is general enough to be used in other programs too, so there can be objects of any type.
Is there fast way to find out that this method overload does not exist?
Either way you are currently going to get a compile time error, even if there was an overload that accepted a decimal. You can approach this one of 2 ways depending on your needs:
To resolve this at compile time you have to cast to the correct type.
object obj = 1;
var objAsInt = (int) obj;
var result = transformationInstance.TransformFrom(objAsInt);
If there is no proper overload you will get a compile time error and you can resolve this at design time.
To resolve this at runtime use reflection to figure out if there is an overload of the type and if there is pass the instance.
object obj = 1;
var underlyingType = obj.GetType();
var method = typeof(Transformations).GetMethod("TransformFrom", new Type[] { underlyingType });
if(method != null)
{
var result = method.Invoke(transformationInstance, new []{obj});
}
It is possible to find out whether a given overload exists using reflection:
public static bool HasOverloadForArgument(Type targetType, string methodName, object arg)
{
var methodInfo = targetType.GetMethod(name: methodName, types: new[] { arg.GetType() });
return methodInfo != null;
}
Live sample
I'm not sure what is the whole idea here as there won't be much you can do when the transformation is not available during runtime.
Maybe, you'd just be best off using dynamic to avoid all the reflection stuff and caching required otherwise, e.g.
var boxedInt = (object)1;
var boxedFloat = (object)1f;
dynamic dynamicInt = boxedInt;
dynamic dynamicFloat = boxedFloat;
var intResult = new Transformations().TransformFrom(dynamicInt); // works
var floatResult = new Transformations().TransformFrom(dynamicFloat); // throws binder exception

Call dynamic method from string

I'm trying to call a method from a dynamic without knowing its name. I have difficulties to explain this in english so there's the code:
public void CallMethod(dynamic d, string n)
{
// Here I want to call the method named n in the dynamic d
}
I want something like:d.n() but with n replaced by the string.
I want this :
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod(TheCommandString);
theMethod.Invoke(this, userParameters);
but with dynamic.
If you need the context to help you: I'm make an application that's support "mods", you put DLLs in the mod folder and it loads it and execute it. It works with dynamic (I have a dictionnary like this : Dictionnary<string, dynamic> instances;). I want the application to get the methods name from the library (with instances["topkek"].GetMethods();, I've already made this method) but then call the method with the string it returns. I don't know if what I said mean something (I'm french :/ )...
I'm using VS 2013 Express with the .Net framework 4.5, if you need more information to help me ask me.
you can write your method as follows -
public void CallMethod(dynamic d, string n)
{
d.GetType().GetMethod(n).Invoke(d, null);
}
If all methods are void, this could work. Otherwise you need to change it a bit.
public void CallMethod(string className, string methodName)
{
object dynamicObject;
// Here I want to call the method named n in the dynamic d
string objectClass = "yourNamespace.yourFolder." + className;
Type objectType = Type.GetType(objectClass);
if (objectType == null)
{
// Handle here unknown dynamic objects
}
else
{
// Call here the desired method
dynamicObject = Activator.CreateInstance(objectType);
System.Reflection.MethodInfo method = objectType.GetMethod(methodName);
if (method == null)
{
// Handle here unknown method for the known dynamic object
}
else
{
object[] parameters = new object[] { }; // No parameters
method.Invoke(dynamicObject, parameters);
}
}
}
I want to add another approach as solution:
In your case, the caller (developer of the mod) knows the method to call. Thus, this might helpful:
// In the main application:
public dynamic PerformMethodCall(dynamic obj, Func<dynamic, dynamic> method)
{
return method(obj);
{
// In a mod:
mainProgram.PerformMethodCall(myDynamicObj, n => n.myDynamicMethod());
// In another mod:
mainProgram.PerformMethodCall(myDynamicObj, n => n.anotherMethod());
This is a further development of the idea of Yuval Itzchakov in his commentary. He had suggested using a delegate.

Dynamically cast object to a type, when type is unknown at compile time

I have a method for fetching data from database, and it is generic:
public static IQueryable<T> GetData<T>(IQueryable<T> data, some more parameters)
data is unfiltered collection of db entities, and GetData does filtering, sorting, skipping, taking upon that collection...
When I provide variable of type IQueryable (T being, for example, Document) as first parameter, as I usually do, it, of course, works:
IQueryable<Document> data = ...
GetData<Document>(data, ....);
Now, I have a need to "calculate" the first parameter dynamically. For that I use LINQ Expressions which will evaluate into IQueryable, but I dont know which T at compile time. I was thinking something like this:
Expression db = Expression.Constant(new DataModelContainer());
Expression table = Expression.Property(db, tbl); /* tbl = "Documents", this is the whole point */
Type type = table.Type.GetGenericArguments()[0];
Expression call = Expression.Call(typeof(Queryable), "AsQueryable", new Type[] { type }, table);
object o = Expression.Lambda(call, null).Compile().DynamicInvoke();
At this point o INDEED IS IQueryable (IQueryable), and as such should be able to serve as an argument to GetData. But, I have only 'object' reference to it, and naturally, cannot use it like that.
So, my question is: Is there any way to dynamically cast 'o' to 'IQueryable' when o is exactly that. I know that cast is compile time thing, but I am hoping someone has a workaround of some sort. Or maybe I am trying too much.
You can make use of the dynamic feature. Dynamic is great for situations where you already have to do reflection:
dynamic o = Expressin.Lambda(...
Get a load of this fellah:
First. We presume the class surrounding your GetData < T > method is called Foo:
public static class Foo {
public static IQueryable<T> GetData<T>(IQueryable<T> data, int bar, bool bravo) {
// ... whatever
}
Then we try to reflect upon the MethodInfo of GetData < > (and by that I mean the actual template, generic definition, not a closed particularization of it). We try to obtain that (and succeed) at the birth of the Foo class.
private static readonly MethodInfo genericDefinitionOf_getData;
static Foo() {
Type prototypeQueryable = typeof(IQueryable<int>);
// this could be any IQuerable< something >
// just had to choose one
MethodInfo getData_ForInts = typeof(Foo).GetMethod(
name: "GetData",
bindingAttr: BindingFlags.Static | BindingFlags.Public,
binder: Type.DefaultBinder,
types: new [] { prototypeQueryable, typeof(int), typeof(bool) },
modifiers: null
);
// now we have the GetData<int>(IQueryable<int> data, int bar, bool bravo)
// reffered by the reflection object getData_ForInts
MethodInfo definition = getData_ForInts.GetGenericMethodDefinition();
// now we have the generic (non-invokable) GetData<>(IQueryable<> data, int bar, bool bravo)
// reffered by the reflection object definition
Foo.genericDefinitionOf_getData = definition;
// and we store it for future use
}
Then we write a non-generic variant of the method which should call the specific generic method with regard to the actual element type being sent as a parameter:
public static IQueryable GetDataEx(IQueryable data, int bar, bool bravo) {
if (null == data)
throw new ArgumentNullException("data");
// we can't honor null data parameters
Type typeof_data = data.GetType(); // get the type (a class) of the data object
Type[] interfaces = typeof.GetInterfaces(); // list it's interfaces
var ifaceQuery = interfaces.Where(iface =>
iface.IsGenericType &&
(iface.GetGenericTypeDefinition() == typeof(IQueryable<>))
); // filter the list down to just those IQueryable<T1>, IQueryable<T2>, etc interfaces
Type foundIface = ifaceQuery.SingleOrDefault();
// hope there is at least one, and only one
if (null == foundIface) // if we find more it's obviously not the time and place to make assumptions
throw new ArgumentException("The argument is ambiguous. It either implements 0 or more (distinct) IQueryable<T> particularizations.");
Type elementType = foundIface.GetGenericArguments()[0];
// we take the typeof(T) out of the typeof(IQueryable<T>)
MethodInfo getData_particularizedFor_ElementType = Foo.genericDefinitionOf_getData.MakeGenericMethod(elementType);
// and ask the TypeSystem to make us (or find us) the specific particularization
// of the **GetData < T >** method
try {
object result = getData_particularizedFor_ElementType.Invoke(
obj: null,
parameters: new object[] { data, bar, bravo }
);
// then we invoke it (via reflection)
// and obliviously "as-cast" the result to IQueryable
// (it's surely going to be ok, even if it's null)
return result as IQueryable;
} catch (TargetInvocationException ex) {
// in case of any mis-haps we make pretend we weren't here
// doing any of this
throw ex.InnerException;
// rethink-edit: Actually by rethrowing this in this manner
// you are overwriting the ex.InnerException's original StackTrace
// so, you would have to choose what you want: in most cases it's best not to rethrow
// especially when you want to change that which is being thrown
}
}
}

Passing a value using Expression Trees does not work

I am working on a function that takes a delegate type and a delegate of type Action<Object[]> and creates a dynamic function of the given type, that passes, if called, all arguments to the given action handle:
public static T GetEventDelegate<T>(Action<Object[]> handler) where T : class
{
if (!typeof(T).IsSubclassOf(typeof(Delegate)))
throw new Exception("T must be a delegate type");
Type[] argTypes = typeof(T).GetMethod("Invoke").GetParameters().Select((para) => para.ParameterType).ToArray();
List<ParameterExpression> lstArgs = new List<ParameterExpression>(
argTypes.Select((arg)=>Expression.Parameter(arg))
);
ParameterExpression result = Expression.Variable(typeof(Object[]));
var assignExpression = Expression.NewArrayInit(typeof(Object),lstArgs.ToArray());
var callExpression = Expression.Call(handler.Method, result);
var block = Expression.Block(
new List<ParameterExpression>(){result},
new Expression[]{assignExpression,callExpression}
);
var del = Expression.Lambda(block, lstArgs.ToArray()).Compile();
return Delegate.CreateDelegate(typeof(T), del, "Invoke") as T;
}
private static void testDel()
{
var del = GetEventDelegate<EventHandler>(
(x) =>
{
//Error, because x == null
Debug.Print(x.ToString());
}
);
del("testString", new EventArgs());
}
Unfortunately the action handler only gets a null value passed (see testDel()).
Could you please help me to find the error?
Thanks in advance!
Your problem is because you initialize the result ParameterExpression as type Object, but never actually assign it a value. What this pretty much compiles down to (after calling compile) is:
void Func(arguments..)
{
Object result;
new object[](arguments...);
method(result);
}
You never actually assign the array to the result with an assign expression.
Unrelated to your problem, you could use Expression.Lambda() when creating the lambda because you have the type from the generic.

Categories

Resources