是否可以在已创建的实例上直接调用构造函数?

时间:2014-11-26 21:38:31

标签: c# .net

我知道你可以直接调用static constructor of a typeI know that you can create an instance of an object without calling the constructor,但有没有办法在已经存在的实例上运行类型(.ctor)的构造函数?

我正在寻找类似的东西:

public static void Reinitialize<T>(T instance)
{
  var initializer = typeof(T).GetHiddenConstructorThatDoesntNew(typeof(int), typeof(string));
  // call the constructor (int, string) on instance
  initializer.Invoke(instance, 7, "Bill");
}

我知道我永远不应该真的需要这样做,我更想知道是否可能在已创建的对象上重新调用构造函数/初始值设定项。

2 个答案:

答案 0 :(得分:8)

ConstructorInfo对象重载MethodBase的{​​{1}}方法,但不隐藏继承的方法。您只需确保传递正确的实例即可。例如:

Invoke

但是,正如这个答案也表明的那样,没有重置任何对象的字段,并且可以编写构造函数,假设所有字段都保留在他们的默认值。如果您有这样的构造函数,那么您肯定需要确保不要弄乱任何字段,或者如果有的话重新设置它们。如果你有一个未初始化的对象,但尚未调用构造函数,那应该没问题。

答案 1 :(得分:5)

var ctor = typeof(T).GetConstructor(new[]{ typeof(int), typeof(string) });
ctor.Invoke(instance, new Object[]{ 7, "Bill" });

您正在寻找.GetConstructor


更多详情

给出以下对象:

public class Foo
{
    public Int32 a;
    public String b;
    public DateTime c;
    public Double d = 5318008;

    public Foo(Int32 a, String b)
    {
        this.a = a;
        this.b = b;
    }
}

以标准方式调用ctor会产生以下结果:

var foo = new Foo(42, "Hello, world!") { new DateTime(2014, 11, 26) };
// foo {
//   a=42,
//   b="Hello, world!",
//   c=11/27/2014 12:00:00 AM
//   d = 5318008
// }

现在让'改变d:

foo.d = 319009;
// foo {
//   a=42,
//   b="Hello, world!",
//   c=11/27/2014 12:00:00 AM
//   d=319009
// }

再次致电ctor:

typeof(Foo)
  .GetConstructor(new[]{ typeof(Int32), typeof(String) }).
  .Invoke(foo, new Object[]{ 84, "World, Hello!" });
// foo {
//   a=84,
//   b="World, hello!",
//   c=11/27/2014 12:00:00 AM // only unchanged property
//   d=5318008
// }

请注意c保持不变。这是因为&amp; b在ctor中定义,虽然不是很明显,但d也是如此(在调用ctor时实际分配了在对象级别分配的属性)。