如何以编程方式创建Func 委托

我有一个小的dependency injection框架,我试图让它动态地解析Lazy实例。 我的想法是做那样的事情:

 DIContainer.Register(); var lazyCommand = DIContainer.Resolve<Lazy>(); 

前几天我读到Autofac能够做到这一点。

我试图设置该Lazy实例的构造函数。 在下一个测试代码中,抛出exception,因为所需的类型构造函数需要一个Func ,但我传递的是一个Func

  static readonly Type _lazyType = typeof(Lazy); static Object ResolveTest(Type type) { if (type.IsGenericType && type.GetGenericTypeDefinition() == _lazyType) { var arg = type.GetGenericArguments()[0]; return Activator.CreateInstance(_lazyType.MakeGenericType(arg), new Func(() => ResolveType(arg))); } else return ResolveType(type); } 

我不知道如何创建适合Lazy构造函数参数的委托。 任何的想法?

干杯。

这不是微不足道的。 一种可能的解决方案是使用reflection:

  1. 创建一个通用的ResolveType方法:

     public static T ResolveType() { return (T)ResolveType(typeof(T)); } 
  2. 创建使用此方法的委托:

     // You probably want to cache this MethodInfo: var method = typeof(TypeContainingResolveType) .GetMethods() .Single(x => x.IsGenericMethod && x.Name == "ResolveType") .MakeGenericMethod(arg); var delegate = Delegate.CreateDelegate( typeof(Func<>).MakeGenericType(arg), method); 
  3. 使用该委托:

     return Activator.CreateInstance(_lazyType.MakeGenericType(arg), delegate); 

这个应用程序输出“True”和“0”。 即ResolveTest(typeof(Lazy))返回一个Lazy对象,构造方式与您想要的一样。

 using System; using System.Linq.Expressions; namespace TestApp { public class Class1 { public static void Main() { object lazyInt = ResolveTest(typeof(Lazy)); Console.WriteLine(lazyInt.GetType() == typeof(Lazy)); Console.WriteLine(((Lazy)lazyInt).Value); } static readonly Type _lazyType = typeof(Lazy<>); static Object ResolveTest(Type type) { if (type.IsGenericType && type.GetGenericTypeDefinition() == _lazyType) { var arg = type.GetGenericArguments()[0]; var lazyArgType = _lazyType.MakeGenericType(arg); var funcArgType = typeof(Func<>).MakeGenericType(arg); var funcCtor = lazyArgType.GetConstructor(new[] { funcArgType }); Expression> f = () => ResolveTest(arg); var func = typeof(Class1).GetMethod("BuildCastedThing").MakeGenericMethod(arg).Invoke(null, new[] { f }); var arguments = new object[] { func }; var retVal = funcCtor.Invoke(arguments); return retVal; } else return ResolveType(type); } public static object ResolveType(Type type) { return Activator.CreateInstance(type); } public static Func BuildCastedThing(Expression> f) { Expression> expr = Expression.Lambda>( Expression.Convert( Expression.Invoke(f), typeof(T))); return expr.Compile(); } } } 

这是一种将ResolveTest重写为通用Resolve (例如Resolve返回Lazy )。 这有点不同,因为没有等效的ResolveTest(typeof(int)) ,它返回一个int

 static Lazy Resolve() { var arg = typeof(T); return new Lazy(() => (T)ResolveType(arg)); } 

或者使用通用的ResolveType

 static Lazy Resolve() { return new Lazy(() => ResolveType()); } public static T ResolveType() { return Activator.CreateInstance(); } 
 public static Object ResolveTest(Type type) { if (type.IsGenericType && type.GetGenericTypeDefinition() == _lazyType) { var arg = type.GetGenericArguments()[0]; Expression> expressionWithFuncOfTypeObject = () => ResolveType(arg); UnaryExpression expressionThatEvaluatesToAnObjectOfTypeArg = Expression.Convert(expressionWithFuncOfTypeObject.Body, arg); LambdaExpression expressionWithFuncOfTypeArg = Expression.Lambda(typeof(Func<>).MakeGenericType(arg), expressionThatEvaluatesToAnObjectOfTypeArg); Delegate funcOfTypeArg = expressionWithFuncOfTypeArg.Compile(); // <-- At runtime this will be of type Func return Activator.CreateInstance(_lazyType.MakeGenericType(arg), funcOfTypeArg); } else return ResolveType(type); }