where ObjectType can be any type and MyParentClass is a base class.
public class MyWrapperClass : MyParentClass
{
private ObjectType _WrappedObject;
public ObjectType WrappedObject
{
set { _WrappedObject = value; }
}
public string Field1
{
get { return _WrappedObject.Field1; }
}
public int Field2
{
get { return _WrappedObject.Field2; }
}
// ... other stuff
}
Fortunately, .NET reflection and class generation is pretty straight-forward. Generating the class itself requires an assembly, module etc.:
AppDomain appDomain = Thread.GetDomain();
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "MyAssembly";
AssemblyBuilder assemblyBuilder
= appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule");
TypeBuilder typeBuilder
= moduleBuilder.DefineType("MyWrapperClass", TypeAttributes.Public);
typeBuilder.SetParent(typeof(MyParentClass));
The field holding our wrapped object must be declared to be the same type as the object to be wrapped
private ObjectType _ObjectToBeWrapped
This can be done with the following code:
We will also need a setter for the object
Type objectType = wrappedObject.GetType();
FieldBuilder wrappedObjectField
= typeBuilder.DefineField("_WrappedObject", objectType, FieldAttributes.Private);
And this requires some IL code generation:
public ObjectType WrappedObject { set { _WrappedObject = value; } }
Note that the "set { value = .. }" notation actually corresponds to a method "set_MyProperty(object value) {...", much like Java-style getters & setters.
// Create property ObjectToBeWrapped
PropertyBuilder wrappedObjPropertyBuilder
= typeBuilder.DefineProperty("WrappedObject", PropertyAttributes.None,
objectType, null);
// Create property setter
MethodBuilder wrappedObjSetBuilder =
typeBuilder.DefineMethod("set_WrappedObject", MethodAttributes.Public,
null, new Type[] { objectType });
ILGenerator wrappedObjSetILG = wrappedObjSetBuilder.GetILGenerator();
wrappedObjSetILG.Emit(OpCodes.Ldarg_0);
wrappedObjSetILG.Emit(OpCodes.Ldarg_1);
wrappedObjSetILG.Emit(OpCodes.Stfld, wrappedObjectField);
wrappedObjSetILG.Emit(OpCodes.Ret);
wrappedObjPropertyBuilder.SetSetMethod(wrappedObjSetBuilder);
Now for the fun bit: Create a getter for each property in the wrapped object. We iterate through the properties and generating a getter method works much like the setter above.
foreach (PropertyInfo propertyInfo in objectType.GetProperties())
{
string name = propertyInfo.Name;
if (IgnoreProperty(name))
{
continue;
}
PropertyBuilder propertyBuilder =
typeBuilder.DefineProperty(name, PropertyAttributes.None,
propertyInfo.PropertyType, null);
MethodBuilder getBuilder =
typeBuilder.DefineMethod("get_" + name, MethodAttributes.Public,
propertyInfo.PropertyType, Type.EmptyTypes);
ILGenerator getILG = getBuilder.GetILGenerator();
getILG.Emit(OpCodes.Ldarg_0);
getILG.Emit(OpCodes.Ldfld, wrappedObjectField);
getILG.Emit(OpCodes.Call, propertyInfo.GetGetMethod());
getILG.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getBuilder);
}
No comments:
Post a Comment