1

我正在尝试创建一个指定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并摆脱这种as int重复?通过这种方式,我的返回类型(以及我将对象转换为的类型)在编译时将是未知的

对我来说,这似乎是设计上不可能的,但如果你能弄清楚,我将不胜感激。

编辑:我被卡住的地方是,例如,当你在铸造时,return (T) result如果你使用的是通用方法,你可以这样做,但你不能这样做,Type t = ...; return (t) result这是行不通的。您不能转换为作为编译时未知的参数传递给您的类型。

4

3 回答 3

1

遵循已知模式

这不是一个新问题。这是任何允许特定类型返回值的 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);

如果你这样做,很难想象任何程序员会在使用你的库时遇到麻烦,因为他们应该已经熟悉这种方法。

于 2020-01-28T03:37:22.460 回答
0

其实你可以这样写GetInstance

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

并使用它:

int j = GetInstance<int>();
于 2012-11-29T01:36:30.980 回答
0

这可能会帮助您创建所需类型的实例:

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 可以用来转换创建的实例,这可以用作模板来创建具有参数化构造函数的任何类型的实例

于 2020-01-28T02:17:41.510 回答