|
-
Jan 12th, 2011, 12:44 PM
#1
[RESOLVED] 'Virtual member call in constructor'
Hi,
I got an abstract class BasePage that inherits System.Web.UI.Page for a web application, and actual pages are supposed to inherit this BasePage instead of Page directly.
The BasePage needs to create some object in its constructor using a Configuration. A Configuration is a class related to NHibernation (doesn't really matter for my question).
However, as far as I know I cannot pass this configuration via the constructor because in ASP.NET you never call the constructor of a page directly (in each case, I wouldn't know how to pass parameters to the constructor of a page even if it is possible).
So I need some other way to get the information in the constructor. I thought I could use an abstract property that the derived class has to override in which it can return the Configuration object, so I did this:
csharp Code:
public abstract class BasePage : System.Web.UI.Page
{
public BasePage() // cannot use parameters here
{
// Get the configuration it needs to use
Configuration config = this.Configuration;
// And use it
this.CreateObjectFromConfiguration(config);
}
public abstract Configuration Configuration { get; }
//...
}
My reasoning is that now, a deriving page can do supply the configuration from wherever it gets it from (for example, a session variable or whatever):
csharp Code:
public class ActualPage : BasePage
{
public override Configuration Configuration
{
get { return (Configuration)this.Session["Configuration"]; }
}
}
While conceptually this seemed to fit, ReSharper gave me a warning on line 6 of the first code sample, saying "Virtual member call in constructor". I googled the warning and I came up with a few threads that explain why this can be a problem. If I understand it correctly, in my example, the constructor of BasePage would request the Configuration property in the deriving class (ActualPage.Configuration), but the deriving class has not been created yet. I guess that this.Session["Configuration"] would then return null?
I am not in the opportunity to test it with the actual page objects at the moment, so I created a little test where I replaced Configuration with a simple Button:
csharp Code:
class Program
{
static void Main(string[] args)
{
var page = new ActualPage();
}
}
public abstract class BasePage
{
public BasePage()
{
Button btn = this.Button;
Debug.WriteLine(btn.Text);
}
public abstract Button Button { get; }
}
public class ActualPage : BasePage
{
private Button b;
public ActualPage()
{
b = new Button {Text = "test"};
}
public override Button Button
{
get { return b; }
}
}
Indeed, when I run this, I get a null reference exception on the Debug.WriteLine method as 'btn' is null.
How can I solve this problem? How can I pass the Configuration (or the Button in my example) to the constructor of the BasePage without passing it via a parameter as usual?
Thanks!
-
Jan 12th, 2011, 01:33 PM
#2
Re: 'Virtual member call in constructor'
Isn't the base constructor called before the derived constructor? If so, then the problem is simply order of operations. I'm going to do a double check online, but I believe with abstract classes, that's the case.
Edit: I am embarking on this search but perhaps before I do, I should point out the way I usually go about these things.
I create a constructor in the base class, but not the derived class. It called a virtual method that actually does my constructing. The derived class overrides the virtual method and give it innards.
Code:
class BaseClass
{
public BaseClass(string param, int param2){
DoInit(string param, int param2);
}
private abstract void DoInit(string param, int param2);
}
class DerivedClass : BaseClass
{
private override void DoInit(string param, int param2){
//Do Work
}
}
Edit 2: I am indeed correct on the order of operations. Constructors are executed according to the order of inheritance.
Last edited by Lord_Rat; Jan 12th, 2011 at 01:48 PM.
Need to re-register ASP.NET?
C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i
(Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)
-
Jan 12th, 2011, 01:39 PM
#3
Re: 'Virtual member call in constructor'
Yes, that is what I found as well, but that is exactly the problem. The BasePage constructor is getting a property on the derived class, which is not created yet (or not 'constructed' yet, I dunno if there's a difference).
In the meantime I found a way to delay the getting and using of Configuration (until it's actually required) but I'd rather do it in the constructor.
-
Jan 12th, 2011, 01:42 PM
#4
Re: 'Virtual member call in constructor'
The edit I added should handle that though. Just move the construction of the button to the equivelant of the "DoInit".
Need to re-register ASP.NET?
C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i
(Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)
-
Jan 12th, 2011, 01:59 PM
#5
Re: 'Virtual member call in constructor'
Yeah, I guess that could work. Thanks!
-
Jan 12th, 2011, 02:08 PM
#6
Re: [RESOLVED] 'Virtual member call in constructor'
No problem! Sometimes, it just takes turning the problem on its side to see the solution. =)
Need to re-register ASP.NET?
C:\WINNT\Microsoft.NET\Framework\v#VERSIONNUMBER#\aspnet_regiis -i
(Edit #VERSIONNUMBER# as needed - do a DIR if you don't know)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|