如果您想蛮力确保从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的回答上,如果你所有的页面都从一个基类继承,你将能够更可靠地做到这一点。我建议是这样的:
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会抛出异常,除非它被称为PreInit和InitComplete(这听起来像你想要什么)之间。
作为最后一个选项,您可能会偷偷摸摸地使用反射来访问Control.ControlState
属性(这是一个令人困惑的名称,因为它与控件状态无关 - 类似于视图状态)。该属性会跟踪控件,因为它会抛出其生命周期 - 它具有以下值:
internal enum ControlState
{
Constructed,
FrameworkInitialized,
ChildrenInitialized,
Initialized,
ViewStateLoaded,
Loaded,
PreRendered
}
您会注意到Enum是内部的。 Control.ControlState属性也是如此。但是使用反射,你可以使用它 - 你甚至可以从页面外部的扩展方法中使用它。
希望这些方法之一将为您工作!
这是很棒的信息,并按我的意图解决了这个问题。谢谢。 – roydukkey