使用动态generetad lambda调用泛型扩展

时间:2017-10-05 15:20:11

标签: c# generics lambda

目前我有一些这样的电话

app.CreatePerOwinContext<BasicUserManager>(BasicUserManager.Create);
app.CreatePerOwinContext<ADUserManager>(ADUserManager.Create);
...

这些“Create”方法是每个类的静态成员。所以基本上它正在注册一个处理程序,一旦我从BasicUserManager请求owinContext对象,就会调用它。

我想用这样的东西替换它:

var types = AppDomain.CurrentDomain.GetAssemblies()
                     .SelectMany(s => s.GetTypes())
                     .Where(p => typeof(AbstractUserManager).IsAssignableFrom(p) && !p.IsAbstract);

foreach (var type in types)
{
    app.RegisterUserManagers(type);
}

到目前为止没问题。 RegisterUserManagers是一个扩展,定义如下:

public static void RegisterSRTUserManager(this IAppBuilder app, Type type)
{            
    var createPerOwinContextMethod = typeof(AppBuilderExtensions).GetMethods().Where(p => p.Name == "CreatePerOwinContext" && p.GetParameters().Count() == 2).FirstOrDefault().MakeGenericMethod(type);

    var createMethod = type.GetMethod("Create", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);

    var optionsType = typeof(IdentityFactoryOptions<>).MakeGenericType(type);

    var delegateType = typeof(Func<,,>).MakeGenericType(optionsType, typeof(IOwinContext), type);                                  

    var body = Expression.Call(createMethod, Expression.Parameter(optionsType, "options"), Expression.Parameter(typeof(IOwinContext), "context"));            

    var func = Expression.Lambda(delegateType, body, Expression.Parameter(optionsType, "options"), Expression.Parameter(typeof(IOwinContext), "context")).Compile();

    createPerOwinContextMethod.Invoke(null, new object[] {app, func });
}

编译lambda表达式后,我得到一个异常:

  

附加信息:类型为'Microsoft.AspNet.Identity.Owin.IdentityFactoryOptions`1 [SeguridadAuth.Login.BD&gt; .AdminOrgUserManager]'的变量'options''从范围''引用,但未定义。

我知道params应该在这里通过引用传递,但我无法在这种情况下想办法。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

在发布问题后得到它。只需要将相同的参数引用传递给两种方法。

var optionsPar = Expression.Parameter(optionsType, "options");
var contextPar = Expression.Parameter(typeof(IOwinContext), "context");

var body = Expression.Call(createMethod, optionsPar, contextPar );

var func = Expression.Lambda(delegateType, body, optionsPar, contextPar).Compile();