private static void DefineGuardedProperty(PropertyInfo property, TypeBuilder typeBuilder, FieldInfo field, Type objectType, IEntityMap entityMap) { // create the new property. var propertyBuilder = typeBuilder.DefineProperty(property.Name, System.Reflection.PropertyAttributes.HasDefault, property.PropertyType, null); // The property "set" and property "get" methods require a special set of attributes. //var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual; var getSetAttr = MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.SpecialName; // create the getter if we can read. if (property.CanRead) { // create the get method for the property. var getMethodName = "get_" + property.Name; var getMethod = typeBuilder.DefineMethod(getMethodName, getSetAttr, property.PropertyType, Type.EmptyTypes); // get the IL generator to generate the required IL. ILGenerator il = getMethod.GetILGenerator(); // directly call the inner object's get method of the property. if (Reflector.IsDataEntityList(property.PropertyType, out var elementType)) { var isInterface = property.PropertyType.GetGenericTypeDefinition() == typeof(IList <>); var asReadOnlyMethod = typeof(ObjectExtensions).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "AsReadOnly").First(m => m.GetParameters()[0].ParameterType.Name == (isInterface ? "IList`1" : "List`1")); var result = il.DeclareLocal(property.PropertyType); // load the first argument (the instance itself) and the field. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); il.Emit(OpCodes.Call, asReadOnlyMethod.MakeGenericMethod(elementType)); il.Emit(OpCodes.Stloc_0, result); il.Emit(OpCodes.Ldloc_0); } else if (Reflector.IsDataEntity(property.PropertyType)) { var asReadOnlyMethod = typeof(ObjectExtensions).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "AsReadOnly").First(m => m.GetParameters()[0].ParameterType.IsGenericParameter); var result = il.DeclareLocal(property.PropertyType); // load the first argument (the instance itself) and the field. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); il.Emit(OpCodes.Call, asReadOnlyMethod.MakeGenericMethod(property.PropertyType)); il.Emit(OpCodes.Stloc_0, result); il.Emit(OpCodes.Ldloc_0); } else if (property.DeclaringType.InheritsFrom(typeof(ITrackableDataEntity)) && property.PropertyType == typeof(ObjectState) && property.Name == "ObjectState") { il.Emit(OpCodes.Ldc_I4, (int)ObjectState.ReadOnly); } else { // load the first argument (the instance itself) and the field. il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); il.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null); } il.Emit(OpCodes.Ret); // set the method. propertyBuilder.SetGetMethod(getMethod); typeBuilder.DefineMethodOverride(getMethod, property.ReflectedType.GetMethod(getMethodName)); } // create the setter if we can read. if (property.CanWrite) { // create the set method of the property. var setMethodName = "set_" + property.Name; var setMethod = typeBuilder.DefineMethod(setMethodName, getSetAttr, null, new Type[] { property.PropertyType }); // get the IL generator to generate some IL. ILGenerator il = setMethod.GetILGenerator(); // load the first argument (instance itself) and the field. il.Emit(OpCodes.Newobj, typeof(NotSupportedException).GetConstructor(Type.EmptyTypes)); il.Emit(OpCodes.Throw); propertyBuilder.SetSetMethod(setMethod); typeBuilder.DefineMethodOverride(setMethod, property.ReflectedType.GetMethod(setMethodName)); } }