C# 使用每个字符串的动态类型参数和强类型结果动态加载泛型 class

C# dynamically load generic class with dynamic type parameters per strings and strongly typed result

我正在尝试获取一个 JSON 文件,其中包含有关通用 [​​=45=](程序集、class 名称、类型参数名称)的数据,并动态加载和实例化指定的class。如果我为类型参数使用接口,我可以做到这一点。但是,实现细节不允许我走这条路,所以我需要使用特定类型参数 classes.

到目前为止我有以下代码:

var ci = Invoke.GetClassRef(@"D:\ROCT\Debug\x64 Core\Common Complex Functions.dll", "Namespace.Class");
Type[] typeArgs = { typeof(DoubleABCAry), typeof(FloatABCAry), typeof(Search3Range), typeof(object) };
var _model = ci.GetType().MakeGenericType(typeArgs);
var model = Activator.CreateInstance(_model) as ComplexBaseModel<IModelInput, IModelIOBase, ISearchDimension, object>;
model.Validate();

第 1 行:加载程序集并 class。没问题。

第 2 行:列出我需要通过 string[].

按名称指定的类型

第 4 行:DoubleABCAry 实现 IModelInputFloatABCAry 实施 IModelIOBase,等等

第 4 行将对象转换为其基本定义(如图所示),这不是我想要的。我要 RGB255ToCIELAB : ComplexBaseModel<DoubleABCAry, FloatABCAry, Search3Range, object>.

第 5 行表明 class 被正确理解。然而,class显然是在实现接口,而不是我需要的具体类型。

有没有办法实现这两个目标:

  1. 使用字符串名称指定每个类型参数。
  2. 最终 model 强类型化了?

我知道它可以通过动态编译代码实现,但这是我最后的选择。

我正在使用 C# 9 预览版。

所以我认为最终你的问题归结为你想要加载 dynamic 类型然后将它们视为 static 这样你就可以使用 instance.MyMethod() 语法调用方法.这是 not 可能的(AFAIC),因为 instance.MyMethod() 被编译为 IL,此时编译器不知道 instance 是什么。

因此,如果您无法知道要调用的方法是什么,则必须采用完全动态的方式,即使用反射 API 来调用正确的方法。

所以您不仅需要提供 class 名称,还需要提供方法名称或约定,例如always invoke method called 'Validate' 或类似的东西。

下面的一个简单列表说明了我的观点:

using System;
using System.Reflection;

namespace Shoes {
    
    public interface IA { }
    public class A : IA {}

    public interface IB { }
    public class B : IB {}

    public class SomeKindOfModel<T1, T2> { 

    }

    public class ConcreteModel<T1, T2> : SomeKindOfModel<T1, T2> {
       public bool Validate() {
           return true;
       }    
    }

    public class Program
    {   
        public static void Main()
        {
            // since i don't have your Invoke.GetClassRef, i just did this, works in .net core
            var type = Type.GetType($"Shoes.ConcreteModel`2");

            var genType = type.MakeGenericType(new[] { typeof(A), typeof(B) });
            var instance = Activator.CreateInstance(genType);
            var result = genType.GetMethod("Validate", BindingFlags.Instance | BindingFlags.Public)
                .Invoke(instance, null); // instead of null you can pass data etc.
            Console.WriteLine(result); // prints True
        }
    }
}