【发布时间】:2017-06-19 20:04:57
【问题描述】:
我需要在 AOT 平台上运行时生成泛型类型。我知道一种“解决方法”,它提示编译器通过在代码中创建一个虚拟方法来生成特定的泛型类:
public void DoDummy(){
var a1 = new MyClass<MyType>();
}
不幸的是,这个特定的解决方法对我不起作用,因为我有超过几十万(毫不夸张)可以创建的类型组合。
有什么方法可以实现我想要实现的目标吗?
【问题讨论】:
我需要在 AOT 平台上运行时生成泛型类型。我知道一种“解决方法”,它提示编译器通过在代码中创建一个虚拟方法来生成特定的泛型类:
public void DoDummy(){
var a1 = new MyClass<MyType>();
}
不幸的是,这个特定的解决方法对我不起作用,因为我有超过几十万(毫不夸张)可以创建的类型组合。
有什么方法可以实现我想要实现的目标吗?
【问题讨论】:
虽然不是一个完美的解决方案,但我发现使用泛型接口和泛型抽象类可以实现比所有组合的蛮力列表更好的方法(正常的解决方法)。
创建一个泛型类,例如:
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 并且不需要列出所有组合.
【讨论】:
我不能 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。
【讨论】: