protected virtual void ValidatePropertyModel(CompositeValidationResult result, CompositeModel model, PropertyModel property) { if (property.IsPartOfCompositeState()) { UseDefaultsAttribute udAttr; if (property.IsUseDefaults(out udAttr)) { if (udAttr.ActualType != null && !property.NativeInfo.PropertyType.IsAssignableFrom(udAttr.ActualType)) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("The type " + property.NativeInfo.PropertyType + " of " + property.NativeInfo + " is not assignable from type given to " + typeof(UseDefaultsAttribute) + " constructor ( " + udAttr.ActualType + ").", model, property)); } else if (property.NativeInfo.PropertyType.IsGenericParameter) { result.StructureValidationErrors.Add(ValidationErrorFactory.NewStructureError("The type " + property.NativeInfo.PropertyType + " of " + property.NativeInfo + " is marked with " + typeof(UseDefaultsAttribute) + " but it is generic type parameter.", model, property)); } } } }
protected virtual void EmitLoadDefaultValueForPropertyModel( PropertyModel propModel, CompositeTypeGenerationInfo propertyDeclaringTypeGenInfo, MethodGenerationInfo methodGenInfo ) { var il = methodGenInfo.IL; var pInfo = propModel.NativeInfo.NewWrapper(this.ctx); var propType = propertyDeclaringTypeGenInfo.AutoGeneratedPropertyInfos[propModel.NativeInfo].PropertyType; var declType = pInfo.DeclaringType; UseDefaultsAttribute udAttr; if (propModel.DefaultValueCreator != null) { // Get creator from property model il.EmitLoadLocal(methodGenInfo.GetLocalOrThrow(LB_C_INSTANCE)) .EmitCall(MODEL_INFO_GETTER) .EmitCall(MODEL_GETTER) .EmitCall(C_METHODS_GETTER) .EmitLoadInt32(propModel.GetterMethod.MethodIndex) .EmitCall(COMPOSITE_METHODS_INDEXER) .EmitCall(PROPERTY_MODEL_GETTER) .EmitCall(DEFAULT_CREATOR_GETTER); if (WillDefaultValueCreatorParameterBeNull(pInfo)) { il.EmitLoadNull(); } else { il.EmitReflectionObjectOf(propertyDeclaringTypeGenInfo.Parents[declType]) .EmitLoadString(pInfo.Name) .EmitCall(GET_PROPERTY_INFO_METHOD); } il .EmitLoadLocal(methodGenInfo.GetLocalOrThrow(LB_C_INSTANCE)) .EmitCall(STRUCTURE_OWNER_GETTER_METHOD) .EmitCall(APPLICATION_GETTER_METHOD) .EmitCall(DEFAULT_CREATOR_INVOKER) .EmitCastToType(DEFAULT_CREATOR_INVOKER.GetReturnType(), TypeGenerationUtils.CreateTypeForEmitting(propType, propertyDeclaringTypeGenInfo.GenericArguments, null)); } else if (propModel.IsUseDefaults(out udAttr)) { var propTypeGDef = propModel.NativeInfo.PropertyType.GetGenericDefinitionIfGenericType(); System.Reflection.MethodBase defaultValueCtor; CILTypeBase nullableParameter; if (propType.IsNullable(out nullableParameter)) { il.EmitLoadDefault(nullableParameter, aType => methodGenInfo.GetOrCreateLocalBasedOnType(aType)) .EmitNewObject(GetMethodBase(propType, NULLABLE_CTOR, propertyDeclaringTypeGenInfo)); } else if (STRING_TYPE.Equals(propType)) { il.EmitLoadString(DEFAULT_STRING); } else if (DEFAULT_CREATORS.TryGetValue(propTypeGDef, out defaultValueCtor)) { if (udAttr.ActualType != null) { var otherCtor = udAttr.ActualType .GetConstructors(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public) .FirstOrDefault(ctor => ctor.GetParameters().Length == 0); if (otherCtor != null) { defaultValueCtor = otherCtor; } } if (defaultValueCtor is System.Reflection.ConstructorInfo) { il.EmitNewObject(GetMethodBase(propType, ((System.Reflection.ConstructorInfo)defaultValueCtor).NewWrapper(this.ctx), propertyDeclaringTypeGenInfo)); } else if (defaultValueCtor is System.Reflection.MethodInfo) { if (((System.Reflection.MethodInfo)defaultValueCtor).IsStatic) { il.EmitCall(GetMethodBase(propType, ((System.Reflection.MethodInfo)defaultValueCtor).NewWrapper(this.ctx), propertyDeclaringTypeGenInfo)); } else { throw new InternalException("The default creators contained non-static method for type " + propTypeGDef + "."); } } else { throw new InternalException("Unknown default value creator " + defaultValueCtor + "."); } } else if (propType.IsArray() || IENUMERABLE_GDEF_TYPE.Equals(TypeGenerationUtils.GenericDefinitionIfGArgsHaveGenericParams(propType as CILType))) // || IENUMERABLE_NO_GDEF_TYPE.Equals( propType ) ) { var elementType = propType.IsArray() ? ((CILType)propType).ElementType : /*( IENUMERABLE_NO_GDEF_TYPE.Equals( propType ) ? OBJECT_TYPE :*/ ((CILType)propType).GenericArguments[0] /* )*/; il.EmitLoadInt32(0) .EmitNewArray(TypeGenerationUtils.CreateTypeForEmitting(elementType, propertyDeclaringTypeGenInfo.GenericArguments, null)); } else if (!propType.IsValueType()) { var ctorType = udAttr.ActualType == null ? (CILType)propType : udAttr.ActualType.NewWrapperAsType(this.ctx); var eDefaultValueCtor = ctorType.Constructors.FirstOrDefault(ctor => !ctor.Parameters.Any()); if (eDefaultValueCtor != null) { il.EmitNewObject(GetMethodBase(ctorType, eDefaultValueCtor, propertyDeclaringTypeGenInfo)); } else { throw new NotSupportedException("Tried to use " + USE_DEFAULTS_ATTRIBUTE_TYPE + " on a type (" + ctorType + ") with no parameterless constructor."); } } else { throw new InternalException("Could not emit default value for " + pInfo.GetPropertyType() + "."); } } }
protected virtual Boolean CanEmitDefaultValueForPropertyModel(PropertyModel propModel) { return(propModel.IsPartOfCompositeState() && (propModel.DefaultValueCreator != null || propModel.IsUseDefaults())); }