[英]How to invoke generic method with Action<T> parameter using reflection in C#
I want this code to be called generic.我希望将此代码称为通用代码。
services.AddDbContext<ProductsDbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sqlServerOptions =>
{
sqlServerOptions.MigrationsAssembly("Modules.Products");
});
});
It's from entityframeworkcore.它来自实体框架核心。 See the documentation here .
请参阅此处的文档。
I created a class for getting the builder:我创建了一个 class 来获取构建器:
public static class DbContextExtensions
{
public static Action<DbContextOptionsBuilder> GetDbContextOptionsBuilder(string connectionString, AssemblyName moduleName)
{
return options =>
{
options.UseSqlServer(connectionString,
sqlServerOptions =>
{
sqlServerOptions.MigrationsAssembly(moduleName.Name);
});
};
}
}
And I created the following for invoke the method:我为调用该方法创建了以下内容:
var moduleAssembly = Assembly.GetAssembly(manifest);
var moduleName = moduleAssembly.GetName();
// Get dbcontext like ProductsDbContext
var dbContext = moduleAssembly.GetTypes().Where(p => typeof(DbContext).IsAssignableFrom(p)).First();
// Get the correct extensionmethod with Action<DbContextOptionsBuilder>
MethodInfo addDbContextMethod = typeof(EntityFrameworkServiceCollectionExtensions)
.GetMethod(nameof(EntityFrameworkServiceCollectionExtensions.AddDbContext),
1,
new Type[] { typeof(ServiceCollection), typeof(Action<DbContextOptionsBuilder>), typeof(ServiceLifetime), typeof(ServiceLifetime) });
MethodInfo generic = addDbContextMethod.MakeGenericMethod(dbContext);
// But how to pass the Action<DbContextOptionsBuilder> method?
// I tried the following but i'm lost...
var delegateType = typeof(Action<>).MakeGenericType(typeof(DbContextOptionsBuilder));
var methodInfo = typeof(DbContextExtensions).GetMethod(nameof(DbContextExtensions.GetDbContextOptionsBuilder));
var del = Delegate.CreateDelegate(delegateType, null, methodInfo);
// invoke subscribe method
generic.Invoke(services, new[] { del });
Any ideas?有任何想法吗? Thanks
谢谢
From your code I see that DbContextExtensions
is your local class which you don't need to call using Reflection, so you can call the GetDbContextOptionsBuilder
method directly providing the correct parameters and get the action.从您的代码中,我看到
DbContextExtensions
是您不需要使用反射调用的本地 class ,因此您可以直接调用GetDbContextOptionsBuilder
方法,提供正确的参数并获取操作。 Then you can call your generic
method with the generated actions.然后您可以使用生成的操作调用您的
generic
方法。
var moduleAssembly = Assembly.GetAssembly(manifest);
var moduleName = moduleAssembly.GetName();
var dbContext = moduleAssembly.GetTypes().Where(p => typeof(DbContext).IsAssignableFrom(p)).First();
MethodInfo addDbContextMethod = typeof(EntityFrameworkServiceCollectionExtensions)
.GetMethod(nameof(EntityFrameworkServiceCollectionExtensions.AddDbContext),
1,
new Type[] { typeof(IServiceCollection), typeof(Action<DbContextOptionsBuilder>), typeof(ServiceLifetime), typeof(ServiceLifetime) });
MethodInfo generic = addDbContextMethod.MakeGenericMethod(dbContext);
var action = DbContextExtensions.GetDbContextOptionsBuilder("connectionString", moduleName);
generic.Invoke(null, new object[] { services, action, ServiceLifetime.Scoped, ServiceLifetime.Scoped });
If you want to get the action from the external assembly, you can use the same approach by dynamically getting the GetDbContextOptionsBuilder
method info and calling it with parameters and as the result you get the action which you can use in calling your generic
method.如果您想从外部程序集中获取操作,您可以通过动态获取
GetDbContextOptionsBuilder
方法信息并使用参数调用它来使用相同的方法,结果您将获得可用于调用generic
方法的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.