このメソッドがInitから呼び出されていることを確認したい場合は、呼び出しスタックを調べることができます。このような何か:
public static bool CalledFromInit()
{
//Grab the current Stack Trace and loop through each frame
foreach(var callFrame in new StackTrace().GetFrames())
{
//Get the method in which the frame is executing
var method = callFrame.GetMethod();
//Check if the method is Control.OnInit (or any other method you want to test for)
if(method.DeclaringType == typeof(Control) && method.Name == "OnInit")
//If so, return right away
return true;
}
//Otherwise, we didn't find the method in the callstack
return false;
}
その後、あなたのようにそれを使用します。
public static void PrependTitle(this Page page, string newTitle)
{
//If we aren't called from Init, do something
if (!CalledFromInit())
{
//We could either return to silently ignore the problem
return;
//Or we could throw an exception to let the developer know they
// did something wrong
throw new ApplicationException("Invalid call to PrependTitle");
}
//Do the normally processing
page.Title = newTitle + " " + Global.TITLE_DELIMITER + " " + page.Title;
}
しかし、私は、スタックトレースは、最も信頼性の高いものではないことを警告したいです。リリースでは、あなたのコードがコールスタックでそれを見ることができないように、Control.OnInitメソッドがインライン化されるようにコードを最適化することができます。このチェックは#if DEBUG
ブロックにラップすることができるので、開発中にのみ実行されます。あなたのユースケースに応じて、DEBUG中にこの問題を捕らえ、RELEASEでチェックするのを邪魔しないように十分な場合があります。しかし、それはあなた次第です。
別のオプション... Tommy Hinrichsの答えに基づいて、あなたのすべてのページが基本クラスから継承されていれば、より確実にそれを行うことができます。私はこのようなものをお勧めしたい:それは(正確に何をしたいのように聞こえる)PREINITとINITCOMPLETEの間で呼ばれていない限り、
public abstract class BasePage : Page
{
private bool _executingInit;
protected internal override void OnPreInit(EventArgs e)
{
_executingInit = true;
base.OnPreInit(e);
}
protected internal override void OnInitComplete(EventArgs e)
{
base.OnInitComplete(e);
_executingInit = true;
}
public void PrependTitle(string newTitle)
{
if (!_executingInit)
throw new ApplicationException("Invalid call to PrependTitle.");
Title = newTitle + " " + Global.TITLE_DELIMITER + " " + Title;
}
}
そうすれば、PrependTitleが例外をスローします。
最後のオプションとして、卑劣であり、反射を使用してControl.ControlState
プロパティにアクセスすることができます(これは、コントロール状態とは関係ないため、表示状態に似ています)。そのプロパティはコントロールのライフサイクルを追跡して追跡し、以下の値を持ちます:
internal enum ControlState
{
Constructed,
FrameworkInitialized,
ChildrenInitialized,
Initialized,
ViewStateLoaded,
Loaded,
PreRendered
}
Enumは内部であることがわかります。 Control.ControlStateプロパティもそうです。しかし、Reflectionでは、これを使用することができます。また、ページの外部にある拡張メソッドから使用することもできます。
希望の方法の1つがあなたのために働くでしょう!
これは素晴らしい情報であり、私が意図したとおりに問題を解決します。ありがとう。 – roydukkey