开发者

Activator.CreateInstance(Type) for a type without parameterless constructor [duplicate]

开发者 https://www.devze.com 2022-12-24 02:04 出处:网络
This question already has answers here: Creating instance of type without default constructor in C# using reflection
This question already has answers here: Creating instance of type without default constructor in C# using reflection (4 answers) Closed 9 years ago.

Reading existing code at work, I wondered how come this could work. I have a class defined in an assembly :

[Serializable]
public class A
{
    private readonly string _name;
    private A(string name)
    {
        _name = name;
    }
}

And in another assembly :

pu开发者_如何学编程blic void f(Type t) {
    object o = Activator.CreateInstance(t);
}

and that simple call f(typeof(A))

I expected an exception about the lack of a parameterless constructor because AFAIK, if a ctor is declared, the compiler isn't supposed to generate the default public parameterless constructor.

This code runs under .NET 2.0.

[EDIT] I'm sorry but I misread the actual code... The sample I provided doesn't illustrate it. I accepted JonH answer because it provided a good piece of information.


An alternative is:

object obj = System.Runtime.Serialization.FormatterServices
          .GetUninitializedObject(t);

which creates the object in memory but doesn't run any constructor. Scary.


See this: Creating instance of type without default constructor in C# using reflection

Here's to the future also, this is in regards to C# 4.0:

Posted by Microsoft on 1/4/2010 at 2:08 PM
We have reviewed your bug and have determined that the behavior that you described is by design. We are now archiving this issue. Thanks for using Visual Studio and the .Net Framework!

There are many overloads of Activator.CreateInstance, the one that takes a single type parameter only invokes the default parameterless constructor. Constructors that take an optional parameter like the one in your example are not default constructors. To invoke them you need to:

  1. use an overload that takes an argument array
  2. Pass in Type.Missing as the argument
  3. Specify OptionalParamBinding in the BindingFlags

Here is an example:

Activator.CreateInstance(typeof(MyClassName),
 BindingFlags.CreateInstance |
 BindingFlags.Public |
 BindingFlags.Instance |
 BindingFlags.OptionalParamBinding,
 null, new Object[] {Type.Missing}, null);

Thanks,

Weitao Su

Microsoft Corp.


This may not be feasible for you to do, but the simplest thing is to pass the argument list after the type like so:

Activator.CreateInstance(t, "name");

You'll want to think about what f() is really trying to do. Should it be instantiating an object of type A at all? What other classes will it instantiate?

One possibility is to have a switch statement within f() which passes the correct parameters to CreateInstance() for class A. This won't scale, but that may not be an issue for you.


There are two confusing flavors of CreateInstance: one that takes an object of type System.Type as a parameter, another that takes a type parameter T.

First one:

object Activator.CreateInstance(type As Type) { }

Second one:

T Activator.CreateInstance<T>() { }

The second one is the one that doesn't work for a class without a public parameterless constructor.

Note that it almost never makes sense to even use the second one; in any case where it would be used, it would be better to have a where T : new() constraint on your class and simply use T's constructor.

The MSDN documentation agrees:

In general, there is no use for the CreateInstance in application code, because the type must be known at compile time. If the type is known at compile time, normal instantiation syntax can be used (new operator in C#, New in Visual Basic, gcnew in C++).

EDIT: I may have spoken too soon; it appears the first version isn't supposed to work either.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号