protected void ImplementSetValue(IPropertyInfo[] propertyPath) { IMethodVisitor mv = VisitMethod(template_m_setValue); IPropertyInfo lastProperty = propertyPath[propertyPath.Length - 1]; if (lastProperty is MethodPropertyInfo && ((MethodPropertyInfo)lastProperty).Setter == null) { throw new Exception("Property not writable: " + lastProperty.EntityType.FullName + "." + lastProperty.Name); } mv.LoadArg(0); Type typeOfArgumentOnStack = typeof(Object); for (int a = 0, size = propertyPath.Length - 1; a < size; a++) { typeOfArgumentOnStack = InvokeGetProperty(mv, propertyPath[a], typeOfArgumentOnStack); } if (!lastProperty.DeclaringType.Equals(typeOfArgumentOnStack)) { mv.CheckCast(lastProperty.DeclaringType); } mv.LoadArg(1); Type lastPropertyType = lastProperty.PropertyType; if (lastProperty.PropertyType.IsPrimitive) { Type pType = lastProperty.PropertyType; Label l_valueIsNonNull = mv.NewLabel(); Label l_valueIsValid = mv.NewLabel(); mv.IfNonNull(l_valueIsNonNull); mv.PushNullOrZero(pType); mv.GoTo(l_valueIsValid); mv.Mark(l_valueIsNonNull); mv.LoadArg(1); mv.Unbox(pType); mv.Mark(l_valueIsValid); } else { mv.CheckCast(lastPropertyType); } InvokeSetProperty(mv, lastProperty); mv.ReturnValue(); mv.EndMethod(); }
public virtual void LoadArg(int argIndex) { if (mv != null) { mv.LoadArg(argIndex); } }
protected void ImplementNotifyPropertyChanged(PropertyInstance p_propertyChangeTemplate, MethodInstance m_getPropertyChangeSupport) { // implement IPropertyChanged foreach (MethodInfo rMethod in typeof(INotifyPropertyChanged).GetMethods()) { MethodInstance existingMethod = MethodInstance.FindByTemplate(rMethod, true); if (existingMethod != null) { continue; } MethodInstance method = new MethodInstance(rMethod); IMethodVisitor mg = VisitMethod(method); mg.CallThisGetter(p_propertyChangeTemplate); // this.propertyChangeSupport mg.CallThisGetter(m_getPropertyChangeSupport); // listener mg.LoadArg(0); if ("add_PropertyChanged".Equals(method.Name)) { // addPropertyChangeListener(propertyChangeSupport, listener) mg.InvokeVirtual(m_addPropertyChangeListener); } else { // removePropertyChangeListener(propertyChangeSupport, listener) mg.InvokeVirtual(m_removePropertyChangeListener); } mg.ReturnValue(); mg.EndMethod(); } }
protected void ImplementSetRelation(RelationMember[] relationMembers, FieldInstance[] f_relations) { MethodInstance template_m_setRelation = new MethodInstance(null, typeof(RootCacheValue), typeof(void), "SetRelation", typeof(int), typeof(IObjRef[])); IMethodVisitor mv = VisitMethod(template_m_setRelation); Label l_finish = mv.NewLabel(); for (int relationIndex = 0, size = f_relations.Length; relationIndex < size; relationIndex++) { FieldInstance f_relation = f_relations[relationIndex]; Label l_notEqual = mv.NewLabel(); mv.LoadArg(0); mv.Push(relationIndex); mv.IfCmp(typeof(int), CompareOperator.NE, l_notEqual); mv.PutThisField(f_relation, delegate(IMethodVisitor mg) { mg.LoadArg(1); }); mv.GoTo(l_finish); mv.Mark(l_notEqual); } mv.ThrowException(typeof(ArgumentException), "Given relationIndex not known"); mv.Mark(l_finish); mv.ReturnValue(); mv.EndMethod(); }
protected void ImplementGetRelation(RelationMember[] relationMembers, FieldInstance[] f_relations) { MethodInstance template_m_getRelation = new MethodInstance(null, typeof(RootCacheValue), typeof(IObjRef[]), "GetRelation", typeof(int)); IMethodVisitor mv = VisitMethod(template_m_getRelation); if (f_relations.Length > 0) { Label l_default = mv.NewLabel(); Label[] l_relations = new Label[f_relations.Length]; for (int relationIndex = 0, size = l_relations.Length; relationIndex < size; relationIndex++) { l_relations[relationIndex] = mv.NewLabel(); } mv.LoadArg(0); mv.Switch(0, l_relations.Length - 1, l_default, l_relations); for (int relationIndex = 0, size = f_relations.Length; relationIndex < size; relationIndex++) { FieldInstance f_relation = f_relations[relationIndex]; mv.Mark(l_relations[relationIndex]); mv.GetThisField(f_relation); mv.ReturnValue(); } mv.Mark(l_default); } mv.ThrowException(typeof(ArgumentException), "Given relationIndex not known"); mv.PushNull(); mv.ReturnValue(); mv.EndMethod(); }
public override void VisitEnd() { Type entityType = metaData.EntityType; { IMethodVisitor mv = VisitMethod(template_m_getEntityType); mv.Push(entityType); mv.ReturnValue(); mv.EndMethod(); } { IMethodVisitor mv = VisitMethod(template_m_getIdIndex); mv.Push(idIndex); mv.ReturnValue(); mv.EndMethod(); } FieldInstance f_id = ImplementNativeField(this, metaData.GetIdMemberByIdIndex(idIndex), template_m_getId, template_m_setId); if (f_id.Type.Type.IsPrimitive) { // id is a primitive type. So we use an improved version of the 3-tuple equals without boxing the id IMethodVisitor mv = VisitMethod(template_m_isEqualTo); Label l_notEqual = mv.NewLabel(); mv.Push(entityType); mv.LoadArg(0); mv.IfCmp(typeof(Type), CompareOperator.NE, l_notEqual); mv.Push(idIndex); mv.LoadArg(1); mv.IfCmp(typeof(bool), CompareOperator.NE, l_notEqual); mv.GetThisField(f_id); mv.LoadArg(2); mv.Unbox(f_id.Type.Type); mv.IfCmp(f_id.Type.Type, CompareOperator.NE, l_notEqual); mv.Push(true); mv.ReturnValue(); mv.Mark(l_notEqual); mv.Push(false); mv.ReturnValue(); mv.EndMethod(); } base.VisitEnd(); }
protected void ImplementGetPrimitive(Member[] primitiveMember, FieldInstance[] f_primitives, FieldInstance[] f_nullFlags) { MethodInstance template_m_getPrimitive = new MethodInstance(null, typeof(RootCacheValue), typeof(Object), "GetPrimitive", typeof(int)); IMethodVisitor mv = VisitMethod(template_m_getPrimitive); if (f_primitives.Length > 0) { Label l_default = mv.NewLabel(); Label[] l_primitives = new Label[f_primitives.Length]; for (int primitiveIndex = 0, size = f_primitives.Length; primitiveIndex < size; primitiveIndex++) { l_primitives[primitiveIndex] = mv.NewLabel(); } mv.LoadArg(0); mv.Switch(0, l_primitives.Length - 1, l_default, l_primitives); for (int primitiveIndex = 0, size = f_primitives.Length; primitiveIndex < size; primitiveIndex++) { FieldInstance f_primitive = f_primitives[primitiveIndex]; FieldInstance f_nullFlag = f_nullFlags[primitiveIndex]; mv.Mark(l_primitives[primitiveIndex]); Label?l_fieldIsNull = null; if (f_nullFlag != null) { l_fieldIsNull = mv.NewLabel(); // only do something if the field is non-null mv.GetThisField(f_nullFlag); mv.IfZCmp(CompareOperator.NE, l_fieldIsNull.Value); } mv.GetThisField(f_primitive); mv.ValueOf(f_primitive.Type.Type); mv.ReturnValue(); if (f_nullFlag != null) { mv.Mark(l_fieldIsNull.Value); mv.PushNull(); } mv.ReturnValue(); } mv.Mark(l_default); } mv.ThrowException(typeof(ArgumentException), "Given relationIndex not known"); mv.PushNull(); mv.ReturnValue(); mv.EndMethod(); }
protected void ImplementConstructor(MethodInstance template_m_setPrimitivePropertyPrivilege, MethodInstance template_m_setRelationPropertyPrivilege) { IBytecodeBehaviorState state = State; ConstructorInfo constructor = state.CurrentType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(bool), typeof(IPropertyPrivilege[]), typeof(IPropertyPrivilege[]) }, null); ConstructorInstance c_method = new ConstructorInstance(constructor); IMethodVisitor mg = VisitMethod(c_method); mg.LoadThis(); mg.LoadArgs(); mg.InvokeConstructor(c_method); Type propertyPrivilegeType = typeof(IPropertyPrivilege); for (int primitiveIndex = 0, size = metaData.PrimitiveMembers.Length; primitiveIndex < size; primitiveIndex++) { mg.LoadThis(); mg.Push(primitiveIndex); mg.LoadArg(5); mg.Push(primitiveIndex); mg.ArrayLoad(propertyPrivilegeType); mg.InvokeVirtual(template_m_setPrimitivePropertyPrivilege); } for (int relationIndex = 0, size = metaData.RelationMembers.Length; relationIndex < size; relationIndex++) { mg.LoadThis(); mg.Push(relationIndex); mg.LoadArg(6); mg.Push(relationIndex); mg.ArrayLoad(propertyPrivilegeType); mg.InvokeVirtual(template_m_setRelationPropertyPrivilege); } mg.ReturnValue(); mg.EndMethod(); }
protected void ImplementGetAttribute(IPropertyInfo[] property) { HashMap <Type, Attribute> typeToAttributeMap = new HashMap <Type, Attribute>(); Attribute[] annotations = property[property.Length - 1].GetAnnotations(); foreach (Attribute annotation in annotations) { typeToAttributeMap.Put(annotation.GetType(), annotation); } FieldInstance f_typeToAttributeMap = ImplementStaticAssignedField("sf__typeToAttributeMap", typeToAttributeMap); IMethodVisitor mv = VisitMethod(template_m_getAttribute); mv.GetThisField(f_typeToAttributeMap); mv.LoadArg(0); mv.InvokeVirtual(new MethodInstance(null, typeof(HashMap <Type, Attribute>), typeof(Attribute), "Get", typeof(Type))); // mv.CheckCast(typeof(Attribute)); mv.ReturnValue(); mv.EndMethod(); }
protected void ImplementEmbeddedConstructor(FieldInstance f_parentObject, ConstructorInstance superConstructor) { if (superConstructor.Parameters.Length > 0 && superConstructor.Parameters[0].Equals(f_parentObject.Type)) { // super constructor already enhanced return; } bool baseIsEnhanced = false;//EntityEnhancer.IsEnhancedType(vs.CurrentType); NewType[] parameters = superConstructor.Parameters; NewType[] types; if (baseIsEnhanced) { // Only Pass-through constructors necessary. So signature remains the same types = null;//TypeUtil.GetClassesToTypes(..GetTypes(parameters); } else { types = new NewType[parameters.Length + 1]; for (int a = parameters.Length + 1; a-- > 1;) { types[a] = parameters[a - 1]; } types[0] = f_parentObject.Type; } IMethodVisitor mv = VisitMethod(new ConstructorInstance(MethodAttributes.Public, types)); mv.LoadThis(); for (int a = 1, size = types.Length; a < size; a++) { mv.LoadArg(a); // Load constructor argument one by one, starting with the 2nd constructor argument } mv.InvokeConstructor(superConstructor); mv.PutThisField(f_parentObject, delegate(IMethodVisitor mv2) { mv2.LoadArg(0); }); mv.ReturnValue(); mv.EndMethod(); }
public MethodInstance ImplementSwitchByIndex(MethodInstance method, String exceptionMessageOnIllegalIndex, int indexSize, ScriptWithIndex script) { IMethodVisitor mv = VisitMethod(method); if (indexSize == 0) { mv.ThrowException(typeof(ArgumentException), exceptionMessageOnIllegalIndex); mv.PushNull(); mv.ReturnValue(); mv.EndMethod(); return(mv.Method); } Label l_default = mv.NewLabel(); Label[] l_fields = new Label[indexSize]; for (int index = 0, size = indexSize; index < size; index++) { l_fields[index] = mv.NewLabel(); } mv.LoadArg(0); mv.VisitTableSwitchInsn(0, l_fields.Length - 1, l_default, l_fields); for (int index = 0, size = l_fields.Length; index < size; index++) { mv.Mark(l_fields[index]); script(mv, index); } mv.Mark(l_default); mv.ThrowException(typeof(ArgumentException), "Given relationIndex not known"); mv.PushNull(); mv.ReturnValue(); mv.EndMethod(); return(mv.Method); }
protected PropertyInstance ImplementNotifyPropertyChangedSource(PropertyInstance p_propertyChangeTemplate, FieldInstance f_propertyChangeSupport) { MethodInstance m_onPropertyChanged_Values = MethodInstance.FindByTemplate(template_m_onPropertyChanged_Values, true); if (m_onPropertyChanged_Values == null) { IMethodVisitor mv = VisitMethod(template_m_onPropertyChanged_Values); mv.CallThisGetter(p_propertyChangeTemplate); mv.LoadThis(); mv.GetThisField(f_propertyChangeSupport); // getMethodHandle(sender, propertyName) mv.CallThisGetter(p_propertyChangeTemplate); mv.LoadThis(); mv.LoadArg(0); mv.InvokeVirtual(m_getMethodHandle); mv.LoadArg(1); mv.LoadArg(2); // firePropertyChange(sender, propertyChangeSupport, property, oldValue, newValue) mv.InvokeVirtual(m_firePropertyChange); mv.PopIfReturnValue(m_firePropertyChange); mv.ReturnVoidOrThis(); mv.EndMethod(); m_onPropertyChanged_Values = mv.Method; } MethodInstance m_onPropertyChanged = MethodInstance.FindByTemplate(template_m_onPropertyChanged, true); if (m_onPropertyChanged == null) { IMethodVisitor mv = VisitMethod(template_m_onPropertyChanged); mv.LoadThis(); mv.LoadArg(0); mv.PushNull(); mv.PushNull(); mv.InvokeVirtual(m_onPropertyChanged_Values); mv.PopIfReturnValue(m_onPropertyChanged_Values); mv.ReturnVoidOrThis(); mv.EndMethod(); m_onPropertyChanged = mv.Method; } PropertyInstance p_pceHandlers = PropertyInstance.FindByTemplate(p_propertyChangeSupport, true); if (p_pceHandlers == null) { HideFromDebug(ImplementGetter(p_propertyChangeSupport.Getter, f_propertyChangeSupport)); p_pceHandlers = PropertyInstance.FindByTemplate(p_propertyChangeSupport, false); } if (EmbeddedEnhancementHint.HasMemberPath(State.Context)) { PropertyInstance p_parentEntity = EmbeddedTypeVisitor.GetParentObjectProperty(this); if (MethodInstance.FindByTemplate(p_parentChildEventHandler.Getter, true) == null) { IMethodVisitor mv = VisitMethod(p_parentChildEventHandler.Getter); mv.CallThisGetter(p_parentEntity); mv.InvokeInterface(p_parentChildEventHandler.Getter); mv.ReturnValue(); mv.EndMethod(); HideFromDebug(mv.Method); } if (MethodInstance.FindByTemplate(p_collectionEventHandler.Getter, true) == null) { IMethodVisitor mv = VisitMethod(p_collectionEventHandler.Getter); mv.CallThisGetter(p_parentEntity); mv.InvokeInterface(p_collectionEventHandler.Getter); mv.ReturnValue(); mv.EndMethod(); HideFromDebug(mv.Method); } } else { if (MethodInstance.FindByTemplate(p_parentChildEventHandler.Getter, true) == null) { HideFromDebug(ImplementLazyInitProperty(p_parentChildEventHandler, delegate(IMethodVisitor mv) { MethodInstance method = new MethodInstance(null, typeof(NotifyPropertyChangedClassVisitor), typeof(PropertyChangedEventHandler), "CreateParentChildEventHandler", typeof(Object)); mv.LoadThis(); mv.InvokeStatic(method); })); } if (MethodInstance.FindByTemplate(p_collectionEventHandler.Getter, true) == null) { HideFromDebug(ImplementLazyInitProperty(p_collectionEventHandler, delegate(IMethodVisitor mv) { MethodInstance method = new MethodInstance(null, typeof(NotifyPropertyChangedClassVisitor), typeof(NotifyCollectionChangedEventHandler), "CreateCollectionEventHandler", typeof(Object)); mv.LoadThis(); mv.InvokeStatic(method); })); } } //MethodAttributes ma = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig; //{ // ConstructorInfo pceaCI = typeof(PropertyChangedEventArgs).GetConstructor(new Type[] { typeof(String) }); // MethodBuilder mb = VisitorUtil.DefineMethod(vs, onPropertyChangedMI_string, ma); // ILGenerator gen = mb.GetILGenerator(); // gen.Emit(OpCodes.Ldarg_0); // gen.Emit(OpCodes.Ldarg_1); // gen.Emit(OpCodes.Newobj, pceaCI); // gen.Emit(OpCodes.Call, onPropertyChangedMI_pceArg); // gen.Emit(OpCodes.Ret); //} //{ // MethodBuilder mb = VisitorUtil.DefineMethod(vs, onPropertyChangedMI_pceArg, ma); // ILGenerator gen = mb.GetILGenerator(); // gen.Emit(OpCodes.Ldarg_0); // gen.Emit(OpCodes.Call, pctPI.GetGetMethod()); // gen.Emit(OpCodes.Ldarg_0); // gen.Emit(OpCodes.Ldarg_1); // gen.Emit(OpCodes.Call, FirePropertyChangedMI); // gen.Emit(OpCodes.Ret); //} // List<PropertyChangedEventHandler> PropertyChangedEventHandlers { get; } //void OnPropertyChanged(String propertyName); //void OnPropertyChanged(PropertyChangedEventArgs args); return(p_pceHandlers); }
protected void ImplementPropertyChangeOnProperty(PropertyInstance propertyInfo, PropertyInstance p_propertyChangeTemplate, MethodInstance m_firePropertyChange, FieldInstance f_propertyChangeSupport) { // add property change detection and notification if (propertyInfo.Getter == null || propertyInfo.Setter == null) { return; } if (InitializeEmbeddedMemberVisitor.IsEmbeddedMember(metaData, propertyInfo.Name)) { return; } PropertyInstance p_getterMethodHandle = ImplementAssignedReadonlyProperty(propertyInfo.Name + "$MethodHandle", new MethodHandleValueResolver(PropertyInfoProvider, propertyInfo.Name)); Type propertyType = propertyInfo.PropertyType.Type; MethodInstance m_hasPropertyChanged = GetApplicableHasPropertyChangedOverload(propertyType); // check value type of last parameter bool isBoxingNeededForHasPropertyChanged = IsBoxingNeededForHasPropertyChangedOverload(m_hasPropertyChanged, propertyType); IMethodVisitor mg = VisitMethod(propertyInfo.Setter); Label l_finish = mg.NewLabel(); Label l_noOldValue = mg.NewLabel(); Label l_noChangeCheck = mg.NewLabel(); LocalVariableInfo loc_oldValue; if (isBoxingNeededForHasPropertyChanged) { loc_oldValue = mg.NewLocal(typeof(Object)); } else { loc_oldValue = mg.NewLocal(propertyType); } LocalVariableInfo loc_valueChanged = mg.NewLocal <bool>(); MethodInstance m_getSuper = EnhancerUtil.GetSuperGetter(propertyInfo); bool relationProperty = m_getSuper.Name.EndsWith(ValueHolderIEC.GetNoInitSuffix()); // initialize flag with false mg.Push(false); mg.StoreLocal(loc_valueChanged); // initialize oldValue with null mg.PushNullOrZero(loc_oldValue.LocalType); mg.StoreLocal(loc_oldValue); if (relationProperty) { // check if a setter call to an UNINITIALIZED relation occured with value null // if it the case there would be no PCE because oldValue & newValue are both null // but we need a PCE in this special case Label l_noSpecialHandling = mg.NewLabel(); FieldInstance f_state = State.GetAlreadyImplementedField(ValueHolderIEC.GetInitializedFieldName(propertyInfo.Name)); mg.GetThisField(f_state); mg.PushEnum(ValueHolderState.INIT); mg.IfCmp(typeof(ValueHolderState), CompareOperator.EQ, l_noSpecialHandling); mg.Push(true); mg.StoreLocal(loc_valueChanged); mg.Mark(l_noSpecialHandling); } // check if value should be checked to decide for a PCE mg.LoadLocal(loc_valueChanged); mg.IfZCmp(CompareOperator.NE, l_noOldValue); // get old field value calling super property getter mg.LoadThis(); mg.InvokeOnExactOwner(m_getSuper); if (isBoxingNeededForHasPropertyChanged) { mg.Box(propertyType); } mg.StoreLocal(loc_oldValue); mg.Mark(l_noOldValue); // set new field value calling super property setter mg.LoadThis(); mg.LoadArg(0); mg.InvokeOnExactOwner(EnhancerUtil.GetSuperSetter(propertyInfo)); mg.PopIfReturnValue(EnhancerUtil.GetSuperSetter(propertyInfo)); // check if value should be checked to decide for a PCE mg.LoadLocal(loc_valueChanged); mg.IfZCmp(CompareOperator.NE, l_noChangeCheck); LocalVariableInfo loc_newValue = null; if (isBoxingNeededForHasPropertyChanged) { loc_newValue = mg.NewLocal(typeof(Object)); // loc_1 Object newValue // Object loc_1 = (Object)value; mg.LoadArg(0); mg.Box(propertyType); mg.StoreLocal(loc_newValue); } mg.CallThisGetter(p_propertyChangeTemplate); // call HasPropertyChanged (static) mg.LoadThis(); // "this" as Object obj mg.Push(propertyInfo.Name); // String propertyName mg.LoadLocal(loc_oldValue); if (loc_newValue != null) { mg.LoadLocal(loc_newValue); } else { mg.LoadArg(0); } mg.InvokeVirtual(m_hasPropertyChanged); //// if (!result) //// { return; } mg.IfZCmp(CompareOperator.EQ, l_finish); mg.Mark(l_noChangeCheck); // call firePropertyChange on this mg.LoadThis(); // propertyChangeSupport mg.GetThisField(f_propertyChangeSupport); // property mg.CallThisGetter(p_getterMethodHandle); // oldValue mg.LoadLocal(loc_oldValue); if (!isBoxingNeededForHasPropertyChanged && propertyType.IsValueType) { // old value has not already been boxed but it is now necessary mg.ValueOf(propertyType); } // newValue if (loc_newValue != null) { mg.LoadLocal(loc_newValue); } else { mg.LoadArg(0); if (propertyType.IsValueType) { mg.ValueOf(propertyType); } } // firePropertyChange(propertyChangeSupport, property, oldValue, newValue) mg.InvokeVirtual(m_firePropertyChange); // return mg.Mark(l_finish); mg.ReturnVoidOrThis(); mg.EndMethod(); }
protected void ImplementGetValueIntern(MethodInstance template_m_getValue, IPropertyInfo[] propertyPath) { IMethodVisitor mv = VisitMethod(template_m_getValue); Type declaringType = propertyPath[0].EntityType; Label l_finish = mv.NewLabel(); mv.LoadArg(0); Type typeOfArgumentOnStack = typeof(Object); for (int a = 0, size = propertyPath.Length - 1; a < size; a++) { typeOfArgumentOnStack = InvokeGetProperty(mv, propertyPath[a], typeOfArgumentOnStack); mv.Dup(); mv.IfNull(l_finish); } IPropertyInfo lastProperty = propertyPath[propertyPath.Length - 1]; typeOfArgumentOnStack = InvokeGetProperty(mv, lastProperty, typeOfArgumentOnStack); if (lastProperty.PropertyType.IsPrimitive) { Type pType = lastProperty.PropertyType; LocalVariableInfo loc_value = mv.NewLocal(pType); mv.StoreLocal(loc_value); mv.LoadLocal(loc_value); Label l_valueIsNonZero = mv.NewLabel(); mv.IfZCmp(pType, CompareOperator.NE, l_valueIsNonZero); if (mv.Method.Parameters.Length == 2) { Label l_nullAllowed = mv.NewLabel(); // check null-equi flag mv.LoadArg(1); mv.IfZCmp(CompareOperator.EQ, l_nullAllowed); mv.PushNullOrZero(pType); if (!mv.Method.ReturnType.Type.IsValueType) { mv.ValueOf(pType); } mv.ReturnValue(); mv.Mark(l_nullAllowed); } mv.PushNullOrZero(mv.Method.ReturnType); mv.ReturnValue(); mv.Mark(l_valueIsNonZero); mv.LoadLocal(loc_value); mv.ValueOf(pType); } else if (lastProperty.PropertyType.IsValueType) { Type pType = lastProperty.PropertyType; MethodInfo m_hasValue = pType.GetMethod("get_HasValue"); if (m_hasValue != null) { LocalVariableInfo loc_value = mv.NewLocal(pType); mv.StoreLocal(loc_value); mv.LoadLocal(loc_value); MethodInfo m_getValue = pType.GetMethod("get_Value"); LocalVariableInfo loc_realValue = mv.NewLocal(m_getValue.ReturnType); Label l_hasNoValue = mv.NewLabel(); mv.InvokeOnExactOwner(m_hasValue); mv.IfZCmp(CompareOperator.EQ, l_hasNoValue); mv.LoadLocal(loc_value); mv.InvokeOnExactOwner(m_getValue); mv.StoreLocal(loc_realValue); mv.LoadLocal(loc_realValue); mv.IfZCmp(CompareOperator.EQ, l_hasNoValue); mv.LoadLocal(loc_realValue); if (!mv.Method.ReturnType.Type.IsValueType) { mv.ValueOf(m_getValue.ReturnType); } mv.ReturnValue(); mv.Mark(l_hasNoValue); if (mv.Method.Parameters.Length == 2) { Label l_nullEquivalentValueAllowed = mv.NewLabel(); // check null-equi flag mv.LoadArg(1); mv.IfZCmp(CompareOperator.NE, l_nullEquivalentValueAllowed); mv.PushNull(); mv.ReturnValue(); mv.Mark(l_nullEquivalentValueAllowed); } mv.PushNullOrZero(m_getValue.ReturnType); if (!mv.Method.ReturnType.Type.IsValueType) { mv.ValueOf(m_getValue.ReturnType); } } else { mv.Box(pType); } } mv.Mark(l_finish); mv.ReturnValue(); mv.EndMethod(); }