private void HandleField( PropertyInfo f, IFieldAttribute a, Type t ) { if( a is PersistentFieldAttribute ) { PersistentFieldAttribute attribute = a as PersistentFieldAttribute; string tablename = attribute.Name; this.Context.AddChild( new PersistentFieldMap() { Field = f, ChildReturnType = attribute.ChildReturnType ?? f.PropertyType, Cascade = attribute.Cascade, Lazy = ( attribute.Loading == Loading.Active ? false : true ), Linked = attribute.Linked } .WithBehavior( attribute.Behavior ) .WithLinkedTable( attribute.LinkName ) .WithParentKeyColumn( attribute.LinkLeft ) .WithChildKeyColumn( attribute.LinkRight ) .WithTable( tablename ) ); } else if( a is FieldAttribute ) { FieldAttribute attribute = a as FieldAttribute; FieldMap fm = new FieldMap() { Field = f, Behavior = attribute.Behavior, Cascade = attribute.Cascade, DefaultValue = attribute.DefaultValue, MappingType = attribute.MappingType, Name = attribute.Name, Parent = attribute.Parent, Static = attribute.IsStatic, AllowNull = attribute.AllowNull }; switch( attribute.MappingType ) { case FieldMappingType.ForeignKey: { this.HandleForeignKey( fm ); break; } case FieldMappingType.ManagedPrimaryKey: case FieldMappingType.PrimaryKey: { this.Context.SetPrimaryKey( fm, ( ( PrimaryKeyAttribute )attribute ).UnsavedValue ); break; } case FieldMappingType.PrimaryForeignKey: { this.HandlePrimaryForeignKey( fm ); break; } case FieldMappingType.Reference: { this.Context.AddReferencedField( fm ); break; } case FieldMappingType.Value: { this.Context.AddField( fm ); break; } } EncryptedAttribute encrypted = Utility.GetCustomFieldAttribute<EncryptedAttribute>( f ); if( encrypted.NotNull() ) fm.WithEncryption( encrypted.PrivateKey, encrypted.Algorithm ); } }
protected IEnumerable <Expression> CreateFieldExpression(PropertyInfo propertyInfo, IFieldAttribute fieldAttribute, ParameterExpression returnExpression, Expression valueExpression) { List <Expression> ret = new List <Expression>(); Regex nullRegex = (fieldAttribute.NullPattern != null) ? new Regex(fieldAttribute.NullPattern) : new Regex(@"^\s*$"); Expression isNullMatch = Expression.Call(Expression.Constant(nullRegex), typeof(Regex).GetMethod("IsMatch", new[] { typeof(String) }), valueExpression); Expression assignedExpression; if (fieldAttribute.IsRequired) { ret.Add(Expression.IfThen(isNullMatch, Expression.Throw(Expression.Constant(new Exception($"Field '{propertyInfo.Name}' cannot be null"))))); } assignedExpression = valueExpression; List <Expression> temp = new List <Expression>(); if (fieldAttribute.ValidationPattern != null) { Regex validationRegex = new Regex(fieldAttribute.ValidationPattern); Expression isValidationMatch = Expression.Call(Expression.Constant(validationRegex), typeof(Regex).GetMethod("IsMatch", new[] { typeof(String) }), valueExpression); Expression s = Expression.Call(typeof(String).GetMethod("Format", new[] { typeof(String), typeof(String) }), Expression.Constant($"Field '{propertyInfo.Name}' does not match the required format.\nValue: {{0}}"), valueExpression); Expression exception = Expression.New(typeof(Exception).GetConstructor(new[] { typeof(String) }), s); temp.Add(Expression.IfThen(Expression.Not(isValidationMatch), Expression.Throw(exception))); } IEnumerable <Attribute> conversionAttributes = propertyInfo.GetCustomAttributes().Where(attribute => attribute.GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConversionAttribute <>))); if (conversionAttributes.Count() > 1) { throw new Exception(String.Format("Property '{0}' cannot contain multiple conversion attributes.")); } else if (conversionAttributes.Count() == 1) { assignedExpression = Expression.Convert(Expression.Call(Expression.Constant(conversionAttributes.First()), conversionAttributes.First().GetType().GetMethod("Convert", new[] { typeof(String) }), assignedExpression), propertyInfo.PropertyType); } else if (propertyInfo.PropertyType.IsEnum || (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>) && propertyInfo.PropertyType.GetGenericArguments()[0].IsEnum)) { Type enumType = (propertyInfo.PropertyType.IsEnum) ? propertyInfo.PropertyType : propertyInfo.PropertyType.GetGenericArguments()[0]; assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }), Expression.Constant(" "), Expression.Constant("")); assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }), Expression.Constant("_"), Expression.Constant("")); assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }), Expression.Constant("&"), Expression.Constant("")); assignedExpression = Expression.Convert(Expression.Call(typeof(Enum).GetMethod("Parse", new[] { typeof(Type), typeof(String), typeof(Boolean) }), Expression.Constant(enumType), assignedExpression, Expression.Constant(true)), propertyInfo.PropertyType); } else if (propertyInfo.PropertyType != typeof(String)) { // Attempt to find a "Parse" method to convert MethodInfo parseMethod = propertyInfo.PropertyType.GetMethod("Parse", new[] { typeof(String) }); if (parseMethod == null) { throw new Exception($"No '{propertyInfo.PropertyType}.Parse(String)' method was found to use for conversion."); } assignedExpression = Expression.Call(parseMethod, assignedExpression); } temp.Add(Expression.Assign(Expression.Property(returnExpression, propertyInfo), assignedExpression)); if (fieldAttribute.IsRequired) { ret.AddRange(temp); } else { ret.Add(Expression.IfThenElse(isNullMatch, Expression.Assign(Expression.Property(returnExpression, propertyInfo), Expression.Convert(Expression.Constant(null), propertyInfo.PropertyType)), Expression.Block(temp))); } return(ret); }
private SR.FieldInfo GetTargetField(IFieldAttribute attr, Type targetType, SR.FieldInfo injectionField) { var fieldName = !String.IsNullOrEmpty(attr.Name) ? attr.Name : injectionField.Name; var foundField = FindMatchingFieldByName(targetType, injectionField, fieldName); if (attr is FieldAddInjectionAttribute) { if (foundField != null) throw new InvalidOperationException(targetType.FullName + "." + fieldName + " is duplicate"); } else { if (foundField == null) throw new InvalidOperationException(targetType.FullName + "." + fieldName + " not found"); } return foundField; }
private static List <Expression> CreateFieldExpression(PropertyInfo propertyInfo, IFieldAttribute fieldAttribute, ParameterExpression returnExpression, Expression valueExpression) { List <Expression> ret = new List <Expression>(); Regex nullRegex = (fieldAttribute.NullPattern != null) ? new Regex(fieldAttribute.NullPattern) : new Regex(@"^\s*$"); Expression isNullMatch = Expression.Call(Expression.Constant(nullRegex), typeof(Regex).GetMethod("IsMatch", new[] { typeof(string) }) ?? throw new InvalidOperationException(), valueExpression); Expression assignedExpression = valueExpression; if (fieldAttribute.IsRequired) { ret.Add(Expression.IfThen(isNullMatch, Expression.Throw(Expression.Constant(new Exception($"Field '{propertyInfo.Name}' cannot be null"))))); } List <Expression> temp = new List <Expression>(); if (fieldAttribute.ValidationPattern != null) { Regex validationRegex = new Regex(fieldAttribute.ValidationPattern); Expression isValidationMatch = Expression.Call(Expression.Constant(validationRegex), typeof(Regex).GetMethod("IsMatch", new[] { typeof(String) }) ?? throw new InvalidOperationException(), valueExpression); Expression s = Expression.Call(typeof(String).GetMethod("Format", new[] { typeof(String), typeof(String) }) ?? throw new InvalidOperationException(), Expression.Constant($"Field '{propertyInfo.Name}' does not match the required format.\nValue: {{0}}"), valueExpression); Expression exception = Expression.New(typeof(Exception).GetConstructor(new[] { typeof(String) }) ?? throw new InvalidOperationException(), s); temp.Add(Expression.IfThen(Expression.Not(isValidationMatch), Expression.Throw(exception))); } IEnumerable <Attribute> conversionAttributes = propertyInfo.GetCustomAttributes().Where(attribute => attribute.GetType().GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IConversionAttribute <>))).ToArray(); if (conversionAttributes.Count() > 1) { throw new Exception($"Property '{propertyInfo}' cannot contain multiple conversion attributes."); } else if (conversionAttributes.Count() == 1) { assignedExpression = Expression.Convert(Expression.Call(Expression.Constant(conversionAttributes.First()), conversionAttributes.First().GetType().GetMethod("Convert", new[] { typeof(String) }) ?? throw new InvalidOperationException(), assignedExpression), propertyInfo.PropertyType); } else if (propertyInfo.PropertyType.IsEnum || (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>) && propertyInfo.PropertyType.GetGenericArguments()[0].IsEnum)) { Type enumType = (propertyInfo.PropertyType.IsEnum) ? propertyInfo.PropertyType : propertyInfo.PropertyType.GetGenericArguments()[0]; assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }) ?? throw new InvalidOperationException(), Expression.Constant(" "), Expression.Constant("")); assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }) ?? throw new InvalidOperationException(), Expression.Constant("_"), Expression.Constant("")); assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }) ?? throw new InvalidOperationException(), Expression.Constant("&"), Expression.Constant("")); assignedExpression = Expression.Call(assignedExpression, typeof(String).GetMethod("Replace", new[] { typeof(String), typeof(String) }) ?? throw new InvalidOperationException(), Expression.Constant("-"), Expression.Constant("")); if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable <>)) { assignedExpression = Expression.Convert(Expression.Call(typeof(StreamParser <TRecord>).GetMethod("ParseEnumCaseIgnored").MakeGenericMethod(Nullable.GetUnderlyingType(propertyInfo.PropertyType)), Expression.Constant(propertyInfo.Name), assignedExpression), propertyInfo.PropertyType); } else { assignedExpression = Expression.Call(typeof(StreamParser <TRecord>).GetMethod("ParseEnumCaseIgnored").MakeGenericMethod(propertyInfo.PropertyType), Expression.Constant(propertyInfo.Name), assignedExpression); } } else if (propertyInfo.PropertyType != typeof(String)) { Type conversionType = propertyInfo.PropertyType; // If this is a Nullable<?> type then we need to extract the inner type to find the parse method; if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition() == typeof(Nullable <>)) { conversionType = propertyInfo.PropertyType.GetGenericArguments()[0]; } // Attempt to find a "Parse" method to convert MethodInfo parseMethod = conversionType.GetMethod("Parse", new[] { typeof(String) }); if (parseMethod == null) { throw new Exception($"No '{propertyInfo.PropertyType}.Parse(String)' method was found to use for conversion."); } assignedExpression = Expression.Call(parseMethod, assignedExpression); if (conversionType != propertyInfo.PropertyType) { assignedExpression = Expression.Convert(assignedExpression, propertyInfo.PropertyType); } } temp.Add(Expression.Assign(Expression.Property(returnExpression, propertyInfo), assignedExpression)); if (fieldAttribute.IsRequired) { ret.AddRange(temp); } else { ret.Add(Expression.IfThenElse(isNullMatch, Expression.Assign(Expression.Property(returnExpression, propertyInfo), Expression.Convert(Expression.Constant(null), propertyInfo.PropertyType)), Expression.Block(temp))); } return(ret); }