tags:

views:

513

answers:

3

I have a C# base class that I was to associate information with on a per-type (rather than per-instance) basis. Essentially I want all child classes to present an Icon and a FriendlyName that represents the type. I'd like to not have to create a type instance to get this information and I want to require that all child classes provide this information. Ideally it would be in the interface that the base derives from.

I tried to use a class Attribute, but it requires a constant value, so while I can set the FriendlyName, I can't set the Icon, and I can't see a way to make the Attribute required anyway, so child classes could get away with not having it (until run time).

I added a static Property to the base that children can hide, but that's kind of ugly and the values from the base are really nonsensical. It can't know what the name would be for a child. I could have the base throw in the Property, but again, that wouldn't get caught until run time.

Anyone have any ideas on how I might implement something like this? Is there a pattern I'm missing? Any out-of-the-box thinking is encouraged as well.

Edit: Really what I need to the ability to require class Attributes along an inheritance tree and be able to use an embedded resource to set those attributes. All of the information that will be returned really is static and known at compile. I just can't figure out a way to nicely expose it.

Edit 2: Here's a more concrete example of what I need:

Let's assume I have a base class:

abstract class Vehicle { ... }

I then have two children:

class Car : Vehicle { ... }

class Truck : Vehicle { ... }

I'd like to be able to get an Icon representing a "Car" or a "Truck" without having to create an instance of one (a la Car.Icon) since all vehicles of a given type will all have the same icon.

I also want to ensure that all Vehicle-derived Types expose the same way to get this Icon in case someone comes along in the future and adds a new class

class Airplane : Vehicle  { ... }

Edit 3: Why do I need this? Well we have an app that can take plug-ins. The plug in is defined by a type, and when the type is loaded, we show the user an icon and name. When they click the icon, it creates an instance of that type (and gives them a dialog for naming the instance, etc). I don't need or want to have to create an instance of the type to get the icon.

+1  A: 

If you want to absolutely dictate that the child implement this, then the only way I see doing it is making the base class abstract, and expose instance properties to return the icon and friendly name.

These would be abstract, not virtual, so you force the implementation by the derived class. I know it's not clean, in that it is information that is better stored on the type level, but it's the only way I can see to enforce this requirement at compile-time.

casperOne
Yeah, that's the route I've gone, but I just feel dirty doing it. Having to create an instance to get the info adds some complexity to how it's used.
ctacke
+1  A: 

I think the point you may have missed is that you can't override static properties for a good reason -- namely that when you're writing code to call it, you don't have an instace, so the complier will statically link it at that time -- if you need polymorphism, you need to be working with an instance for the runtime to work out which version of the method to call.

EDIT: (In response to your EDIT2)

What scenario would you want to be calling this from?

If you're wanting to show your icon against an instance, you've got an instance, so why not have it as a property on the instance (because, after all, somebody might override your Car to create a SportsCar and want a different icon for it) -- in effect you're asking for a property of your object, albeit one that matches the conceptual model (so it's not the number of wheels, the max speed, etc; but something to visualise it to the end user)

EDIT2: (In response to your EDIT3)

The approach I'd do would be something along the lines using an attribute to identify which embedded resource to use as the icon for the respective type (so you don't need an instance), and use reflection to read the value. You could define your own custom attribute, or look at ToolboxItemAttribute which might be of use.

Rowland Shaw
No, I've not missed it - which is why the title includes "conceptually". I know I can't inherit a static but I have a need for that conceptual behavior.
ctacke
Break out the abstract readonly properties, or maybe an interface then :)
Rowland Shaw
Yea, but with properties or an interface, you'd still have to have an instance of the derived class to get that info. The OP is trying to avoid having to create an instance just to get this info which is the same for all objects of this type.
BFree
Turn the question around -- how would you call the derived version, rather than the base implementation? -- the best you can do is to shadow the parent, but you'll always be specifying the exact type's version to use.
Rowland Shaw
I'd be using this in a plug-in scenario. The icon is for the plug-in type. When the user clicks on it, it creates an instance. I don't need (or want) an instance until they do that click, but I do need the icon (and name).
ctacke
Did you get anywhere using this approach orf reflection and attributes?
Rowland Shaw
No. Attributes work for contants, but there are two inherent problems: 1. you can't force a chile to implement an attribute and 2. You can't verify that the string refers to a valid resource at compile time.
ctacke
You could refuse to load it if it didn't support your attribute...I take it you've read Microsoft's guidance on creating a plug-in Framework at http://msdn.microsoft.com/en-us/library/ms972962.aspx ?
Rowland Shaw
A: 

Maybe what you can do is to define an attribute that will be used for registering that object in your plugin system.

This way you will enforce the developer of the class to assign the attribute in order to work within your plugin system.

Maybe you can use an approach like the ToolboxBitmapAttribute, where you can set an image found into a resource of your dll.

jmservera