【问题标题】:c# Creating an unknown generic type at runtimec# 在运行时创建一个未知的泛型类型
【发布时间】:2020-10-15 22:54:46
【问题描述】:

所以我有一个泛型类,它可能需要在自己的方法中创建一个具有不同类型泛型的自身实例,其类型是通过反射获得的。

这很重要,因为此存储库将 T 映射到数据库表 [这是我正在编写的 ORMish],如果代表 T 的类有一个代表另一个表的集合,我需要能够实例化并传递它到存储库 [ala Inception]。
我提供了方法,以防它更容易发现问题。

private PropertiesAttributesAndRelatedClasses GetPropertyAndAttributesCollection() 
{
  // Returns a List of PropertyAndAttributes

  var type = typeof(T);
  //For type T return an array of PropertyInfo

  PropertiesAttributesAndRelatedClasses PAA = new PropertiesAttributesAndRelatedClasses();
  //Get our container ready

  //Let's loop through all the properties.
  PropertyAndAttributes _paa;
  foreach(PropertyInfo Property in type.GetProperties())
  {
    //Create a new instance each time.
    _paa = new PropertyAndAttributes();

    //Adds the property and generates an internal collection of attributes for it too
    _paa.AddProperty(Property);

    bool MapPropertyAndAttribute = true;
    //This is a class we need to map to another table
    if (Property.PropertyType.Namespace == "System.Collections.Generic")
    {
      PAA.AddRelatedClass(Property);
      //var x = Activator.CreateInstance("GenericRepository", Property.GetType().ToString());
    }
    else 
    {
      foreach(var attr in _paa.Attrs) 
      {
        if (attr is IgnoreProperty)
        {
          //If we find this attribute it is an override and we ignore this property.
          MapPropertyAndAttribute = false;
          break;
        }
      }
    }
    //Add this to the list.
    if (MapPropertyAndAttribute) PAA.AddPaa(_paa);
  }
  return PAA;
}

所以给定 GenericRepository<T>,我想做一个GenericRepository<string type obtained via reflection from the Property>,我该怎么做? 我需要用 WORKS 替换的行是:

//var x = Activator.CreateInstance("GenericRepository", Property.GetType().ToString());

谢谢。

【问题讨论】:

  • 如何在 C# 代码中声明属性(System.Collections.Generic 类型之一)?它的类型参数<T> 是否与拥有该属性的GenericRepository<T> 相同?
  • 不,基本上它只是另一个类的泛型集合,作为类的属性。即一个教师类有一个类的列表。存储库获取教师类并且还必须处理类类,但由于它确实得到 T,它必须弄清楚它必须使用反射处理什么
  • 那么Teacher 类中的属性是否声明为List<Class> Classes {/*getter and/or setter*/}? Activator.CreateInstance(Property.GetType()) 不工作吗?
  • 啊,但是如果当前实例化的存储库是 T = 教师,我需要一个类型为 T 的存储库 [我自己的通用],其中 T = 类。你的建议会起作用,但只是为了创建类型 Classes
  • 以下两个答案都是正确的。他们对你有用吗?

标签: c# reflection casting


【解决方案1】:

我认为您正在寻找MakeGenericType 方法:

// Assuming that Property.PropertyType is something like List<T>
Type elementType = Property.PropertyType.GetGenericArguments()[0];
Type repositoryType = typeof(GenericRepository<>).MakeGenericType(elementType);
var repository = Activator.CreateInstance(repositoryType);

【讨论】:

  • 如果可以的话,我遇到了 1 个问题。我无法访问给定存储库的任何方法。如果我通过它说 GenericRepository 的即时窗口访问它,我会这样做?((GenericRepository)re​​pository).GetAll() 这正常工作,我怎样才能在代码中正确转换它这样我就不需要这个了?显然我只能在即时窗口中进行,因为我知道它代表的类型。
  • @Jordan,您可以使用返回对象数组的GetAll 方法创建非泛型IRepository 接口,并在GenericRepository&lt;T&gt; 类中显式实现此接口。或者您可以使用反射动态调用该方法,但速度较慢...
【解决方案2】:
Activator.CreateInstance(typeof(GenericRepository<>).MakeGenericType(new Type[] { Property.GetTYpe() }))

【讨论】:

  • 这将创建一个GenericRepository&lt;RuntimePropertyInfo&gt; 的实例,因为Property.GetType() 返回RuntimePropertyInfo...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-04
  • 2022-07-28
  • 1970-01-01
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2018-06-12
相关资源
最近更新 更多