簡體   English   中英

從 Activator.CreateInstance() 而不是對象返回所需的類型

[英]Returning desired type from Activator.CreateInstance() instead of object

我正在嘗試創建用戶想要的任何指定Type的實例。 為了快速說明我的目的,請參閱下面的代碼:

    static void Main(string[] args)
    {
        object o = GetInstance(typeof(int));
        Console.WriteLine("Created type: {0}", o.GetType().FullName);
    }

    public static object GetInstance(Type t)
    {
        Console.WriteLine("Creating instance of {0}", t.FullName);
        return Activator.CreateInstance(t);
    }

問題是Activator.CreateInstance()默認返回object 此方法還有一個重載,如T Activator.CreateInstance<T>() ,它是無參數的,並返回您指定為T的類型。

但是,問題是在調用此方法時T應該是硬編碼的,因此應該是一個固定值。 我正在嘗試創建所需類的實例並將其作為其類型返回。

現在,如果您使用此方法,您應該編寫如下內容:

int i = GetInstance(typeof(int)) as int

我試圖將其減少到:

int i = GetInstance(typeof(int))

有沒有辦法可以在GetInstance進行強制GetInstance並將其as int重復刪除? 通過這種方式,我的返回類型(以及我將對象轉換為的類型)在編譯時將是未知的

對我來說似乎不可能設計,但如果你能弄清楚,我真的很感激。

編輯:我被卡住的地方是,例如,當你在投射時,如果你在一個通用方法中,你可以做return (T) result ,但你不能做Type t = ...; return (t) result Type t = ...; return (t) result這不起作用。 您不能強制轉換為在編譯時作為參數傳遞給您的類型。

遵循已知模式

這不是一個新問題。 這是任何允許特定類型返回值的 API 所面臨的問題。 例如,像 Newtonsoft 這樣的 JSON 解析庫(即 2019 年 .NET 程序員下載的最流行的 .NET 包)必須能夠解析字符串並返回特定於類型的對象,該對象可能或可能在編譯時不知道。 效仿他們的榜樣可能是有意義的。

Newtonsoft 在反序列化時公開了三種指定類型的方法 您可以按照目前的方式進行:

//Cast required
var result = JsonConvert.DeserializeObject(text, typeof(MyType)) as MyType;  

您可以使用通用方法:

//No cast required, but you have to hardcode a type as a type parameter
var result = JsonConvert.DeserializeObject<MyType>(text);  

或者,您可以將實例用作模板,這對於匿名類型非常有用,盡管您也可以將其與非匿名類一起使用。 這個通過泛型類型推斷工作:

//No cast required and no need to specify type; the type is inferred from the argument
var result = JsonConvert.DeserializeAnonymousType(text, new MyType());  

這是你的方法:

因此,為了讓您完成這項工作,您的代碼可能如下所示:

public object GetInstance(Type type)
{
    return Activator.CreateInstance(type);
}

int i = GetInstance(typeof(int)) as int;


public T GetInstance<T>()
{
    return Activator.CreateInstance<T>();
}

int i = GetInstance<int>();


public T GetInstance<T>(T template)
{
    return Activator.CreateInstance<T>();
}

int i = GetInstance(0);

如果你這樣做,很難想象任何程序員在使用你的庫時會遇到問題,因為他們應該已經熟悉這種方法。

實際上你可以這樣寫GetInstance

static T GetInstance<T>()
{
    return Activator.CreateInstance<T>();
}

並使用它:

int j = GetInstance<int>();

這可能會幫助您創建所需類型的實例:

public class ConcreteFactory<T>  : AbstractFactory<T>
    {
        public override T CreateInstance(string typeName,params object[] parameters)
        {
            var path = Assembly.GetExecutingAssembly().CodeBase;
            var assembly = Assembly.LoadFrom(path);
            var type = assembly.GetTypes().SingleOrDefault(t => t.Name == typeName);
            return (T)Activator.CreateInstance(type, parameters);
        }
}

這里的關鍵是泛型類型 T 可用於轉換創建的實例,這可以用作模板來創建具有參數化構造函數的任何類型的實例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM