简体   繁体   English

从 Activator.CreateInstance() 而不是对象返回所需的类型

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

I'm trying to create an instance of specified Type whatever user wants to have.我正在尝试创建用户想要的任何指定Type的实例。 For a quick illustration of my purpose please see the code below:为了快速说明我的目的,请参阅下面的代码:

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

The problem is Activator.CreateInstance() returns object by default.问题是Activator.CreateInstance()默认返回object There is also an overload of this method like T Activator.CreateInstance<T>() which is parameterless and returns the type you specify as T .此方法还有一个重载,如T Activator.CreateInstance<T>() ,它是无参数的,并返回您指定为T的类型。

However, the problem is T should be hard-coded while calling this method and thus should be a fixed value.但是,问题是在调用此方法时T应该是硬编码的,因此应该是一个固定值。 I am trying to create an instance of desired class and return it as its type.我正在尝试创建所需类的实例并将其作为其类型返回。

Right now if you use this method you should write something like:现在,如果您使用此方法,您应该编写如下内容:

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

I'm trying to reduce this to:我试图将其减少到:

int i = GetInstance(typeof(int))

Is there a way that I can do casting inside the GetInstance and get rid of that as int repetition?有没有办法可以在GetInstance进行强制GetInstance并将其as int重复删除? By this way, my return type (and also the type I cast the object to) will be unknown at compile time .通过这种方式,我的返回类型(以及我将对象转换为的类型)在编译时将是未知的

Seemed impossible by design to me but I'd really appreciate if you figure it out.对我来说似乎不可能设计,但如果你能弄清楚,我真的很感激。

EDIT: Where I'm stuck is eg while you're casting, you can do return (T) result if you are in a generic method, but you can't do Type t = ...; return (t) result编辑:我被卡住的地方是,例如,当你在投射时,如果你在一个通用方法中,你可以做return (T) result ,但你不能做Type t = ...; return (t) result Type t = ...; return (t) result this doesn't work. Type t = ...; return (t) result这不起作用。 You cannot cast to a type which is passed to you as a parameter which is not known at compile time .您不能强制转换为在编译时作为参数传递给您的类型。

Follow a known pattern遵循已知模式

This is not a new problem.这不是一个新问题。 It is a problem facing any API that allows type-specific return values.这是任何允许特定类型返回值的 API 所面临的问题。 For example, a JSON parsing library like Newtonsoft (which is, to wit, the single most popular .NET package downloaded by .NET programmers in 2019) must be able to parse a string and return a type-specific object, which may or may not be known at compile time.例如,像 Newtonsoft 这样的 JSON 解析库(即 2019 年 .NET 程序员下载的最流行的 .NET 包)必须能够解析字符串并返回特定于类型的对象,该对象可能或可能在编译时不知道。 It might make sense to follow their example.效仿他们的榜样可能是有意义的。

Newtonsoft exposes three ways to specify the type when deserializing. Newtonsoft 在反序列化时公开了三种指定类型的方法 You could do as you are currently doing:您可以按照目前的方式进行:

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

You can use a generic method:您可以使用通用方法:

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

Or you can use an instance as a template, which is great for anonymous types, although you can use it with non-anonymous classes as well.或者,您可以将实例用作模板,这对于匿名类型非常有用,尽管您也可以将其与非匿名类一起使用。 This one works via generic type inference:这个通过泛型类型推断工作:

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

Here's how you'd do it:这是你的方法:

So for you to make this work, your code might look like this:因此,为了让您完成这项工作,您的代码可能如下所示:

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

If you do it this way, it's hard to imagine any programmer would have trouble using your library, as the approach should already be familiar to them.如果你这样做,很难想象任何程序员在使用你的库时会遇到问题,因为他们应该已经熟悉这种方法。

Actually you could write GetInstance like this:实际上你可以这样写GetInstance

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

And use it:并使用它:

int j = GetInstance<int>();

This might help you to create instance of desired type:这可能会帮助您创建所需类型的实例:

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

Key here is generic type T can be used to cast the created instance, this can be used as a template to create instance of any type with parameterized constructor这里的关键是泛型类型 T 可用于转换创建的实例,这可以用作模板来创建具有参数化构造函数的任何类型的实例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有动态类型的Activator.CreateInstance - Activator.CreateInstance with dynamic Type Activator.CreateInstance和Activator.CreateInstance之间的区别<Type> - difference between Activator.CreateInstance and Activator.CreateInstance<Type> 快速创建对象而不是 Activator.CreateInstance(type) - Fast creation of objects instead of Activator.CreateInstance(type) Activator.CreateInstance创建类型T的值,而不是Nullable <T> - Activator.CreateInstance creates value of type T instead of Nullable<T> 如何将object []传递给Activator.CreateInstance(type,params object []) - How to pass object[] to Activator.CreateInstance(type, params object[]) 从类型创建泛型变量 - 如何? 或者使用带有属性{}而不是参数()的Activator.CreateInstance()? - Creating generic variables from a type - How? Or use Activator.CreateInstance() with properties { } instead of parameters ( )? 如何动态地将类型传递给Activator.CreateInstance(object)? - How to pass type dynamically to Activator.CreateInstance(object)? 从使用Activator.CreateInstance(type)创建的实例中捕获异常 - Catch an exception from an instance created with Activator.CreateInstance(type) Activator.CreateInstance:无法从程序集加载类型 - Activator.CreateInstance: Could not load type from assembly 如何使用Activator.CreateInstance从系统dll中加载类型? - How to load type from system dll using Activator.CreateInstance?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM