inheritance/polymorphism and maybe generics question

J

James Crosswell

I'm not sure if I'm going about this the right way - it may be that
Generics might be able to help me out here... but here goes:

I have three classes as follows
class BaseEdit
class WidgetEdit: BaseEdit
class FooEdit: BaseEdit

These are all acutally Windows Forms and BaseEdit is an abstract class
(and so never gets instantiated). I'd like to define a method in
BaseEdit called EditSelected, which takes a proprietary grid control as
a parameter, checks to see if any items/rows in the grid are selected
and, if so, opens the creates and instance of whichever derived class
was used to call the method and shows this... I've seen various examples
of polymorphism but none that actually instantiate derived classes.

So basically what I'd like is:

class BaseEdit {
//...

public static void EditSelected(GridControl aGrid)
{
if (aGrid.SelectedRecordCount > 0)
{
BaseEdit editForm = [create instance of derived class here];
editForm.EditItem(aGrid.SelectedRow["Id"]);
}
}

//...
}

And in the code for the application I'd write something like
WidgetEdit.EditSelected( someGrid );

Is this possible? I know I could do this by overriding constructors but
I don't actually want to have to create an instance of the derived class
unless it is necessary.

Alternatively, and maybe this is what Generics are for although most of
the docs I've stumbled upon seem to refer to them in the context of
collections, I could maybe make a method that took a "Class Parameter" -
as a Delphi programmer I'm not sure what you'd call that in c#...
basically I need something which is to classes what Delegates are to
methods... so I can pass into a method:

public static void EditSelected<SomeClass>
{
SomeClass editForm = new SomeClass();
editForm.EditItem(aGrid.SelectedRow["Id"]);
}

But if it was a Generic then there'd be no way of knowing if it had an
EditItem method... I don't think... so maybe I need to throw some
interfaces in there as well.

The more I think about this the more I get the feeling I'm going about
this the wrong way in any case. Can anyone help?

Thanks in advance.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
M

Mark Wilden

public static void EditSelected(GridControl aGrid)
{
if (aGrid.SelectedRecordCount > 0)
{
BaseEdit editForm = [create instance of derived class here];
editForm.EditItem(aGrid.SelectedRow["Id"]);
}
}

If you need to create a second instance of the concrete class, then use a
factory method that the concrete classes override to return a new instance
of themself.

///ark
 
S

Simon Tamman

BaseEdit editForm = Activator.CreateInstance(this.GetType, new object[]{});

As long as it has a constructor that doesn't take any params that should
work fine.
 
S

Simon Tamman

Oh hang on I got the syntax wrong:

BaseEdit editForm = (BaseEdit) Activator.CreateInstance(this.GetType(), new
object[]{});

this.GetType() will return the type of the concrete class NOT the abstract
class, even if called within the abstract class.
Pretty nifty eh?

HTH

Simon


Simon Tamman said:
BaseEdit editForm = Activator.CreateInstance(this.GetType, new object[]{});

As long as it has a constructor that doesn't take any params that should
work fine.


James Crosswell said:
I'm not sure if I'm going about this the right way - it may be that
Generics might be able to help me out here... but here goes:

I have three classes as follows
class BaseEdit
class WidgetEdit: BaseEdit
class FooEdit: BaseEdit

These are all acutally Windows Forms and BaseEdit is an abstract class
(and so never gets instantiated). I'd like to define a method in
BaseEdit called EditSelected, which takes a proprietary grid control as
a parameter, checks to see if any items/rows in the grid are selected
and, if so, opens the creates and instance of whichever derived class
was used to call the method and shows this... I've seen various examples
of polymorphism but none that actually instantiate derived classes.

So basically what I'd like is:

class BaseEdit {
//...

public static void EditSelected(GridControl aGrid)
{
if (aGrid.SelectedRecordCount > 0)
{
BaseEdit editForm = [create instance of derived class here];
editForm.EditItem(aGrid.SelectedRow["Id"]);
}
}

//...
}

And in the code for the application I'd write something like
WidgetEdit.EditSelected( someGrid );

Is this possible? I know I could do this by overriding constructors but
I don't actually want to have to create an instance of the derived class
unless it is necessary.

Alternatively, and maybe this is what Generics are for although most of
the docs I've stumbled upon seem to refer to them in the context of
collections, I could maybe make a method that took a "Class Parameter" -
as a Delphi programmer I'm not sure what you'd call that in c#...
basically I need something which is to classes what Delegates are to
methods... so I can pass into a method:

public static void EditSelected<SomeClass>
{
SomeClass editForm = new SomeClass();
editForm.EditItem(aGrid.SelectedRow["Id"]);
}

But if it was a Generic then there'd be no way of knowing if it had an
EditItem method... I don't think... so maybe I need to throw some
interfaces in there as well.

The more I think about this the more I get the feeling I'm going about
this the wrong way in any case. Can anyone help?

Thanks in advance.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

James Crosswell

Simon said:
Oh hang on I got the syntax wrong:

BaseEdit editForm = (BaseEdit) Activator.CreateInstance(this.GetType(), new
object[]{});

this.GetType() will return the type of the concrete class NOT the abstract
class, even if called within the abstract class.
Pretty nifty eh?

Hi Simon,

Thanks for the attempt but I don't think that will work, since the
"this" keyword returns the current instance of the class - i.e. I
already have to have the class that I want to instantiate
instantiated... which is what I'm trying to avoid. The "If" clause in my
original code checks the grid to see if there are any items selected.
Only if there are items selected do I want to create an instance of the
appropriate EditForm to view the details of the selected item.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

James Crosswell

If you need to create a second instance of the concrete class, then use a
factory method that the concrete classes override to return a new instance
of themself.

Hi Mark,

Thanks for the reply. It's not so much that I need a second instance -
it's the first instance that I'm focusing on. I have some code in the
base (abstract) class in a "static" method (i.e. not associated with any
particular instance of a derived class) which says, basically, do I need
to open an edit dialog and, if so then do it.

As for overriding a method, there's no real need - the constructor is
just fine (and it's already overridden). Maybe I haven't understood
exactly what you're getting at though.

What I've come up with, which seems to work, is:

public static void EditSelected<TItemEdit>(GridView aView)
where TItemEdit fBaseEdit, new()
{
if (aView.SelectedRowsCount > 0)
{
TItemEdit editDialog = new TItemEdit();
editDialog.EditItem(uWinLib.SelectedGID(aView));
}
}

NB: uWinLib.SelectedGID is just some other code I have sitting around to
extract the ID from the selected record in the grid

It seems constraints on the Generics was all I was missing from the
puzzle before.

On the other hand, maybe the method you are/were talking about would be
a more elegant approach??? I have to call this as so:
fBaseEdit.EditSelected<fContactEdit>(someGrid);

It would be mildly more convenient to write:
fContactEdit.EditSelected(someGrid);

But I can't seem to find out a way of doing that... I can't get at the
type of a class from within a static method.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
S

Simon Tamman

I appreciate that this wont work, I didn't realise that the method was
static.
However I don't understand your response in regards to your initial query:

"opens the creates and instance of whichever derived class
was used to call the method and shows this"

So therefore you want to create an instance of the class that the method was
called from? Ay? Noe? I'm confused because you then state:

"I already have to have the class that I want to instantiate
instantiated... which is what I'm trying to avoid"

I'd agree that you'll probably want to add a type to the parameters of the
method for this to work (if it's going to remain static) as (apart from
doing some significant hijinks with reflection) it's very difficult to get
the type of object from a static method.
If you pass a type in you can still use that Activator.CreateInstance call
to create an instance of it.

Simon

James Crosswell said:
Simon said:
Oh hang on I got the syntax wrong:

BaseEdit editForm = (BaseEdit) Activator.CreateInstance(this.GetType(), new
object[]{});

this.GetType() will return the type of the concrete class NOT the abstract
class, even if called within the abstract class.
Pretty nifty eh?

Hi Simon,

Thanks for the attempt but I don't think that will work, since the
"this" keyword returns the current instance of the class - i.e. I
already have to have the class that I want to instantiate
instantiated... which is what I'm trying to avoid. The "If" clause in my
original code checks the grid to see if there are any items selected.
Only if there are items selected do I want to create an instance of the
appropriate EditForm to view the details of the selected item.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
J

James Crosswell

Simon said:
I appreciate that this wont work, I didn't realise that the method was
static.
However I don't understand your response in regards to your initial query:

"opens the creates and instance of whichever derived class
was used to call the method and shows this"

So therefore you want to create an instance of the class that the method was
called from? Ay? Noe? I'm confused because you then state:

What I wanted to do was invoke the static method using the name of one
of the derived classes - e.g.
WidgetEdit.EditSelected(someGrid);
FooEdit.EditSelected(someGrid);

The first line of code would instantiate and show a WidgetEdit dialog
(if and only if an item in the grid was selected) and the second would
instantiate and show a FooEdit dialog under the same conditions...
without having to define or override an EditSelected method in each and
every class which did almost exactly the same thing.

This may or may not be possible - it turns out I can do pretty much what
I want using Generics - as described in my reply to Mark Wilden above...
in which case I can do something like the following instead:
BaseEdit<WidgetEdit>.EditSelected(someGrid);

The syntax isn't quite as succinct as what I was originally shooting for
but is good enough for me ;-) If you know of some way to achieve what I
was originally trying to do then I'm still all ears though.

Once again, thanks for your help.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 
M

Mark Wilden

Thanks for the reply. It's not so much that I need a second instance -
it's the first instance that I'm focusing on.

Yes, I also missed the fact that the caller is static.
On the other hand, maybe the method you are/were talking about would be a
more elegant approach??? I have to call this as so:
fBaseEdit.EditSelected<fContactEdit>(someGrid);

It would be mildly more convenient to write:
fContactEdit.EditSelected(someGrid);

But I can't seem to find out a way of doing that... I can't get at the
type of a class from within a static method.

Is it required that the method be static?

///ark
 
J

James Crosswell

Mark said:
Is it required that the method be static?

Yeah that was kind of the point - the EditForm will have quite a few GUI
components on it and I didn't want to bother creating an instance of it
unless it was actually necessary (i.e. unless I was actually going to
show it). The Generics solution seems sweet though, I think it's pretty
much what I was after.

Best Regards,

James Crosswell
Microforge.net LLC
http://www.microforge.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top