/// <summary> /// Creates a value converter for <see cref="IValidatableEnum{TKey}"/>. /// </summary> /// <param name="type">Type of the value object/enum.</param> /// <param name="validateOnWrite">In case of an <see cref="IValidatableEnum{TKey}"/>, ensures that the item is valid before writing it to database.</param> /// <returns>An instance of <see cref="ValueConverter"/>></returns> public static ValueConverter Create(Type type, bool validateOnWrite) { if (type is null) { throw new ArgumentNullException(nameof(type)); } var metadata = ValueObjectMetadataLookup.Find(type); if (metadata is null) { throw new ArgumentException($"The provided type '{type.Name}' is neither an Smart Enum nor a Value Object with a key member."); } object converter; if (metadata.IsValidatableEnum) { var enumConverterType = typeof(ValidatableEnumValueConverter <,>).MakeGenericType(metadata.Type, metadata.KeyType); converter = Activator.CreateInstance(enumConverterType, new object[] { validateOnWrite }) ?? throw new Exception($"Could not create an instance of '{enumConverterType.Name}'."); } else { var converterType = typeof(ValueObjectValueConverter <,>).MakeGenericType(metadata.Type, metadata.KeyType); converter = Activator.CreateInstance(converterType) ?? throw new Exception($"Could not create an instance of '{converterType.Name}'."); } return((ValueConverter)converter); }
private static void AddConverterForScalarProperties( IMutableEntityType entity, bool validateOnWrite, Dictionary <Type, ValueConverter> converterLookup, Action <IMutableProperty> configure) { foreach (var property in entity.GetProperties()) { var valueConverter = property.GetValueConverter(); if (valueConverter is not null) { continue; } var propertyType = property.ClrType; if (ValueObjectMetadataLookup.Find(propertyType) is null) { continue; } SetConverterAndExecuteCallback(validateOnWrite, converterLookup, configure, property); } }
private static void AddConvertersForNavigations( IMutableEntityType entity, ModelBuilder modelBuilder, bool validateOnWrite, Dictionary <Type, ValueConverter> converterLookup, Action <IMutableProperty> configure) { List <IMutableNavigation>?navigationsToConvert = null; foreach (var navigation in entity.GetNavigations()) { if (ValueObjectMetadataLookup.Find(navigation.ClrType) is not null) { (navigationsToConvert ??= new List <IMutableNavigation>()).Add(navigation); } } if (navigationsToConvert is null) { return; } var builders = modelBuilder.FindEntityBuilder(entity); foreach (var navigation in navigationsToConvert) { var property = FindPropertyBuilder(builders, entity, navigation.Name); SetConverterAndExecuteCallback(validateOnWrite, converterLookup, configure, property.Metadata); } }
/// <inheritdoc /> public IModelBinder?GetBinder(ModelBinderProviderContext context) { if (context is null) { throw new ArgumentNullException(nameof(context)); } // Skip model binding from body so BodyModelBinder incl. JSON serialization takes over if (SkipModelBinding(context)) { return(null); } var metadata = ValueObjectMetadataLookup.Find(context.Metadata.ModelType); if (metadata is null) { return(null); } var loggerFactory = context.Services.GetRequiredService <ILoggerFactory>(); var modelBinderType = typeof(ValueObjectModelBinder <,>).MakeGenericType(metadata.Type, metadata.KeyType); var modelBinder = Activator.CreateInstance(modelBinderType, loggerFactory, metadata.Validate) ?? throw new Exception($"Could not create an instance of type '{modelBinderType.Name}'."); return((IModelBinder)modelBinder); }
private static Expression <Func <T, TKey> > GetConverterToKey <T, TKey>() { var metadata = ValueObjectMetadataLookup.Find(typeof(T)); if (metadata is null) { throw new InvalidOperationException($"No metadata for provided type '{typeof(T).Name}' found."); } return((Expression <Func <T, TKey> >)metadata.ConvertToKeyExpression); }
private void ProcessProperty(IConventionProperty property) { var valueConverter = property.GetValueConverter(); if (valueConverter is not null) { return; } if (ValueObjectMetadataLookup.Find(property.ClrType) is null) { return; } SetConverterAndExecuteCallback(property); }
private void AddSmartEnumAndKeyedValueObjects(IConventionEntityTypeBuilder entityTypeBuilder) { var entity = entityTypeBuilder.Metadata; foreach (var propertyInfo in entity.ClrType.GetRuntimeProperties()) { var navigation = entity.FindNavigation(propertyInfo); if (navigation is not null) { ProcessNavigation(navigation); continue; } var property = entity.FindProperty(propertyInfo); if (property is not null) { ProcessProperty(property); continue; } if (!propertyInfo.IsCandidateProperty()) { continue; } var propertyType = propertyInfo.PropertyType; var metadata = ValueObjectMetadataLookup.Find(propertyType); if (metadata is null) { continue; } property = entity.AddProperty(propertyInfo); if (property is not null) { SetConverterAndExecuteCallback(property); } } }
private void ProcessNavigation(IConventionNavigation navigation) { var naviType = navigation.ClrType; if (ValueObjectMetadataLookup.Find(naviType) is null) { return; } var property = navigation.DeclaringEntityType.Builder .Property(naviType, navigation.Name)? .Metadata; if (property is null) { return; } SetConverterAndExecuteCallback(property); }
private static void AddSmartEnumAndKeyedValueObjects( bool validateOnWrite, Dictionary <Type, ValueConverter> converterLookup, Action <IMutableProperty> configure, IMutableEntityType entity) { foreach (var propertyInfo in entity.ClrType.GetRuntimeProperties()) { // will be handled by "AddConvertersForNavigations" if (entity.FindNavigation(propertyInfo) is not null) { continue; } // wil be handled by AddConverterForScalarProperties if (entity.FindProperty(propertyInfo) is not null) { continue; } if (!propertyInfo.IsCandidateProperty()) { continue; } var propertyType = propertyInfo.PropertyType; var metadata = ValueObjectMetadataLookup.Find(propertyType); if (metadata is null) { continue; } var property = entity.AddProperty(propertyInfo); SetConverterAndExecuteCallback(validateOnWrite, converterLookup, configure, property); } }
/// <inheritdoc /> public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { if (typeToConvert is null) { throw new ArgumentNullException(nameof(typeToConvert)); } if (options is null) { throw new ArgumentNullException(nameof(options)); } var metadata = ValueObjectMetadataLookup.Find(typeToConvert); if (metadata is null) { throw new InvalidOperationException($"No metadata for provided type '{typeToConvert.Name}' found."); } var converterType = typeof(ValueObjectJsonConverter <,>).MakeGenericType(metadata.Type, metadata.KeyType); var converter = Activator.CreateInstance(converterType, metadata.ConvertFromKey, metadata.ConvertToKey, options) ?? throw new Exception($"Could not create converter of type '{converterType.Name}'."); return((JsonConverter)converter); }
static Cache() { var type = typeof(T); var metadata = ValueObjectMetadataLookup.Find(type); if (metadata is null) { return; } var formatterGenericTypeDefinition = Nullable.GetUnderlyingType(type) == metadata.Type ? typeof(NullableStructValueObjectMessagePackFormatter <,>) : typeof(ValueObjectMessagePackFormatter <,>); var formatterType = formatterGenericTypeDefinition.MakeGenericType(metadata.Type, metadata.KeyType); var formatter = Activator.CreateInstance(formatterType, metadata.ConvertFromKey, metadata.ConvertToKey); if (formatter is null) { InitError = $"The formatter of '{formatterType.Name}' could not be instantiated."; return; } Formatter = (IMessagePackFormatter <T>)formatter; }
/// <inheritdoc /> public override bool CanConvert(Type typeToConvert) { return(ValueObjectMetadataLookup.Find(typeToConvert) is not null); }