Is it possible to directly call the constructor on an already created instance?

I know that you can directly refer to a static type constructor and I know that you can instantiate an object without calling a constructor , but is there a way to start a type constructor ( .ctor ) in an existing instance?

I am looking for something like:

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

I know that I really donโ€™t need to do this, Iโ€™m more interested in whether itโ€™s possible re-call the constructor / initializer on the already created object.

+6
source share
2 answers

A ConstructorInfo object overloads the MethodBase Invoke method, but does not hide inherited methods. You can just pass the correct instance. Example:

 using System; using System.Reflection; class A { public int i; public A() { Console.WriteLine("A()"); } private A(int j) { Console.WriteLine("A(" + j + "): i = " + i); } } static class Program { static void Main(string[] args) { var a = new A(); ai = 3; var constructor = a.GetType().GetConstructor(BindingFlags.Instance | BindingFlags.Public |BindingFlags.NonPublic, null, new Type[] { typeof(int) }, null); constructor.Invoke(a, new object[] { 3 }); } } 

However, as this answer shows, this does not reset any of the fields of the object, and the constructor can be written with the assumption that all fields remain by default. If you have such a constructor, you definitely need to make sure that you either do not bother with any fields, or reinstall them if you have any. If you have an uninitialized object for which the constructor has not yet been called, this should be fine.

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

You are looking for .GetConstructor .


More details

Given the following object:

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

Calling ctor in the standard way leads to the following:

 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 // } 

Now let's change d:

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

Call ctor again:

 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 // } 

Note that c remains unchanged. This is due to the fact that a and b are defined in ctor and, although not obvious, is equal to d (properties assigned at the object level are actually assigned when ctor is called).

+5
source

Source: https://habr.com/ru/post/978760/


All Articles