I need to implement the method:
object GetFactory(Type type);
This method needs to return a Func<T> where typeparam 'T' is the 'type'.
So, my problem is that I don't know how to create a Func<?> at runtime using reflection. Activator.CreateInstance doesn't work because there are no constructors on delegates.
Any Ideas?
Func is a delegate that points to a method that accepts one or more arguments and returns a value. Action is a delegate that points to a method which in turn accepts one or more arguments but returns no value. In other words, you should use Action when your delegate points to a method that returns void.
Func is generally used for those methods which are going to return a value, or in other words, Func delegate is used for value returning methods. It can also contain parameters of the same type or of different types.
You use Delegate.CreateDelegate
, i.e. from a MethodInfo
; below, I've hard-coded, but you would use some logic, or Expression
, to get the actual creation method:
using System;
using System.Reflection;
class Foo {}
static class Program
{
static Func<T> GetFactory<T>()
{
return (Func<T>)GetFactory(typeof(T));
}
static object GetFactory(Type type)
{
Type funcType = typeof(Func<>).MakeGenericType(type);
MethodInfo method = typeof(Program).GetMethod("CreateFoo",
BindingFlags.NonPublic | BindingFlags.Static);
return Delegate.CreateDelegate(funcType, method);
}
static Foo CreateFoo() { return new Foo(); }
static void Main()
{
Func<Foo> factory = GetFactory<Foo>();
Foo foo = factory();
}
}
For non-static methods, there is an overload of Delegate.CreateDelegate
that accepts the target instance.
I use this with generics in EF Core including making Expression<Func<SomeModelType,bool>> for let's say a Where clause, you can chain MakeGenericType calls with nested generics.
var someType = SomeDbContext.SomeDataModelExample.GetType();
var funcType1 = typeof(Func<>).MakeGenericType(new Type[] { someType });
var result = Activator.CreateInstance(funcType1);
var result2 = Activator.CreateInstance(funcType1, someParams);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With