2016-05-15 103 views
1

我需要在運行時在AOT平臺上生成泛型類型。我知道,通過創建代碼的虛擬方法提示編譯器生成一個特定的通用類「解決辦法」的:如何在運行時在AOT平臺上生成任何通用類型?

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

不幸的是,這種特定的解決辦法不會爲我工作,因爲我有幾百千(不誇張)可能創建的類型的可能組合。

有沒有什麼方法可以實現我想要實現的目標?

回答

0

我不是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

+0

嗨René,謝謝你的回答。這就是我正在做的事情,但問題是,在AOT平臺上,如果創建的泛型類型沒有在程序中的任何地方聲明,就會拋出ExecutionEngineException異常。因此,例如,如果我使用MakeGenericType創建MyClass ,並且現在我已在代碼中的任何位置聲明瞭「MyClass 」,它將無法工作。如果我在我的問題中發佈的虛擬方法中添加「MyClass 」,那麼它將起作用。 – Rafael

+0

好的,不知道。沒有AOT平臺的經驗。對不起,我幫不了你。 –

0

雖然不是一個完美的解決方案,但我發現可以使用通用接口和通用抽象類來實現比所有組合的強力列表(常規解決方法)更好的東西。

創建一個通用類,比如這個:

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(); 
} 

現在,系統類型可以AOT編譯列出的泛型類在AOTConstruct中被聲明爲實現接口類的類型,如下所示:

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

對於任何自定義類,無論是與系統類型相同的類還是作爲自定義類聲明的一部分(我更喜歡爲了清晰起見)都可以做到這一點。

爲了支持新系統級類型而更新系統類型併爲需要支持的新通用類更新AOTConstruct是令人失望的,但它適用於編譯到iOS,並且不需要所有組合都是上市。