How can I create a Delegate with types only known at run time ?
I would like to do the following :
Type type1 = someObject.getType();
Type type2 = someOtherObject.getType();
var getter = (Func<type1, type2>)Delegate.CreateDelegate(
typeof(Func<,>).MakeGenericType(type1, type2), someMethodInfo);
How can I achieve something similar ?
I suspect you want Expression.GetFuncType as a simpler way of doing your typeof(...).MakeGenericType operation.
var delegateType = Expression.GetFuncType(type1, type2);
Delegate getter = Delegate.CreateDelegate(delegateType, someMethodInfo);
You can't have a compile-time type for getter that's more specific than Delegate though1, because you simply don't know that type at compile-time. You could potentially use dynamic though, which would make it easier to invoke the delegate:
dynamic getter = ...;
var result = getter(input);
1 As noted in comments, you could cast to MulticastDelegate, but it wouldn't actually buy you anything.
You could create a generic method for that:
public Func<T1, T2> GetFunc<T1, T2>(T1 Object1, T2 Object2, MethodInfo Method)
{
return (Func<T1, T2>)Delegate.CreateDelegate(typeof(Func<,>).MakeGenericType(typeof(T1), typeof(T2)), Method);
}
And I bet you can do something using the same philosophy with the Method to avoid all this reflection stuff.
Obs: that would work only if T1 and T2 are typed variables. If they are as object you'll get a Func<object, object>. But....if the objects you will give to the method are as object as well, that would be no problem at all.
And maybe you can even use Func<object, object> always, depending on your scenario.
Related
Is it possible in C# to have higher-order function which takes a function with an arbitrary number and type of arguments and return values, e.g.,
// No valid C# code
void MyFunction(Func f)
{
// do something
}
MyFunction(string.Join); // type: Func<String, IEnumerable<String>, String>
MyFunction(string.CompareTo); // type: Func<object, int>
// ...
I guess, this question really boils down to whether there's a most generic type for functions which can hold any function with possibly different number and type of arguments.
My use-case is the following: I have a method which takes a MethodInfo object. Currently, I do something like
DoSomething(((Func<object, int>)string.CompareTo).Method)
However, I'd have to repeat this for every different kind of function I expect. I'd prefer a solution in which DoSomething could by itself determine the type, so I just give it the Function itself instead of the MethodInfo object.
EDIT:
To be more precise, I'm writing a Linq-To-X provider using ReLinq. I got some example code from a tutorial blog on this topic (https://www.codeproject.com/Articles/42059/re-linq-ishing-the-Pain-Using-re-linq-to-Implement and https://weblogs.asp.net/dixin/understanding-linq-to-sql-10-implementing-linq-to-sql-provider). For eager execution functions like Sum or Count, I need to wrap them into a MethodCallExpression object.
In the example code, it is solved like this:
public static IQuery CountToSql<T>(this IQueryable<T> source)
{
ArgumentChecker.CheckNull(source, nameof(source));
var expression =
Expression.Call(
null,
GetMethodInfo(Queryable.Count, source),
new Expression[] { source.Expression }
);
return ToQuery(expression, ((DbQueryable<T>)source).SyntaxProvider);
}
private static MethodInfo GetMethodInfo<T1, T2>(Func<T1, T2> f, T1 unused1 => f.Method;
private static MethodInfo GetMethodInfo<T1, T2, T3>(Func<T1, T2, T3> f, T1 unused1, T2 unused2) => f.Method;
// ...
However, I don't want to write this for every type of function (e.g., Queryable.Sum, Queryable.Count, ...). The current solution necessitates it. I just want one single method that can handle all, as they look the same for 90%.
It seem strange that you need to call such different delegates from one place.
I think you need something like "EventDispatcher", when your code got data that should be then casted to object, but after that inside a call you want to operate a real objects.
If I wrong please tell more about task.
If I right, you have to replace reflections by generics. Create method that will wrap you delegate by Action.
public Action<object> WrapCall<T, K>( Func<T, K> func)
{
return (data) => func((T)data);
}
public Action<object, object> WrapCall<T1, T2, K>(Func<T1, T2,K> func)
{
return (t1Data, t2Data) => func((T1)t1Data, (T2)t2Data);
}
and so one.
It may be not solve your problem but will helps you to find solution in other way.
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.
How can I create a Delegate with types only known at run time ?
I would like to do the following :
Type type1 = someObject.getType();
Type type2 = someOtherObject.getType();
var getter = (Func<type1, type2>)Delegate.CreateDelegate(
typeof(Func<,>).MakeGenericType(type1, type2), someMethodInfo);
How can I achieve something similar ?
I suspect you want Expression.GetFuncType as a simpler way of doing your typeof(...).MakeGenericType operation.
var delegateType = Expression.GetFuncType(type1, type2);
Delegate getter = Delegate.CreateDelegate(delegateType, someMethodInfo);
You can't have a compile-time type for getter that's more specific than Delegate though1, because you simply don't know that type at compile-time. You could potentially use dynamic though, which would make it easier to invoke the delegate:
dynamic getter = ...;
var result = getter(input);
1 As noted in comments, you could cast to MulticastDelegate, but it wouldn't actually buy you anything.
You could create a generic method for that:
public Func<T1, T2> GetFunc<T1, T2>(T1 Object1, T2 Object2, MethodInfo Method)
{
return (Func<T1, T2>)Delegate.CreateDelegate(typeof(Func<,>).MakeGenericType(typeof(T1), typeof(T2)), Method);
}
And I bet you can do something using the same philosophy with the Method to avoid all this reflection stuff.
Obs: that would work only if T1 and T2 are typed variables. If they are as object you'll get a Func<object, object>. But....if the objects you will give to the method are as object as well, that would be no problem at all.
And maybe you can even use Func<object, object> always, depending on your scenario.
I've been playing around, partially reinventing wheels so that I can understand how proper wheels spin round.
Consider this generic function for compiling and returning the default constructor of a type.
public static Func<TConcrete> Creator<TConcrete>()
{
// All checking removed for brevity
var ctor = typeof(TConcrete).GetConstructor(new Type[0]);
var lambda = Expression.Lambda<Func<TConcrete>>(Expression.New(ctor));
return lambda.Compile();
}
I believe this will return me a nice typed delegate that I can use to instantiate the passed type.
Now consider, I want a function that would do this for a set of different types, how would I go about that? I was thiking along the lines of ...
public static IEnumerable<Delegate> Creators(IEnumerable<Type> types)
{
foreach (var type in types)
{
var ctor = type.GetConstructor(new Type[0]);
var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
yield return lambda.Compile();
}
}
As you can see from the ???? this is where I got stuck. Is there a way to do this or is my approach just flawed?
You can use a different Expression.Lambda call which takes the delegate type as a Type:
Type delegateType = typeof(Func<>).MakeGenericType(type);
var lambda = Expression.Lambda(delegateType, Expression.New(ctor));
yield return lambda.Compile();
Note that this overload of Lambda returns the non-generic LambdaExpression type rather than Expression<TDelegate> - but it still exposes a Compile method which returns Delegate, which is all you need here. Basically it's just avoiding some of the compile-time type checking you benefit from in your "known delegate type" code.
Use the non-generic overload in combination with MakeGenericType:
var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
Should become:
var funcType = typeof(Func<>).MakeGenericType(type);
var lamda = Expression.Lambda(funcType, Expression.New(ctor));
Imagine type like this (C#):
public interface IAmGeneric<T>
{
void SoAmI<T1>(T one, T1 two);
}
Given I have open generic MethodInfo from open generic version of the type (IAmGeneric<>.SoAmI<>()) and the following array
new[] { typeof(int), typeof(string) }'
I'm looking for well performing and reliable way of getting closed version of the MethodInfo like this:
IAmGeneric<int>.SoAmI<string>()
UPDATE:
by reliable I mean it should handle cases when the method is not public, has dozen overloads, uses generic arguments from base type, not just its immediate interface etc.
Something like so? Not sure exactly what you are looking for, maybe expand on your question... This definitely would need some checks added (like checking if declaring type is generic / if method is generic, etc)
var method = typeof(IAmGeneric<>).GetMethod("SoAmI");
var types = new[] { typeof(int), typeof(string) };
var methodTypeParams = method.GetGenericArguments();
var fullType = method.DeclaringType.MakeGenericType(types.Take(types.Length - methodTypeParams.Length).ToArray());
var fullMethod = fullType.GetMethod(method.Name).MakeGenericMethod(types.Skip(types.Length - methodTypeParams.Length).ToArray());
Here is a case that is pretty complex to get right:
public interface IAmGeneric<T>
{
void SoAmI<T1, T2>(T one, T1 two, T2 three);
void SoAmI<T1, T2>(T one, T2 two, T1 three);
void SoAmI<T1, T2>(T1 one, T two, T2 three);
void SoAmI<T1, T2>(T2 one, T1 two, T three);
void SoAmI<T1, T2, T3>(T2 one, T1 two, T3 three);
}
For me the solution is to use GetMethods(...).Select() and compare method name, parameter count, types and type parameters count to find the right method (basically everything that is part of the signature of the method).
Use MethodBase.GetMethodFromHandle, as pointed out in this related answer:
var ty = typeof(IAmGeneric<>);
var numTyParams = ty.GenericTypeArguments.Length;
var mi = ... do something with ty to get generic def for SoAmI<> ...
var parameters = new[] { typeof(int), typeof(string) };
var output = MethodBase.GetMethodFromHandle(mi.MethodHandle, ty.MakeGenericType(parameters.Take(numTyParams).ToArray()).TypeHandle).MakeGenericMethod(parameters.Skip(numTyParams).ToArray());