How to determine if a class is built (instance constructor completed)?

I have a base class that has a method executed by derived classes. The method is raised by the constructor of the derived class and some methods or properties in it. I need to determine if this came from the constructor of the instance of this derived class or after it (at runtime).

The following example explains what I need:

public class Base { public Base() { } protected void OnSomeAction(object sender) { // if from derived constructor EXIT, else CONTINUE } } public class Derived : Base { public void Raise() { base.OnSomeAction(this); // YES if not called by constructor } public Derived() { base.OnSomeAction(this); // NO Raise(); // NO } } class Program { static void Main(string[] args) { var c = new Derived(); // NO (twice) c.Raise(); // YES } } 

The problem is that I cannot change the signature or arguments, because I cannot change the derived classes. Basically, I thought it would determine if the derived class (sender) was completely built.

So, the implementation is the same as it is. I cannot make changes to the base class that the derived classes break down. I can only make changes in the base class: /

Is it possible, good or not? Unfortunately, even some reflection magic or a similar hacker approach is welcome, as it is necessary: ​​/.

Thanks!

+6
source share
4 answers

Is this possible somehow ...

Yes

good or not?

Not. But you already knew that.;)

However, this is one way to do this.

 protected void OnSomeEvent( object sender, EventArgs e ) { var trace = new StackTrace(); var frames = trace.GetFrames(); for ( int idx = 0; idx < frames.Length; idx++ ) { MethodBase method; method = frames[idx].GetMethod(); if ( method.ReflectedType == typeof(Derived) && method.IsConstructor ) { return; } } /* Perform action */ } 

http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.aspx

+6
source

Nice, clean, right way - No! I'm not afraid.

The hack path, which will undoubtedly lead to pain and suffering, is possible.

Put this insie in the OnSomeEvent handler:

 var whoCalledMe = new StackTrace().GetFrame(1).GetMethod().Name; 

will be .ctor if called from the constructor, or Main when called from the Raise method.

Real-time example: http://rextester.com/rundotnet?code=DBRLC84297

+3
source

I interpret your (very serious!) Limitations, saying that you cannot change the method signatures and maybe you cannot add instance fields, but you will allow code changes and static fields. If so, my approach involves setting up the static variable "fromDerivedConstructor" and testing it as needed. (The variable is made thread-static so that the code is thread safe. The program below prints

 NO NO YES 

upon request :-)

 using System; using System.Diagnostics; namespace ConsoleApplication33 { public class Base { [ThreadStatic] protected static bool fromDerivedConstructor; public Base() {} protected void OnSomeAction(object sender) { // if from derived constructor EXIT, else CONTINUE if(fromDerivedConstructor) { Debug.WriteLine("NO"); return; } Debug.WriteLine("YES"); } } public class Derived : Base { public void Raise() { base.OnSomeAction(this); // YES if not called by constructor } public Derived() { fromDerivedConstructor=true; try { base.OnSomeAction(this); // NO Raise(); // NO } finally { fromDerivedConstructor=false; } } } internal class Program { private static void Main(string[] args) { var c=new Derived(); // NO (twice) c.Raise(); // YES } } } 
0
source

This is a strange problem, the inability to change the derivative, but can change the base? A?

Here's a very simple solution (I feel dirty):

 public class Base { private event EventHandler SomeEvent; private int initCount = 0; public Base() { } protected void OnSomeEvent(object sender, EventArgs e) { // if from derived constructor EXIT switch (initCount) { case 0: initCount += 1; Console.WriteLine("NO"); return; case 1: initCount += 1; this.SomeEvent += new EventHandler(OnSomeEvent); Console.WriteLine("NO"); return; } // else CONTINUE Console.Write("YES"); } } 
0
source

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


All Articles