【问题标题】:How can I create a C# IEnumerable<"ClassName"> at run time? [duplicate]如何在运行时创建 C# IEnumerable<"ClassName">? [复制]
【发布时间】:2021-07-20 14:01:33
【问题描述】:

我目前正在创建一个机器学习引擎,它将运行在数据库中配置的某些例程。我想创建一个方法来处理从数据库作为字符串传递的多种类型的 IEnumerable。我已经在项目中定义了类类型,我只想从类的字符串名称中动态创建 IEnumerable。

更新了更多信息:

下面是我想使用 dapper (.net core) 填充的列表示例。

机器学习预测引擎需要将列属性添加到类中,以便知道如何处理它。我几乎接受了我将无法动态创建类,我只想动态创建一个 List 以节省代码。我可以为我想创建但不想创建的每种类型的 List 编写一个 case 语句。

这是类定义:

class PriceChange24
    {
        [LoadColumn(0)]
        public Single Volume { get; set; }
        
        [LoadColumn(1)]
        public Single PriceChange1H { get; set; }

        [LoadColumn(2)]
        public Single PriceChange24H { get; set; }

        [LoadColumn(3)]
        public Single PriceChange7D { get; set; }

        [LoadColumn(4)]
        public Single PriceChange1HAvg { get; set; }

        [LoadColumn(5)]
        public Single PriceChange24HAvg { get; set; }

        [LoadColumn(6)]
        public Single PriceChange7DAvg { get; set; }

        [LoadColumn(7)]
        public Single RSI { get; set; }

        [LoadColumn(8), ColumnName("Label")]
        public bool GreaterThan10_24 { get; set; }

        public Single Volume24H { get; set; }

        public string Symbol { get; set; }

        public Single GBPValue { get; set; }

        public DateTime LastUpdated { get; set; }

}

【问题讨论】:

  • 您尝试了哪些方法,哪些方法不适合您?还有你以后需要用这个IEnumerable做什么?请向我们展示字符串的示例。
  • IEnumerable&lt;T&gt; 是一个接口。您不能创建接口对象。您必须创建一个实现该接口的集合(例如,T[]List&lt;T&gt;)。虽然您可以使用反射创建这样的对象,但这通常不是很有用,因为如果不再次使用反射,您将无法针对此类动态创建的类型进行编程。因此,从那时起,您最终会通过反思来做所有事情。
  • @OlivierJacot-Descombes doing everything with reflection from then on 没有任何问题;这只是 C# 的动态特性,是插件管理等功能的强大功能。
  • 好的,一旦你创建了这个虚构的类型,你会用它做什么?您希望您的代码如何处理它?这几乎可以肯定是代码异味,但在不了解您的项目结构的情况下,我们无法真正提出解决方案。
  • @zaitsman,关键是泛型在编译时为您提供类型安全。如果在运行时进行反射,则会失去类型安全性。因此,您也可以使用非泛型IEnumerable 并使用object 的集合。对泛型进行反思违背了泛型的目的。但这当然取决于我们不知道的用法。请参阅:What is the XY problem?(我认为是)。

标签: c# generics dynamic reflection


【解决方案1】:

IEnumerable 是一个接口,因此您无法创建它的实例,但您可以使用List&lt;&gt;

你可以这样做:

using System;
using System.Collections.Generic;

// Here we are getting a reference to assembly using a known type.
// Alternatively, you can look at System.Reflection Assembly.GetExecutingAssembly
// or Assembly.GetEntryAssembly
var assemblyReference = typeof(Program).Assembly;
// Below is case sensitive and the type is meant to be public
var targetType = assemblyReference.GetType("Shoes");            

var instance = Activator.CreateInstance(typeof(List<>)
.MakeGenericType(targetType));

Console.WriteLine(instance.GetType()); // prints System.Collections.Generic.List`1[Shoes]

【讨论】:

    猜你喜欢
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    • 2014-08-13
    • 2014-12-03
    • 2018-01-28
    • 1970-01-01
    相关资源
    最近更新 更多