I am reading and writing data to and from a file. The data in the file can be floats, doubles, ints etc. The type is not known until runtime. I will refer to data type stored in the file as Tin. Data is read into or written from arrays of type Tout. This type too is not known until runtime.
The code sequence is something like this. In the Open method Tin and Tout are known, we can create read and write methods for the known data types.
Open(...)
{
MethodInfo ReadMethod = typeof(...)GetMethod("ReadGeneric").MakeGenericMethod(new Type[] {typeof(Tin), typeof(Tout)}));
}
The read write loops repeat millions of times and rely on reflection to invoke the appropriate methods as shown below.
Read loop
{
var values = (Tout[])ReadMethod.Invoke(this,new object[]{index});
process ...
}
When examining this code using a performance profiler I find that c collosal amount if time is spent just invoking the runtime read write methods.
How do I speed this up.
Yes, this is due to the fact that the reflection API is thousands of times slower than direct method calls. There are some interesting techniques to work around this however. Check out Jon Skeet's article on using delegates to cache reflection.
There is a static setup cost but once you have done that the time to invoke the delegate repeatedly is equivalent to virtual method calls.
There are also some pre-packaged frameworks to achieve the same thing.
This'll do anything for ya, almost as fast as a direct call.
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
public class FastMethodInfo
{
private delegate object ReturnValueDelegate(object instance, object[] arguments);
private delegate void VoidDelegate(object instance, object[] arguments);
public FastMethodInfo(MethodInfo methodInfo)
{
var instanceExpression = Expression.Parameter(typeof(object), "instance");
var argumentsExpression = Expression.Parameter(typeof(object[]), "arguments");
var argumentExpressions = new List<Expression>();
var parameterInfos = methodInfo.GetParameters();
for (var i = 0; i < parameterInfos.Length; ++i)
{
var parameterInfo = parameterInfos[i];
argumentExpressions.Add(Expression.Convert(Expression.ArrayIndex(argumentsExpression, Expression.Constant(i)), parameterInfo.ParameterType));
}
var callExpression = Expression.Call(!methodInfo.IsStatic ? Expression.Convert(instanceExpression, methodInfo.ReflectedType) : null, methodInfo, argumentExpressions);
if (callExpression.Type == typeof(void))
{
var voidDelegate = Expression.Lambda<VoidDelegate>(callExpression, instanceExpression, argumentsExpression).Compile();
Delegate = (instance, arguments) => { voidDelegate(instance, arguments); return null; };
}
else
Delegate = Expression.Lambda<ReturnValueDelegate>(Expression.Convert(callExpression, typeof(object)), instanceExpression, argumentsExpression).Compile();
}
private ReturnValueDelegate Delegate { get; }
public object Invoke(object instance, params object[] arguments)
{
return Delegate(instance, arguments);
}
}
Profile to find the solution that matches your expectations :
.Net Framework offers plenty of methods to invoke dynamically methods. However they don't perform equally in terms of performance and they are not equally easy to use.
CreateDelegate may be what you're looking for
In the recent versions of .Net Framework, CreateDelegate beat by a factor 50 the MethodInfo invoke:
// The following should be done once since this does some reflection
var method = typeof (...).GetMethod("ReadGeneric");
// Here we create a Func that targets the instance of type which has the
// ReadGeneric method
var func = (Func<Tin, Tout[]>)_method.CreateDelegate(typeof(Func<Tin, Tout[]>), target);
// Func will be 50x faster than MethodInfo.Invoke
// use func as a standard Func like
// var tout = func(index);
Check this post of mine to see benchmark on different method invocations
Related
I'm trying to create a kind of object factory to instantiate a type implementing a specific interface where the type to instantiate is not known before runtime and I'm trying to achive this without using reflection. I've found some examples sugesting this might be possible using Expressions but I've not managed to find an example that works for my case. Might be that it's simply not possible but I wanted to throw the question out here to make sure.
So what I have this far is this:
public static Func<Type, object[], IMyInterface> FactoryExpression =
Expression.Lambda<Func<Type, object[], IMyInterface>>(
/* Something that creates an instance of the type with given arguments */
).Compile()
public static IMyInterface GetTypeOfMyInterface()
{
Type t = Type.GetType(GetTypeNameFromSomewhere());
ConstructorInfo c = t.GetConstructors().First();
object[] args = ResolveCostructorArguments(c.GetParameters());
return FactoryExpression(t, args);
}
I have little exprience with these types of Expressions. Is it at all possible to get this to work or do I have to fall back to reflection?
EDIT:
By using Jon Hanna's example I came up with the following:
public class TypeInitializer<TResult>
{
private static readonly ConcurrentDictionary<string, Func<object[], TResult>> InstanceCreationMethods =
new ConcurrentDictionary<string, Func<object[], TResult>>();
public static TResult CreateInstance(ConstructorInfo constructorInfo, params object[] arguments)
{
ParameterInfo[] parameterInfo = constructorInfo.GetParameters();
IEnumerable<Type> parameterTypes = parameterInfo.Select(p => p.ParameterType);
string constructorSignatureKey = GetConstructorSignatureKey(constructorInfo.DeclaringType, parameterTypes);
Func<object[], TResult> factoryMethod = InstanceCreationMethods.GetOrAdd(constructorSignatureKey, key =>
{
Expression[] args = new Expression[parameterInfo.Length];
ParameterExpression param = Expression.Parameter(typeof(object[]));
for (int i = 0; i < parameterInfo.Length; i++)
args[i] = Expression.Convert(Expression.ArrayIndex(param, Expression.Constant(i)), parameterInfo[i].ParameterType);
return Expression
.Lambda<Func<object[], TResult>>(Expression.Convert(Expression.New(constructorInfo, args), typeof(TResult)), param)
.Compile();
});
return factoryMethod(arguments);
}
private static string GetConstructorSignatureKey(Type type, IEnumerable<Type> argumentTypes) => string.Concat(type.FullName, " (", string.Join(", ", argumentTypes.Select(at => at.FullName)), ")");
}
Which seems to work exacly as intended! Thanks a lot for that.
For the sake of experimenting I also made an implementation using Activator.CreateInstance as well as constructorInfo.Invoke and built som performance tests to see the difference..
00:00:00.9246614, Actiator
00:00:00.7524483, Constructor Invoke
00:00:00.8235814, Compiled Expression
This test timed the creation of 100 000 instances of the same type using each method and printed the result. I was a bit supprised to see that Constructor Invoke method seams to perform better!
You can use Expression.New to create the instance.
You will also need to pass the ConstructorInfo to your factory, and use Expression.Convert to cast the object to the interface.
public static Func<object[], IMyInterface> BuildFactoryExpression(ConstructorInfo ctor)
{
ParameterInfo[] par = ctor.GetParameters(); // Get the parameters of the constructor
Expression[] args = new Expression[par.Length];
ParameterExpression param = Expression.Parameter(typeof(object[])); // The object[] paramter to the Func
for (int i = 0; i != par.Length; ++i)
{
// get the item from the array in the parameter and cast it to the correct type for the constructor
args[i] = Expression.Convert(Expression.ArrayIndex(param, Expression.Constant(i)), par[i].ParameterType);
}
return Expression.Lambda<Func<object[], IMyInterface>>(
// call the constructor and cast to IMyInterface.
Expression.Convert(
Expression.New(ctor, args)
, typeof(IMyInterface)
), param
).Compile();
}
Yes I've solved this kind of issue with reflection as well which is fairly simple. But in this case I'm looking to avoid the performance loss if at all possible.
This is still using reflection. If you are going to use the same Func repeatedly and you are running in a context where Compile() compiles to IL (e.g. not UWP) then you may gain here because reflection is used once to create a re-usable delegate, and from then on it's much the same as if you'd written the delegate as a C# method. You'll gain even more if you can type your arguments rather than passing an object[] and have to cast from that.
If you are using these delegates once at a time, you'd be as well to just use reflection. If you are only going to be in a context where delegates from expressions are interpreted, then it's going to have to use reflection internally anyway.
I am using reflection to call methods, and invoking the methods using Invoke() doesn't do it for me, too slow. I generate thousands - millions of method calls, it is a test automation tool. At compile time I have no clue about the method name, parameter type(s) or return type. So Jon Skeet's article on using delegates to cache reflection is no help here.
Here is what I have:
foreach (MethodInfo method in _methods)
{
foreach (var p in method.GetParameters())
{
var paramValue = Utils.RandomizeParamValue(p.ParameterType.Name);
parameters.Add(paramValue);
}
var result = method.Invoke(_objectInstance, parameters.ToArray());
//_objectInstance is the class instance of which the method is a member of.
}
I have researched the DLR (ExpandoObject, DynamicObject) but I am not sure it has what I am looking for. What I am looking for is a way to bypass the overhead of reflection, or cache method invocations, even if it turns out be an ugly hack. Is there a common hack that I have missed? Could I go down to IL level and do some tricks there?
One option is to use expression tree to build delegate that will call your methods. MSDN have introduction in Expression Trees article and in particular you'll need MethodCallExpression
Create an expression sample (from MethodCallExpression article):
string[,] gradeArray =
{ {"chemistry", "history", "mathematics"}, {"78", "61", "82"} };
var arrayExpression = Expression.Constant(gradeArray);
// Create a MethodCallExpression that represents indexing
// into the two-dimensional array 'gradeArray' at (0, 2).
// Executing the expression would return "mathematics".
var methodCallExpression = Expression.ArrayIndex(
arrayExpression,
Expression.Constant(0),
Expression.Constant(2));
Compile an expression to delegate sample (from main article):
Expression<Func<int, bool>> expr = num => num < 5;
Func<int, bool> result = expr.Compile();
Console.WriteLine(result(4));
The code below will compile but fails at runtime. It's provided just to give an idea of what I'm trying to do. What I would like to do is create a method that accepts a collection of objects (effectively an "untyped" collection) and if this collect is comprised of numbers of a single type return the mean using the Average() extension method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace nnConsole {
class Program {
static void Main(string[] args) {
var ints = new object[4] { 1, 2, 3, 4 };
var dbls = new object[4] { 1.0, 2.0, 3.0, 4.0 };
Console.WriteLine(ReallyMean(ints));
Console.WriteLine(ReallyMean(dbls));
}
static public double ReallyMean(ICollection<object> data) {
var unique = data.Distinct();
var types = unique.Select(x => x.GetType()).Distinct();
if (types.Count() == 1) {
if (types.First().IsValueType) {
/***********************
* magic here to create ddata var that will
* call the appropriate extension method for average */
dynamic ddata = data; // DOES NOT WORK
return ddata.Average();
}
}
return double.NaN;
}
}
}
I'm sure I could use reflection to find the appropriate Average method and invoke it (not pretty). Is there a shorter/cleaner/better way to do this? I can use the latest C# and .NET runtime.
Since your code always returns a double, what you are looking for is a lambda that translates your object to a double:
var res = data.Cast<dynamic>().Average(n => (double) n);
Note that your program would also compile without a Cast<dynamic>(), but it would fail at runtime unless the underlying data type is double.
Calling ddata.Average() will cause the dynamic runtime to try to find a proper member method on ICollection<object>. It doesn't do the translation to a static method call that an extension method really is underneath the syntactic sugar.
You can however rewrite it to call the extension method with normal syntax. That will allow dynamic overload resolution if there are many matching extension methods in the same class, but it will not allow automatic selection of overloads from different classes:
return Enumerable.Average(ddata);
That will bind to the correct overload of Average depending on the compile time type of the IEnumerable<T>. You are now using IEnumerable<object>, so I guess you will have to change that to IEnumerable<dynamic> to get it right.
Just get the type, and then cast to that type to get access to Average
if( types.First() == typeof(int) ){
return unique.Cast<int>().Average();
}else{
if( types.First() == typeof(double) ){
return unique.Cast<double>().Average();
}
}
How do you get the argument value supplied to a closed/constructed generic method?
It's been a while since I haven't touched Reflection. All this used to be at the back of my, umm, whatever.
class Program
{
static void Main(string[] args)
{
new ConcreteFoo().GenericMethod<int>(5);
Console.ReadKey();
}
}
class ConcreteFoo
{
public void GenericMethod<Q>(Q q)
{
var method = MethodInfo.GetCurrentMethod();
var parameters = method.GetParameters();
if (parameters.Length > 0)
foreach (var p in parameters)
Console.WriteLine("Type: {0}", p.ParameterType);
// That still prints Q as the type.
// I've tried GetGenericArguments as well. No luck.
// I want to know:
// 1) The closed type, i.e. the actual generic argument supplied by the caller; and
// 2) The value of that argument
}
public void GenericMethodWithNoGenericParameters<Q>()
{
// Same here
}
}
class GenericFoo<T>
{
public void NonGenericMethod(T t) { /* And here*/ }
public void GenericMethod<Q>(Q q) { /* And here */ }
}
UPDATE
This question is absurd and hence closed by the asker. He wishes to retain it just to show his children how stupid daddy was, if they ever turned out to be C# programmers.
The short answer is typeof(Q).
The long answer (which tries to explain why you can't enumerate these types and you must write them specifically) goes like this:
Each generic method (which is more generic than it's declaring class) has corresponding, distinct MethodInfo instances for all of its (ever) touched particularizations and another MethodInfo for the "template"/open method.
You could use this to obtain what you want:
class ConcreteFoo {
public void GenericMethod<Q>(Q q) {
var method = MethodInfo.GetCurrentMethod();
var closedMethod = method.MakeGenericMethod(typeof(Q));
// etc
}
}
Why is that ?
It's because none of the "enumerating operations" in reflection return MethodInfo instances that refer to closed particularizations.
If you enumerate the static methods declared by ConcreteFoo like so:
var atTime1 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
ConcreteFoo.GenericMethod( true );
var atTime2 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
you will get identical results.
As far as GenericMethod and it's entourage of particularizations are concerned, you will get only the reflection object associated with GenericMethod (open variant).
atTime2 will not contain an extra MethodInfo referring to the freshly jitted GenericMethod< bool >.
But that not's really a bad thing, now is it ?
GetMethods() should return consistent results and not have its results vary in time.
The algebra of generic methods is actually quite nice when it comes to it's "navigation" operations:
All open MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = true
All closed MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = false
By calling .GetGenericMethodDefinition() on a closed MethodInfo you get the open one
By calling .MakeGenericType(params Type[] types) on an open MethodInfo you get whatever closed one you want (without being syntactically aware of what those types are and with the possibility of receiving an exception for not respecting the where clauses)
The same goes for the reflection operations that come from the current thread's perspective (rather than from that of the assemblies and types):
MethodBase MethodInfo.GetCurrentMethod()
and
StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
select frame.GetMethod();
never return the actual closed variants of generic methods (if any)
that are actually on the top, or throughout the current call stack.
In a way your question is not absurd, because, while in the case of GetCurrentMethod
you could easily replace it with GetCurrentMethod plus MakeGenericMethod plus the syntactically available typeof(Whatever), you can't say that about your callers.
So.. for non-generic methods you can always look at your stack and know precisely what are those methods' parameter types. The methods that invoked each other and eventually yours got invoked... But for generic ones (which are really truly closed, for I repeat it is illogical to think that a generic method that runs and calls another and was called by someone else (etc) is an open one) you can't find out the types of the parameters just like you can't learn the values of any such methods' local variables (which are deterministic but it would be a great flaw in performance to make that a possibility).
I'm trying to test private methods in a Unit test project. So far it's going great, but I hit a bump, when I have to test a method with an out parameter. The signature for that method is:
private bool GotSSI(out SSI ssi, RSI rsi)
{
~code omitted~
}
And the unittest (the part that is not working) looks like this:
SSI ssi = null;
object[] p = new object[]{ssi,rsi};
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool) privateTarget.Invoke("GotSSI",t,p);
The GotSSI method work. I've tested it in debug mode within the unit test and I can see that the 'ssi' out variable is set inside the method, before returning it's true or false value. But when the test returns to it's own code, the 'ssi' variable is still null. So the problem is that the object I created in the "GotSSI" method, is not parsed out of the PrivateObject invoke method.
Anyone knows what I am missing?
Update (Solution by Rafal)
Rafal's solution work perfectly and here is how I implemented the solution.
I created a delegate:
delegate bool GotSSIInternal(out SSI ssi, RSI rsi);
And when I have created the object I wanted to test, I build the delegate (target is the object i'm testing):
GotSSIInternal gotSSIInternal = (GotSSIInternal) Delegate.CreateDelegate(
typeof (GotSSIInternal),
target,
typeof(OfflineResolver).GetMethod("GotSSI", BindingFlags.NonPublic | BindingFlags.Instance));
After that is very simple to call the delegate:
actual = gotSSIInternal.Invoke(out ssi, rsi);
The solution is very simple and works like a charm.
Although the final solution that was accepted works, there is a much simpler way to do it. If you follow the link given in the accepted answer from Rafal, you will find a similar question to this one, with two answers. The second answer (with the most "useful" points) is the simpler of the two.
Here is a modified version of that answer specifically for a testing scenario:
//method to test is a private method of the class ClassTotest with signature
// TryGetCustomerData(List<Invoice> invoices, out CustomerData customerData)
//set up
var objToTest = new ClassToTest();
var invoices = GetInvoices();
CustomerData customerData = null;
//set up the arguments
var args = new object[] { invoices, customerData };
//get the MethodInfo of the method you want to test
var method = typeof(ClassToTest).GetMethod("TryGetCustomerData",
BindingFlags.NonPublic | BindingFlags.Instance);
//invoke it
var success = (bool)method.Invoke(objToTest, args);
//get back the customerData argument - the "out" parameter
var actual = args[1] as CustomerData;
your invocation of method with out parameter is wrong if you want to get the out value. See this on how to invoke it with reflection.
You need to ask yourself if you really need to test private methods? I personally do not test Private methods but it is all down to personal opinion (and it can get quite heated). There are numerous reasons / articles / opinions. A good SO thread can be found here.
An excerpt from the accepted answer is "A private method is an implementation detail that should be hidden to the users of the class. Testing private methods breaks encapsulation..."
The reason I do not test my private methods is because they are more likely to change than the public interface. If you cover all of your private methods it makes refactoring more complex (again, just my opinion). If you change a private method and the Public interface breaks you will know as your unit tests fail and you can then drill down.
That is just my opinion and I know many disagree so just putting it out there!
I can use PrivateObject to do this, although it is not technically a "return value", like:
object[] p = new object[] { null, rsi };
Type[] t = new Type[] { typeof(SSI).MakeByRefType(), typeof(RSI) };
actual = (bool)privateTarget.Invoke("GotSSI", t, p);
SSI ssi = p[0];
Actually the type array can be omitted if the method overload can be determined without it:
object[] p = new object[] { null, rsi };
actual = (bool)privateTarget.Invoke("GotSSI", p);
SSI ssi = p[0];
Just do this: https://instance-factory.com/?p=738
ClassWithPrivateMethods instance = new ClassWithPrivateMethods();
PrivateObject privateObject = new PrivateObject(instance);
object[] args
= new object[] { "some value", null /* placeholder for out param */ };
privateObject.Invoke("PrivateMethodHavingOutParameter", args);
var outParameterValue = args[1];