Created
June 23, 2015 14:09
-
-
Save micklaw/193cddcbf3e4d0e41941 to your computer and use it in GitHub Desktop.
Override property, Proxy class C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Overriding makes sense when you look at the generated IL for overriden fields =) */ | |
public override T OverrideProperty<T>(string propertyName, Type attribute = null, Type [] constructorParams = null, object [] constructorValues = null) | |
{ | |
// [ML] - Default to an empty instance | |
constructorParams = constructorParams ?? Type.EmptyTypes; | |
constructorValues = constructorValues ?? new object[] { null }; | |
var type = typeof(T); | |
// [ML] - Proxy the class | |
var proxyNamespace = new AssemblyName(this.GetType().Namespace + ".Proxied"); | |
var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(proxyNamespace, AssemblyBuilderAccess.RunAndSave); | |
var module = assembly.DefineDynamicModule(proxyNamespace.Name); | |
var proxyType = module.DefineType(type.Name + "Proxy", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, type); | |
// [ML] - Override the virtual converted value | |
var oldProp = type.GetProperty(propertyName); | |
if (oldProp != null && oldProp.GetGetMethod().IsVirtual) | |
{ | |
var newProp = proxyType.DefineProperty(oldProp.Name, oldProp.Attributes, oldProp.PropertyType, null); | |
var backingField = proxyType.DefineField(string.Format("<{0}>k__BackingField", propertyName), oldProp.PropertyType, ributes.Private); | |
// [ML] - Add the custom attribute | |
if (attribute != null) | |
{ | |
var ctor = attribute.GetConstructor(constructorParams); | |
if (ctor != null) | |
{ | |
newProp.SetCustomAttribute(new CustomAttributeBuilder(ctor, constructorValues, new FieldInfo[0], new object[0] | |
} | |
} | |
// [ML] - Define a placeholder for a getter and setter of the new override property on the proxy class | |
var attributes = MethodAttributes.Virtual | MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributesig; | |
var pGet = proxyType.DefineMethod("get_" + oldProp.Name, attributes, oldProp.PropertyType, Type.EmptyTypes); | |
var pSet = proxyType.DefineMethod("set_" + oldProp.Name, attributes, null, new[] {oldProp.PropertyType}); | |
// [ML] - Give the getter a method body | |
ILGenerator pILGet = pGet.GetILGenerator(); | |
pILGet.Emit(OpCodes.Ldarg_0); | |
pILGet.Emit(OpCodes.Ldfld, backingField); | |
pILGet.Emit(OpCodes.Ret); | |
// [ML] - Give the setter a method body | |
ILGenerator pILSet = pSet.GetILGenerator(); | |
pILSet.Emit(OpCodes.Ldarg_0); | |
pILSet.Emit(OpCodes.Ldarg_1); | |
pILSet.Emit(OpCodes.Stfld, backingField); | |
pILSet.Emit(OpCodes.Ret); | |
newProp.SetSetMethod(pSet); | |
newProp.SetGetMethod(pGet); | |
} | |
// [ML] - Create and return a an instance | |
var newType = proxyType.CreateType(); | |
return (T)Activator.CreateInstance(newType); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
41: ... MethodAttributesig - error