/// <summary> /// Retrieves an attribute that applies to a specific dialect. /// </summary> /// <typeparam name="T">The attribute to retrieve.</typeparam> /// <param name="dialect">A dialect that the attribute should apply to.</param> /// <param name="property">The property that the attribute is applied to.</param> /// <returns>An attribute for the given property. This will be <c>null</c> when no attribute is present.</returns> /// <exception cref="ArgumentNullException"><paramref name="dialect"/> or <paramref name="property"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">More than one matching attribute was found.</exception> public static T GetDialectAttribute <T>(this IDatabaseDialect dialect, PropertyInfo property) where T : ModelledSchemaAttribute { if (dialect == null) { throw new ArgumentNullException(nameof(dialect)); } if (property == null) { throw new ArgumentNullException(nameof(property)); } var dialectType = dialect.GetType(); var attrs = property.GetCustomAttributes <T>(true) .Where(attr => attr.SupportsDialect(dialectType)) .ToList(); if (attrs.Count > 1) { throw new ArgumentException($"More than one matching { typeof(T).FullName } attribute was found for the property { property.Name } in { property.ReflectedType.FullName }.", nameof(property)); } return(attrs.SingleOrDefault()); }
public ReflectionColumnDataType(IDatabaseDialect dialect, Type columnType, Type clrType) { if (dialect == null) { throw new ArgumentNullException(nameof(dialect)); } if (columnType == null) { throw new ArgumentNullException(nameof(columnType)); } if (clrType == null) { throw new ArgumentNullException(nameof(clrType)); } var attr = dialect.GetDialectAttribute <DeclaredTypeAttribute>(columnType); if (attr == null) { throw new ArgumentException($"The column type { columnType.FullName } does not contain a definition for the dialect { dialect.GetType().FullName }"); } var typeProvider = dialect.TypeProvider; if (typeProvider == null) { throw new ArgumentException("The given dialect does not contain a valid type provider.", nameof(dialect)); } var collationAttr = dialect.GetDialectAttribute <CollationAttribute>(columnType); var typeMetadata = new ColumnTypeMetadata { ClrType = clrType, Collation = collationAttr?.CollationName != null ? Option <Identifier> .Some(collationAttr.CollationName) : Option <Identifier> .None, DataType = attr.DataType, IsFixedLength = attr.IsFixedLength, MaxLength = attr.Length, NumericPrecision = attr.Precision > 0 && attr.Scale > 0 ? Option <INumericPrecision> .Some(new NumericPrecision(attr.Precision, attr.Scale)) : Option <INumericPrecision> .None, }; var dbType = typeProvider.CreateColumnType(typeMetadata); // map dbType to properties, avoids keeping a reference TypeName = dbType.TypeName; DataType = dbType.DataType; Definition = dbType.Definition; IsFixedLength = dbType.IsFixedLength; MaxLength = dbType.MaxLength; ClrType = dbType.ClrType; NumericPrecision = dbType.NumericPrecision; Collation = dbType.Collation; }