【问题标题】:C# dynamically load generic class with dynamic type parameters per strings and strongly typed resultC# 动态加载具有每个字符串的动态类型参数和强类型结果的泛型类
【发布时间】:2020-08-09 19:53:29
【问题描述】:

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

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

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 行:加载程序集和类。没问题。

第 2 行:列出我需要通过 string[] 指定名称的类型。

第 4 行:DoubleABCAry 实现 IModelInputFloatABCAry 实现 IModelIOBase

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

第 5 行表明该类已被正确理解。但是,该类显然是在实现接口,而不是我需要的特定类型。

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

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

我知道动态编译代码可以实现,但这是我最后的手段。

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

【问题讨论】:

  • 为什么不能投到ComplexBaseModel&lt;DoubleABCAry, FloatABCAry, Search3Range, object&gt;
  • 如果我能施展它,我就不需要去这个麻烦了。我需要对演员表进行硬编码,这意味着我不需要根据字符串动态加载它。
  • 那么也只需动态调用您的方法,不要使用您使用的安全转换运算符进行转换?
  • 我不确定我是否 100% 关注。只有正确的类包含所需的方法,由于方法签名各不相同,因此无法通过接口实现。所以,我必须有正确的类型。我继续用谷歌搜索,发现不可能做我想做的事,因为 C# 无法将对象声明为特定类型(没有强制转换,如前所述,这意味着我不需要动态代码) .除非你知道怎么做并且可以举个例子?

标签: c# generics reflection activator


【解决方案1】:

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

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

因此,您不仅需要提供类名,还需要提供方法名或具有约定,例如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
        }
    }
}

【讨论】:

    猜你喜欢
    • 2019-04-13
    • 2011-02-28
    • 1970-01-01
    • 2021-06-02
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多