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();
                });
            }