C # make class auto registrar

I have several types for which I need to provide custom functions that speak to the outside world. For example, I can have a Widget and a Sprocket, and when data from the world that I have no control over comes in and says "make a widget", then I need to call the Widget.Create () function. If the world says "make a hammer" then I need to return the error "Hummer does not exist". However, the mapping between the world view and the type name is not 1: 1, so I can't just use reflection to find the type name directly - I need a table. (In fact, "name" can be, for example, a specific integer value.)

I understand how I can use a predefined table (or dictionary) that maps from world view to class name. I also understand how to extend / modify this table at runtime if the set of possible classes changes. (Due to rule changes or dynamically loaded parts of the application, or whatever.)

However, all this requires duplication - I must both implement my class and elsewhere in the code, do not forget to add an instance "this class has this name in the outside world". This is a bit of a code smell because in the future I will write a new class (or delete the old class) and forget to update the table and then spend time debugging why it doesn't work correctly.

I thought I could use a static member in every class that registers with the global table:

public static Registration Me = new Registration(typeid(MyClass), "My Name");

      

Unfortunately, static fields are not initialized until some function in the class is executed, so this does not run on startup. (Static constructors have similar limitations, plus even more run-time overhead!)

The next idea was to decorate the class with a special attribute that says "register this class in the table".

[Register("My Name")]
class MyClass : .... {
}

      

Unfortunately, the "Register" attribute does not know which class it is attached to - only the MyClass class knows that it has a Register attribute. (This annoys me as it would be SO CONVENIENT if the attributes knew where they were attached in many, many cases. But that's aside!)

So, the least bad implementation I can think of is to iterate over all types of all assemblies using reflection and check if they have this attribute, and if they do, register them in the table. This is, shall we say, neither elegant nor efficient.

Is there a better way to automatically register classes without updating any other source file with a central registry?

+3


source to share


1 answer


I've checked with other resources (who are knowledgeable about the internals of the CLR and IL) and it seems like a hole in the CLR and C # language. There is simply no direct way to make things automatically happen when you build or prepare your application. Walking the types and looking for the types that interest me is not good. In fact, attributes aren't always created until some parts of the code ask for them, so I can't use the type argument attribute constructor to automatically register either!



This is, of course, not very good, because if there are eight different pieces of code, each with its own kind of registration that they want to do, each of these pieces must iterate over all the types and check for their own. The only way to get around this is to abandon modularity and make all the different "things" that happen to types centralized for a single all-all-types loop at the start of the application. Third party libraries (including MEF) will still not go through this loop, so there is only an inevitable chunk of overhead here, or an inevitable chunk of duplication is my choice as a developer.

0


source







All Articles