[英]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.