Retrieving static members of multiple classes programmatically
I am not sure the best approach to this problem, be it through reflection, redesigning my classes altogether, or doing something simple.
Basically I have a base class, and I can have any number of subclasses which inherit from it. Let's call the base class Shape and the subclasses CircleShape, RectangleShape, etc.
The base class is never itself instantiated, only the subclasses. Some are never instatiated, some are instantiated many times throughout the life of the program.
Sometimes I need information specific to a subclass before I instantiate it. Right now I use an enum to differentiate all subclass types. And I instantiate each subclass based on the enum in a switch statement, like this:
switch (shapeType)
{
case CircleShape:
shape = new CircleShape();
case SquareShape:
shape = new RectangleShape();
}
But say instead of having to use this kind of hardcoded switch statement, I wanted to enumerate through all the subclasses. Is there a way to automatically retrieve a list of subclasses and access the开发者_如何学JAVAir STATIC members for info about them (before instantiating them)? Or is it easier to manually instantiate each class once and add them to an array so an I enumerate through them (but not tie those instances to any actual data).
Or should I do something completely different?
You can use attributes to define metadata on your classes and then use reflection to read this metadata at runtime to decide what you want to do with this class without having to instantiate it.
Here's some information on using attributes (you can create your own custom attributes too) using attributes in C#
Here's a quick sample of what this would look like:
Class Defenition:
// ********* assign the attributes to the class ********
[BugFixAttribute(121,"Jesse Liberty","01/03/05")]
[BugFixAttribute(107,"Jesse Liberty","01/04/05", Comment="Fixed off by one errors")]
public class MyMath
{
...
Using Reflection to read the attributes:
// get the member information and use it to retrieve the custom attributes
System.Reflection.MemberInfo inf = typeof(MyMath);
object[] attributes;
attributes = inf.GetCustomAttributes(typeof(BugFixAttribute), false);
// iterate through the attributes, retrieving the properties
foreach(Object attribute in attributes)
{
BugFixAttribute bfa = (BugFixAttribute) attribute;
Console.WriteLine("\nBugID: {0}", bfa.BugID);
Console.WriteLine("Programmer: {0}", bfa.Programmer);
Console.WriteLine("Date: {0}", bfa.Date);
Console.WriteLine("Comment: {0}", bfa.Comment);
}
NOTE: Be careful with using reflection too heavily on large numbers of iterations of large number of objects though, since it comes with a significant performance cost.
You could use reflection to enumerate all your classes, but this is not a very efficient way to do things since it is kind of slow.
If they are all in the same assembly you could do something like:
class Shape
{
/* ... */
}
class CircleShape : Shape
{
public static string Name
{
get
{
return "Circle";
}
}
}
class RectangleShape : Shape
{
public static string Name
{
get
{
return "Rectangle";
}
}
}
class Program
{
static void Main(string[] args)
{
var subclasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(Shape)));
foreach (var subclass in subclasses)
{
var nameProperty = subclass.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
if (nameProperty != null)
{
Console.WriteLine("Type {0} has name {1}.", subclass.Name, nameProperty.GetValue(null, null));
}
}
}
}
Of course you could also use attributes instead of static members which would probably preferable if you want to decorate the classes with information that you wanted to look up at runtime. There are many examples of how attributes work around the internet.
精彩评论