I'm having some serious trouble accessing a virtual method of a base
class - that is not the immidate base class.
This is the basic situation that I have:
================================================== =========
class A
{
public virtual string PrintMe()
{
return "Original A";
}
}
class B : A
{
public override string PrintMe()
{
return "Overriden B";
}
}
class C : B
{
public override string PrintMe()
{
return "Overriden C";
}
}
================================================== =========
Now, what I'm trying to do is to from an instance of C call A's
PrintMe() method. I've tried various delegate twists, I've tried
reflection - without any luck. It insists on returning the top of the
virtual call table - C's PrintMe().
Any ideas or suggestions?
thanks
--Lucas 25 3769
Why do you want to do this? Maybe there is another way to get the
effect you want, without having to call up the class hierarchy like
that.
Basically it's about deploying components on a selectable level. The
whole story is a bit complicated, but basically the story is that each
class has its own to/from XML methods that store various properties and
settings that belong to the class.
The basic idea is that there are base classes, which are .NET Compact
framework compatible while the user works with classes that inherit
them and have extensive GUI etc. When the system is deployed, we need
to get the XML of the base classes..
Anyway, the whole thing is too complicated to briefly cover here -
there's a bunch of restrictions on how it can be done. Bottom line is
that I really need to do it the way I described it.
How about using base.PrintMe from B? Have a protected method in B that
calls base.PrintMe() and call that method from C.
using System;
class A
{
public virtual void PrintMe() { Console.WriteLine("A"); }
}
class B : A
{
public override void PrintMe() { Console.WriteLine("B"); }
protected void BasePrintMe() { base.PrintMe();}
}
class C : B
{
public override void PrintMe() { BasePrintMe(); }
}
class T
{
public static void Main()
{
A a = new C();
a.PrintMe();
}
}
Regards
Senthil
Lucas... The language does support:
1) Use new instead of override which destroys polymorphic behaviour but
allows access to the base method through a reference variable of the
base type.
2) In the subclass method you can call super.PrintMe()
class Class2 : Class1
{
public override string Test()
{
return base.Test()+"Class2";
}
}
Regards,
Jeff Now, what I'm trying to do is to from an instance of C call A's
PrintMe() method. I've tried various delegate twists, I've tried
reflection - without any luck. It insists on returning the top of the
virtual call table - C's PrintMe().<
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it! lu**********@hotmail.com <lu**********@hotmail.com> wrote: Basically it's about deploying components on a selectable level. The whole story is a bit complicated, but basically the story is that each class has its own to/from XML methods that store various properties and settings that belong to the class.
The basic idea is that there are base classes, which are .NET Compact framework compatible while the user works with classes that inherit them and have extensive GUI etc. When the system is deployed, we need to get the XML of the base classes..
Anyway, the whole thing is too complicated to briefly cover here - there's a bunch of restrictions on how it can be done. Bottom line is that I really need to do it the way I described it.
Well, the bottom line is that you *can't* do what you originally asked.
You can't call a grandparent method if it's overridden in the parent.
However, if you make each method call the base method, making them pick
and choose what they react to, it should work fine.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Unfortunately that's not an option as I don't know beforehand how long
the chain is. I need to do this with an arbitrary amount of inheretence
steps.
> Well, the bottom line is that you *can't* do what you originally
asked. You can't call a grandparent method if it's overridden in the parent.
Well, that's not quite true either. I have no problem doing it through
IL, so as far as the runtime environment goes, it's no problem. It's c#
that's blocking me.
Thanks, but I'm aware of the basic language limitations. Unfortunately,
as I said in the original post, I can't use new. And base doesn't cut
it as it only goes one level and I can't get to it from outside.
What I'm trying to do is get around it through reflection, but without
resorting to have to emit in IL what I need. I don't see why the
runtime constantly refuses me access to any level of the virtual call
table. I always end up at the top, with the last overriden class. The
furthest I have come is to get an actual function pointer (IntPtr) to
the method I want, but when I use it through
RuntimeMethodHandle->MethodHandle, I again end up at the top of the
virtual table, with a call to the last method in the virtual table.
--Lucas
"lu**********@hotmail.com" wrote: Thanks, but I'm aware of the basic language limitations. Unfortunately, as I said in the original post, I can't use new. And base doesn't cut it as it only goes one level and I can't get to it from outside.
What I'm trying to do is get around it through reflection, but without resorting to have to emit in IL what I need. I don't see why the runtime constantly refuses me access to any level of the virtual call table. I always end up at the top, with the last overriden class. The furthest I have come is to get an actual function pointer (IntPtr) to the method I want, but when I use it through RuntimeMethodHandle->MethodHandle, I again end up at the top of the virtual table, with a call to the last method in the virtual table.
--Lucas
it's restricted because that's just how polymorphism suppose to work.
and why can't you use new? from what you described, sounds to me like you
want to hide the base method, not override it.
Just because you can, doesn't mean you should.
<lu**********@hotmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com... Well, the bottom line is that you *can't* do what you originally asked. You can't call a grandparent method if it's overridden in the parent.
Well, that's not quite true either. I have no problem doing it through IL, so as far as the runtime environment goes, it's no problem. It's c# that's blocking me.
I can't use new, because I'm not in control of writing the children
clasess, and forgetting to use new would have nasty consequences.
To explain a bit more, suppose you have these classes:
Atom - contains basic from/to XML serialization functions
Adder:Atom - a class that adds two numbers
AdderGui: Adder - graphical version of Adder, in windows forms
AdderNiceGui: AdderGui, with surround sound, 3d blah blah - i.e a whole
bunch of things
Each class sets/gets XML to store its current state. This is done by
overriding the ToXml and FromXml methods, that have originally been
defined in Atom. The XML works by iteratively encapsulating the lower
levels. So for instance, the Adder XML might look like this (produced
by it's ToXml() ):
<adder class=Adder>
<anum>1</anum>
<bnum>2</bnum>
</adder>
The AdderGui might then look like this:
<addergui class=AdderGui>
<window size=100></>
<base class=Adder>
<adder class=Adder>
<anum>1</anum>
<bnum>2</bnum>
</adder>
</base>
</adderGui>
The AdderNiceGui might look something like this:
<addernicegui class=AdderNiceGui>
<sound mode=surround></sound>
<gfx mode=d3d></gfx>
<base class=AdderGui>
<addergui class=AdderGui>
<window size=100></>
<base class=Adder>
<adder class=Adder>
<anum>1</anum>
<bnum>2</bnum>
</adder>
</base>
</adderGui>
</base>
</addernicegui>
Ok?
Now the user will during run-time use the AdderNiceGui and AdderGui
classes. Once he is done configuring them, he wants to deploy them to
..NET compact. Only the pure Adder class is compact framework
compatible, so I need from the AdderNiceGui class, extract the Adder
class, for deployment. No problems there. Now we want the XML for just
the Adder class - which we get from Adder's ToXml(). And this is where
the problem comes in that from AdderNiceGui, there seems to be no
(civilized) way of getting through a call to Adder's ToXml.
There are a number of design restrictions - such as easy implementation
of new classes as well as that the individual class XML can be whatever
(in short, you can't trust to extract any structural info from the
XML). Each class is responsible for getting the XML from its baseclass
and incorporating it to its XML etc
That's the practical context of it. lu**********@hotmail.com <lu**********@hotmail.com> wrote: Well, the bottom line is that you *can't* do what you originally asked. You can't call a grandparent method if it's overridden in the parent.
Well, that's not quite true either. I have no problem doing it through IL, so as far as the runtime environment goes, it's no problem. It's c# that's blocking me.
You can't do it in C#. Your question is in a C# newsgroup, so I think
it's reasonable to assume you wanted a C# solution.
(There's the matter of "should" as well, where I'd say that you
shouldn't do this even if you could.)
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too lu**********@hotmail.com <lu**********@hotmail.com> wrote: Thanks, but I'm aware of the basic language limitations. Unfortunately, as I said in the original post, I can't use new. And base doesn't cut it as it only goes one level and I can't get to it from outside.
Base only goes one level, but if every method calls base, then you end
up getting all the way up the tree.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
It sounds like you just want to use classes that are already in (and named
different names) - from your base classes. Is this correct?
If so, you just call them - the runtime "figured out" that you mean call it
from a base class if another version doesn't exist higher up..
In other words, if you have BaseTest.FormatIt - then you inherit from that
and create BaseTestTwo.FormatItBetter and you inherit from BaseTestTwo and
create BaseTestThree and and have FormatItBest..
From BaseTestThree, you have access to all of those methods:
BaseTestThree objBTT = new BaseTestThree();
objBTT.FormatIt();
objBTT.FormatItBetter();
objBTT.FormatItBest();
Those are all valid. Is that what you are trying to do??
<lu**********@hotmail.com> wrote in message
news:11**********************@f14g2000cwb.googlegr oups.com... I can't use new, because I'm not in control of writing the children clasess, and forgetting to use new would have nasty consequences.
To explain a bit more, suppose you have these classes:
Atom - contains basic from/to XML serialization functions Adder:Atom - a class that adds two numbers AdderGui: Adder - graphical version of Adder, in windows forms AdderNiceGui: AdderGui, with surround sound, 3d blah blah - i.e a whole bunch of things
Each class sets/gets XML to store its current state. This is done by overriding the ToXml and FromXml methods, that have originally been defined in Atom. The XML works by iteratively encapsulating the lower levels. So for instance, the Adder XML might look like this (produced by it's ToXml() ):
<adder class=Adder> <anum>1</anum> <bnum>2</bnum> </adder>
The AdderGui might then look like this:
<addergui class=AdderGui> <window size=100></> <base class=Adder> <adder class=Adder> <anum>1</anum> <bnum>2</bnum> </adder> </base> </adderGui>
The AdderNiceGui might look something like this:
<addernicegui class=AdderNiceGui> <sound mode=surround></sound> <gfx mode=d3d></gfx> <base class=AdderGui> <addergui class=AdderGui> <window size=100></> <base class=Adder> <adder class=Adder> <anum>1</anum> <bnum>2</bnum> </adder> </base> </adderGui> </base> </addernicegui>
Ok?
Now the user will during run-time use the AdderNiceGui and AdderGui classes. Once he is done configuring them, he wants to deploy them to .NET compact. Only the pure Adder class is compact framework compatible, so I need from the AdderNiceGui class, extract the Adder class, for deployment. No problems there. Now we want the XML for just the Adder class - which we get from Adder's ToXml(). And this is where the problem comes in that from AdderNiceGui, there seems to be no (civilized) way of getting through a call to Adder's ToXml.
There are a number of design restrictions - such as easy implementation of new classes as well as that the individual class XML can be whatever (in short, you can't trust to extract any structural info from the XML). Each class is responsible for getting the XML from its baseclass and incorporating it to its XML etc
That's the practical context of it.
Rather than doing tricky things with Reflection and IL, why not just do
this:
Adder declares not two, but _four_ public methods:
public virtual ... FromXml(...) {...}
public virtual ... ToXml(...) {...}
which is what you have (and have overridden in the various child
classes) and
public ... FromCompactCompatibleXml(...)
{
return FromXml(...);
}
public ... ToCompactCompatibleXml(...)
{
return ToXml(...);
}
which emits XML that is compatible with the Compact Framework version
of the class, and is not virtual, so cannot be overridden.
Child classes override and embellish ToXml and FromXml, but when it's
time to deploy to the Compact Framework, you call the CompactCompatible
methods, which are inherited directly from the base class.
In effect, you give alternate names to FromXml() and ToXml() in the
base class, and forbid inheriting classes from overriding the meaning
of those names, so that you can always get at them from any child class.
>In effect, you give alternate names to FromXml() and ToXml() in the base class, and forbid inheriting classes from overriding the meaning of those names, so that you can always get at them from any child
class.
I can't quite do that as the level at which you choose to deploy is
arbitrary. There can be several components (classes) in the same line
of inheritence that need to be deployed.
And in addition, it isn't an aesthetically pleasing solution, as the
XML method would have to be implemented twice in the deployable class.
Emiting IL is more complicated, but this I can do on my side, sparing
those that write the components to write redundant code.
>Base only goes one level, but if every method calls base, then you end up getting all the way up the tree.
Nah, base is hard-wired at compile time to the actuall base class where
it is defined (not too strange). For it to work, each child-class would
have to actually implement the base call, resulting in unnecessary and
redundant code that could easily introduce errors throughout the entire
inheritance chain.
Thanks for your suggestions, they are appreciated, but I'm really not
looking for a workaround to the problem. What I need help with is how
to accomplish it, through reflection, without resorting to IL.
>Those are all valid. Is that what you are trying to do??
Nope, can't do that either. The only thing I know about the classes
comes from a simple interface (that specifies To/From Xml methods).
Their assemblies are dynamically loaded (plugins) and I have no
knowledge of them at compile time - apart from that they implement a
number of interfaces.
>You can't do it in C#. Your question is in a C# newsgroup, so I think it's reasonable to assume you wanted a C# solution.
Fair point, I probably should have posted it in one of the more
specific .NET framework groups, since it's more about reflection than
about C#. The problem is that this quite doable from for instance
managed C++, so my problem is C# specific.
Anyway, thanks to all of you for the suggestions. This is as has been
mentioned, not an C# issue per se, but rather an reflection/CLR issue.
Perhaps I'll try in the CLR or the Interop (might surprise you, but
Interop is the closest thing I've come to finding a solution) groups.
For the project, it doesn't quite matter at this point, as a
formalization of the XML was required because of other factors. And
through that the necessary info can be extracted directly from the XML
and no multiple level base calls are necessary. I'm still very curious
of how what I described can be accomplished, but it's not a high
priority anymore.
Thanks again.
--Lucas
> I can't quite do that as the level at which you choose to deploy is
arbitrary.
Do you mean that the highest level at which you could deploy to the
Compact Framework could be one of the child classes? Well, then I guess
you have to make the "CompactFramework" methods virtual, and trust the
inheriting child classes to override them only when they can, in fact,
deploy to the compact framework. There can be several components (classes) in the same line of
inheritence that need to be deployed.
OK, now I'm confused again. I thought you said that along a single line
of inheritance, there was some base class that you were trying to find,
which was the one for which you wanted to call ToXml(). Now you're
saying that you may want to call ToXml() for several of the classes up
the hierarchy? Why would you do that when the highest-level one will
include the XML for all of the lower-level ones, and supposedly you're
deploying the most sophisticated control you can to the compact device?
Obviously I don't fully understand what you're trying to achieve. :(
And in addition, it isn't an aesthetically pleasing solution,
Aesthetics is in the eye of the beholder. :) Me, I find messing around
in IL and using Reflection to play tricks aesthetically ugly. :)
I would much prefer to make the situation explicit in my interface:
this class can export to the Compact Framework / this class can't and
instead defers to its base class. In essence I see what you're trying
to do is to load two jobs into one method: Emit XML for the regular
framework and emit XML to deploy to the compact framework, and decide
which to do based on some funky Reflection / IL mashing... or am I not
getting what you're trying to do?
as the XML method would have to be implemented twice in the
deployable class.
Implemented? No, not at all. More like declared. The CompactFramework
versions would never have any more of a body that simply a call to the
corresponding "regular framework" version. Classes that can deploy to
the CF contain an overload. Those that can't, don't. The net effect is
that calling the CompactFramework version of the method will "search up
the hierarchy" until it finds the first class that can deploy to the
framework, and use that class's version of the method, which will
simply call that class's ToXml(). If that's not exactly what you want
to do, then please help me understand better.
Emiting IL is more complicated, but this I can do on my side, sparing
those that write the components to write redundant code.
Nobody has to write redundant code, unless you count three lines of
code in each class that can be deployed to the framework as being
"redundant".
One thing I certainly don't understand is how, if you're going to take
care of this "automagically" under the covers, are you going to figure
out which of the derived classes can be deployed to the framework (and
thus their ToXml() should be used) and which can't (and so you have to
keep searching up the hierarchy)? lu**********@hotmail.com <lu**********@hotmail.com> wrote: Base only goes one level, but if every method calls base, then you end up getting all the way up the tree.
Nah, base is hard-wired at compile time to the actuall base class where it is defined (not too strange). For it to work, each child-class would have to actually implement the base call, resulting in unnecessary and redundant code that could easily introduce errors throughout the entire inheritance chain.
Only the classes which override the method would need to call base.Foo.
It's not that hard to do, and it would be very easy to make the top-
level base class keep a flag to check whether or not it had been done
properly (as you could check that *all* methods had been called simply
by knowing whether or not the top method had been called). You could
test the flag after calling the method.
Thanks for your suggestions, they are appreciated, but I'm really not looking for a workaround to the problem. What I need help with is how to accomplish it, through reflection, without resorting to IL.
Then choose a different language, basically.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace Testing_Samples
{
public class Form2 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
public Form2()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
private void InitializeComponent()
{
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "Form2";
this.Text = "Form2";
this.Load += new System.EventHandler(this.Form2_Load);
}
private void Form2_Load(object sender, System.EventArgs e)
{
C a = new C();
//Invoking Class C Method
MessageBox.Show(a.PrintMe());
//Casting with Class A Method
MessageBox.Show(((A)a).PrintMe());
}
}
class A
{
public string PrintMe()
{
return "Original A";
}
}
class B : A
{
public string PrintMe()
{
return "Overriden B";
}
}
class C : B
{
public string PrintMe()
{
return "Overriden C";
}
}
}
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace Testing_Samples
{
public class Form2 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
public Form2()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
private void InitializeComponent()
{
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "Form2";
this.Text = "Form2";
this.Load += new System.EventHandler(this.Form2_Load);
}
private void Form2_Load(object sender, System.EventArgs e)
{
C a = new C();
//Invoking Class C Method
MessageBox.Show(a.PrintMe());
//Casting with Class A Method
MessageBox.Show(((A)a).PrintMe());
}
}
class A
{
public string PrintMe()
{
return "Original A";
}
}
class B : A
{
public string PrintMe()
{
return "Overriden B";
}
}
class C : B
{
public string PrintMe()
{
return "Overriden C";
}
}
}
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Hmmm... code with no explanation, and it's code that doesn't even
compile!
I understand the implication: that declaring PrintMe() in classes A, B,
and C will cause "Original A" to print out if you cast a reference of
type "C" to type "A". I assume that you meant to say that:
C a = new C();
//Invoking Class C Method
MessageBox.Show(a.PrintMe());
//Casting with Class A Method
MessageBox.Show(((A)a).PrintMe());
will display two message boxes: one that says, "Overridden C" and the
next that says, "Original A". Unfortunately, if you had tried to
compile this code, you would have found that it wouldn't, because you
must make A's PrintMe "virtual", and specify either "override" or "new"
on B and C's PrintMe.
The behaviour you are claiming will happen only if you declare the
PrintMe methods in B and C to be "new". "new," however, isn't an
override, so you won't get the polymorphic behaviour that the OP wants.
If you were to specify "override," you would get the behaviour that the
OP wants, but both message boxes would display "Overridden C." That, in
a nutshell, was the OP's problem: how to have both message boxes
display "Overridden C," but then go back to call the base method
("Original A") on demand.
Unfortunately, no can do (in C#). This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Graham Banks |
last post by:
Does using multiple inheritance introduce any more performance overhead than
single inheritance?
|
by: Stuart Golodetz |
last post by:
Hi,
I've got a minor casting issue which I need to check about (marked // <--).
I was trying to do a static_cast on it (which didn't work, though I'm not
sure why this should be the case?) I...
|
by: Josh Lessard |
last post by:
Hi all. I'm maintaining a C++ program and I've come across a nasty piece
of code that works, but I just don't understand why. I'm not actually
this part of the program, but I really want to know...
|
by: tshad |
last post by:
Can you do a search for more that one string in another string?
Something like:
someString.IndexOf("something1","something2","something3",0)
or would you have to do something like:
if...
|
by: Emmanuel |
last post by:
Hi,
I'm working on a c# web app and require having some code which runs in the
page Load event of each page and to be reusable in other web apps.
So i decided to use a Class Library which...
| |
by: Mark P |
last post by:
#include <iostream>
using namespace std;
struct Base
{
virtual int foo () {return 1;}
virtual int foo (int i) {return 2;}
virtual ~Base () {}
};
|
by: Shawnk |
last post by:
Some Sr. colleges and I have had an on going discussion relative to when and
if
C# will ever support 'true' multiple inheritance.
Relevant to this, I wanted to query the C# community (the...
|
by: John |
last post by:
Hi All,
Although C# has Generics, it still does not support the generic
programming paradigm. Multiple inheritance is required to support real
generic programming. Here is a simple design pattern...
|
by: junyang |
last post by:
Hi all,
I have one DTD fragment, base.dtd, that contains a bunch of useful
element definitions (say an element named "base"), and two DTD
fragments, a.dtd and b.dtd, that each build on base.dtd...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...
| |