【问题标题】:How can I generate any generic type at runtime on AOT platforms?如何在 AOT 平台上运行时生成任何泛型类型?
【发布时间】:2017-06-19 20:04:57
【问题描述】:

我需要在 AOT 平台上运行时生成泛型类型。我知道一种“解决方法”,它提示编译器通过在代码中创建一个虚拟方法来生成特定的泛型类:

public void DoDummy(){
    var a1 = new MyClass<MyType>();
}

不幸的是,这个特定的解决方法对我不起作用,因为我有超过几十万(毫不夸张)可以创建的类型组合。

有什么方法可以实现我想要实现的目标吗?

【问题讨论】:

    标签: c# ios generics aot


    【解决方案1】:

    虽然不是一个完美的解决方案,但我发现使用泛型接口和泛型抽象类可以实现比所有组合的蛮力列表更好的方法(正常的解决方法)。

    创建一个泛型类,例如:

    public abstract class GenericBase<T>
    {
        public static bool AOTConstruct()
        {
            bool b = (new GV<T>() == null); // Where GV<T> is a Generic Class.
            // Do similar for all Generic Classes that need to be AOT compiled.
            return b;
        }
    }
    

    然后创建一个泛型接口,比如:

    public interface IGenericValue<T>
    {
        GenericBase<T> ConstructGenericBase();
    }
    

    现在,可以通过将系统类型声明为实现接口的类的类型,为 AOTConstruct 中列出的通用类进行 AOT 编译,如下所示:

    public class SystemTypes : IGenericValue<float> // Implement IGenericValue for other Types.
    {
        GenericBase<float> IGenericValue<float>.ConstructGenericBase()
        {
            throw new NotImplementedException();
        }
    }
    

    对于任何自定义类都可以这样做,可以与系统类型在同一类中,也可以作为自定义类声明的一部分(为了清楚起见,我更喜欢这样做)。

    不得不为新的系统级类型更新 SystemTypes 以支持,并为需要支持的新通用类更新 AOTConstruct 令人失望,但它适用于编译到 iOS 并且不需要列出所有组合.

    【讨论】:

      【解决方案2】:

      我不能 100% 确定我了解您想要做什么,但也许这对您有帮助:

      private static object Create(Type genericType, params Type[] genericArguments)
      {
          Type genericClass = genericType.MakeGenericType(genericArguments);
          return Activator.CreateInstance(genericClass);
      }
      

      此方法为您要创建的genericType 创建所有需要的泛型类型参数,并使用其无参数构造函数创建结果类型的实例。

      如果你有类似的课程

      public class MyClass<T>
      {
      }
      

      并且想用string 作为类型参数来实例化它,你可以这样称呼它:

      var myinstance = Create(typeof(MyClass<>), typeof(string));
      

      请注意,如果您想有效地使用返回值 (myinstance),您可能应该将其声明为 dynamic

      【讨论】:

      • 嗨 René,感谢您的回答。这就是我正在做的,但问题是在 AOT 平台上,如果正在创建的泛型类型尚未在程序的任何地方声明,则会抛出 ExecutionEngineException。因此,例如,如果我使用 MakeGenericType 创建了一个 MyClass 并且我没有在我的代码中的任何位置声明“MyClass”,它将无法工作。如果我将“MyClass”添加到我在问题中发布的虚拟方法中,那么它将起作用。
      • 啊好吧,不知道。这里没有 AOT 平台的经验。对不起,我帮不了你。
      • @Rafael 我现在面临同样的问题。最后你怎么解决这个问题?
      猜你喜欢
      • 2011-06-30
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-01
      相关资源
      最近更新 更多