如何在C#中通过反射调用嵌套泛型类型的方法

问题描述 投票:0回答:1

我发现了一些通过反射调用泛型方法的示例,例如

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
    {

    }
}
c# generics reflection nested
1个回答
0
投票

抱歉,我相信我没有正确地强调这个问题..我自己对我的要求感到困惑。

我最终在实际代码中得到了什么:

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).
© www.soinside.com 2019 - 2024. All rights reserved.