我发现了一些通过反射调用泛型方法的示例,例如
method<T>()
。就我而言,泛型类型嵌套在类中method<Class<T>>()
。
在示例中,我重定向了 WPF 应用程序的视图模型。我有与
View
枚举一样多的视图模型。当我不断添加新的视图/视图模型时,我会避免重复代码行。 _serviceProvider
由 Microsoft 依赖注入 提供。
switch (view)
{
case View.Settings:
ViewModel = _serviceProvider.GetRequiredService<CreateViewModel<SettingsViewModel>>().Invoke();
break;
// ...
}
到目前为止我整理的内容。有人可以帮我改正吗?
using System;
using System.Reflection;
namespace NestedGenericReflection
{
class Program
{
private static ServiceProviderModel _serviceProvider = new ServiceProviderModel();
static void Main(string[] args)
{
var view = View.Settings;
IViewModel viewModel = null;
var assembly = typeof(IViewModel).Assembly;
var typeName = $"NestedGenericReflection.{view}ViewModel, {assembly.FullName}";
var type = Type.GetType(typeName);
var generic = typeof(CreateViewModel<>).MakeGenericType(type); // I believe this is not correct..
var field = typeof(Program).GetField(nameof(_serviceProvider), BindingFlags.NonPublic | BindingFlags.Static); // Static for this example.
var method = field.FieldType
.GetMethod("GetRequiredService")
.MakeGenericMethod(generic);
viewModel = method.Invoke(_serviceProvider, null) as IViewModel;
}
}
public enum View
{
Settings
}
public interface IViewModel
{
}
public interface IService
{
IViewModel Invoke();
}
public class ServiceProviderModel
{
public IService GetRequiredService<T>()
{
return null;
}
}
public class SettingsViewModel : IViewModel
{
}
public class CreateViewModel<ViewModel> where ViewModel : class
{
}
}
抱歉,我相信我没有正确地强调这个问题..我自己对我的要求感到困惑。
我最终在实际代码中得到了什么:
var assembly = typeof(NavigationModel).Assembly;
// Gets the type of the view model.
var type = Type.GetType($"Software.Desktop.ViewModels.{view}ViewModel, {assembly.FullName}");
// Gets the type of the nested generic CreateViewModel class with the view model.
type = typeof(CreateViewModel<>).MakeGenericType(type);
// Gets the field corresponding to the service provider.
var field = typeof(NavigationModel).GetField(nameof(_serviceProvider), BindingFlags.Instance | BindingFlags.NonPublic);
// Gets the generic extension method.
var method = typeof(ServiceProviderServiceExtensions).GetMethods(BindingFlags.Static | BindingFlags.Public)
.First(method => method.Name == "GetRequiredService"
&& method.IsGenericMethod)
.MakeGenericMethod(type);
var obj = method.Invoke(_serviceProvider, [_serviceProvider]) as CreateViewModel<BaseViewModel>;
ViewModel = obj.Invoke(); // I forgot the CreateViewModel also had its own `Invoke()` method which is completely separated from the generic one (line above).