static void ImplementIDataTransferObject(EmittedClass builder, EmittedConstructor cctor, List <PropertyInfo> props, EmittedField dirtyFlags) { builder.AddInterfaceImplementation(typeof(IDataTransferObject)); ImplementIDataTransferObjectGetDirtyFlags(builder, dirtyFlags); ImplementIDataTransferObjectResetDirtyFlags(builder, props, dirtyFlags); ImplementIDataTransferObjectIsDirty(builder, cctor, props, dirtyFlags); ImplementICloneableClone(builder, props, dirtyFlags); }
static void ImplementIDataTransferObjectIsDirty(EmittedClass builder, EmittedConstructor cctor, List <PropertyInfo> props, EmittedField dirtyFlags) { var fieldMap = builder.DefineField <string[]>("__fieldMap"); fieldMap.ClearAttributes(); fieldMap.IncludeAttributes(FieldAttributes.Static | FieldAttributes.InitOnly | FieldAttributes.Private); cctor.ContributeInstructions((m, il) => { var arr = il.DeclareLocal(typeof(String[])); il.Nop(); il.NewArr(typeof(string), props.Count); il.StoreLocal(arr); for (var i = 0; i < props.Count; i++) { il.LoadLocal(arr); il.LoadValue(i); il.LoadValue(props[i].Name); il.Emit(OpCodes.Stelem, typeof(string)); } il.LoadLocal(arr); il.StoreField(fieldMap); il.Nop(); il.Nop(); }); var method = builder.DefineMethod("IsDirty"); method.ClearAttributes(); method.IncludeAttributes(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final); method.ReturnType = TypeRef.FromType <bool>(); method.DefineParameter("member", typeof(String)); method.ContributeInstructions( (m, il) => { il.DeclareLocal(typeof(Int32)); il.DeclareLocal(typeof(bool)); il.DeclareLocal(typeof(bool)); var proceed = il.DefineLabel(); var yep = il.DefineLabel(); il.Nop(); il.LoadArg_1(); il.LoadNull(); il.CompareEqual(); il.LoadValue(false); il.CompareEqual(); il.StoreLocal_2(); il.LoadLocal_2(); il.BranchIfTrue_ShortForm(proceed); il.LoadValue("member"); il.New <ArgumentNullException>(typeof(string)); il.Throw(); il.MarkLabel(proceed); il.LoadField(fieldMap); il.LoadArg_1(); var indexOf = typeof(Array).MatchGenericMethod("IndexOf", BindingFlags.Public | BindingFlags.Static, 1, typeof(int), typeof(string[]), typeof(string)); il.Call(indexOf.MakeGenericMethod(typeof(string))); il.StoreLocal_0(); il.LoadLocal_0(); il.LoadValue(0); il.CompareLessThan(); il.LoadValue(0); il.CompareEqual(); il.StoreLocal_2(); il.LoadLocal_2(); il.BranchIfTrue(yep); il.Nop(); il.LoadValue("member"); il.LoadValue(String.Concat(typeof(T).GetReadableSimpleName(), " does not define property: `")); il.LoadArg_1(); il.LoadValue("`."); il.Call <string>("Concat", BindingFlags.Static | BindingFlags.Public, typeof(string), typeof(string), typeof(string)); il.NewObj( typeof(ArgumentOutOfRangeException).GetConstructor(new[] { typeof(string), typeof(string) })); il.Throw(); il.MarkLabel(yep); il.LoadArg_0(); il.LoadFieldAddress(dirtyFlags); il.LoadLocal_0(); il.Call <BitVector>("get_Item", typeof(int)); il.StoreLocal_1(); il.DefineAndMarkLabel(); il.LoadLocal_1(); }); }