Avner Kashtan wrote a nice post about using reflection to verify you are subscribed to an event:
FieldInfo delegateField = myObj.GetType().GetField(”MyEvent”, BindingFlags.NonPublic BindingFlags.Instance);
EventHandler del = delegateField.GetValue(myObj) as EventHandler;
And once we had that - it’s a simple matter of iterating the invocation list and seeing whether I’ve registered already:
foreach (EventHandler handler in del.GetInvocationList())
{
if (handler.Target == this)
return true;
}
Just be aware to the fact that using Obfuscation to protect your code will break this code.
Comment » | Uncategorized
I have a class BaseFoo and several classes that inherite from it.
I needed to create instances of the descendants classes based on an integer value loaded from a database row.
The typical solution for this is a factory method pattern, but this pattern requires updating of the factory method every time I create a new descendant (’Foo’) class.
I wanted a way around this.
I needed a method which will extract all available classes from the assembly and will be able to locate the correct class according to the database row information and create a new instance.
At first I added a contant integer to each Foo class, but this meant using reflection to retrieve this constant, searching for the constant’s name and comparing it to a hard-coded string - meaning total meltdown the minute I changed the constant name or used obfuscation.
Instead I created a new Enum containing a range of integer values, this meaning I will search for a type, not a string. During run-time, first I retrieve all Foo classes to a memory dictionary containing also the unique Enum value of each class.
Then for each database row I lookup the integer value (from the database) in the dictionary and use reflection to call the class’s constructor.
private Dictionary FooClasses = new Dictionary();
//Create the memory table
private void BuildClassesMemoryTable()
{
Type[] types = Assembly.GetExecutingAssembly().GetTypes();
for (int i=0; i < types.Length; i++)
{
if (types[i].BaseType == typeof(BaseFoo))
{
foreach (FieldInfo fi in types[i].GetFields())
{
if (fi.FieldType == typeof(FooEnum))
{
FooClasses.Add((int)fi.GetValue(null), types[i]);
break;
}
}
}
}
}
//Create a new instance of a Foo class
private BaseFoo CreateKnownClass()
{
//Create an array of parameter types according to the constructor’s signature to retrieve it
Type[] parameterTypes = new Type[2];
parameterTypes[0] = typeof(String);
parameterTypes[1] = typeof(int);
//Constructor’s parameters
Object[] parameters = new Object[parameterTypes.Length];
parameters[0] = “Hello”;
parameters[1] = 42;
return (BaseFoo)((Type)FooClasses[FooClass.ClassID]).GetConstructor(parameterTypes).Invoke(parameters);
}
private void LoadFromDatabase()
{
for (int i = 0; i < tables.fooDataSet.Rows.Count; i++)
{
//Some code to find the Foo class id from the database row…..
if (FooClasses.ContainsKey(fooClassID))
{
CreateKnownClass();
}
}
}
Comment » | Uncategorized
Suppose you have a form containing a number of data adapters, each linked to few sql command classes.
You have a single sql connection class and you want to link all commands to this connection on runtime:
foreach (FieldInfo fi in this.GetType().GetFields(BindingFlags.NonPublic & BindingFlags.Instance))
{
if (fi.FieldType == typeof(SqlCommand))
(fi.GetValue(this) as SqlCommand).Connection = sqlConnection1;
}
Comment » | Uncategorized