Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/nuget/Microsoft.SourceLink.GitHub…
Browse files Browse the repository at this point in the history
…-8.0.0
  • Loading branch information
ardalis authored Feb 28, 2024
2 parents bbf44b6 + 903ef82 commit 87241be
Show file tree
Hide file tree
Showing 49 changed files with 1,102 additions and 447 deletions.
10 changes: 5 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AutoFixture" Version="4.17.0" />
<PackageVersion Include="AutoFixture" Version="4.18.1" />
<PackageVersion Include="BenchmarkDotNet" Version="0.13.10" />
<PackageVersion Include="Constant" Version="2.0.4" />
<PackageVersion Include="coverlet.collector" Version="3.2.0" />
<PackageVersion Include="coverlet.msbuild" Version="3.2.0" />
<PackageVersion Include="Dapper" Version="2.1.15" />
<PackageVersion Include="Dapper" Version="2.1.28" />
<PackageVersion Include="Enums.NET" Version="4.0.1" />
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
<PackageVersion Include="MessagePack" Version="2.4.59" />
Expand All @@ -22,11 +22,11 @@
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.2" />
<PackageVersion Include="protobuf-net" Version="3.2.26" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.12.0.78982" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="9.17.0.82934" />
<PackageVersion Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageVersion Include="System.Text.Json" Version="7.0.3" />
<PackageVersion Include="System.Text.Json" Version="8.0.2" />
<PackageVersion Include="Utf8Json" Version="1.3.7" />
<PackageVersion Include="xunit" Version="2.4.2" />
<PackageVersion Include="xunit" Version="2.7.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions src/SmartEnum.AutoFixture/SmartEnumCustomization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@ namespace Ardalis.SmartEnum.AutoFixture
{
using global::AutoFixture;

/// <summary>
///
/// </summary>
public class SmartEnumCustomization : ICustomization
{
/// <summary>
///
/// </summary>
/// <param name="fixture"></param>
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new SmartEnumSpecimenBuilder());
Expand Down
9 changes: 9 additions & 0 deletions src/SmartEnum.AutoFixture/SmartEnumSpecimenBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ namespace Ardalis.SmartEnum.AutoFixture
using System;
using global::AutoFixture.Kernel;

/// <summary>
///
/// </summary>
public class SmartEnumSpecimenBuilder :
ISpecimenBuilder
{
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="context"></param>
/// <returns></returns>
public object Create(object request, ISpecimenContext context)
{
if (request is Type type && type.TryGetValues(out var enums))
Expand Down
14 changes: 14 additions & 0 deletions src/SmartEnum.EFCore/SmartEnumConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

namespace Ardalis.SmartEnum.EFCore
{
/// <summary>
///
/// </summary>
/// <typeparam name="TEnum"></typeparam>
/// <typeparam name="TValue"></typeparam>
public class SmartEnumConverter<TEnum, TValue> : ValueConverter<TEnum, TValue>
where TEnum : SmartEnum<TEnum, TValue>
where TValue : IEquatable<TValue>, IComparable<TValue>
Expand Down Expand Up @@ -34,6 +39,12 @@ private static MethodInfo GetBaseFromValueMethod(Type objectType, Type valueType
return null;
}

/// <summary>
///
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public static TEnum GetFromValue(TValue value)
{
if (!CanConvert(typeof(TEnum)))
Expand All @@ -46,6 +57,9 @@ public static TEnum GetFromValue(TValue value)
return method.Invoke(null, new[] { (object)value }) as TEnum;
}

/// <summary>
///
/// </summary>
public SmartEnumConverter() : base(item => item.Value, key => GetFromValue(key), null)
{
}
Expand Down
221 changes: 111 additions & 110 deletions src/SmartEnum.EFCore/SmartEnumConverterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,155 +9,156 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Reflection;
using System.Text;

namespace SmartEnum.EFCore
namespace SmartEnum.EFCore;

/// <summary>
///
/// </summary>
public static class SmartEnumConverterExtensions
{
public static class SmartEnumConverterExtensions
/// <summary>
/// Adds a converter for all properties derived from <see cref="SmartEnum{TValue, TKey}"/>
/// so that entity framework core can work with it.
/// </summary>
public static void ConfigureSmartEnum(this ModelConfigurationBuilder configurationBuilder)
{
var modelBuilder = configurationBuilder.CreateModelBuilder(null);
var propertyTypes = modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.ClrType.GetProperties())
.Where(p => TypeUtil.IsDerived(p.PropertyType, typeof(SmartEnum<,>)))
.Where(p => p.GetCustomAttribute<NotMappedAttribute>() == null)
.Select(p => p.PropertyType)
.Distinct();

foreach (var propertyType in propertyTypes)
{
var (enumType, keyType) = TypeUtil.GetEnumAndValueTypes(propertyType, typeof(SmartEnum<,>));
if (enumType != propertyType)
{
// Only enum types 'TEnum' which extend SmartEnum<TEnum, TValue> are currently supported.
continue;
}

var converterType = typeof(SmartEnumConverter<,>).MakeGenericType(propertyType, keyType);

configurationBuilder.Properties(propertyType)
.HaveConversion(converterType);
}
}

/// <summary>
/// Adds a converter for all properties derived from <see cref="SmartEnum{TValue, TKey}"/>
/// so that entity framework core can work with it.
/// </summary>
/// <param name="modelBuilder"></param>
public static void ConfigureSmartEnum(this ModelBuilder modelBuilder)
{
/// <summary>
/// Adds a converter for all properties derived from <see cref="SmartEnum{TValue, TKey}"/>
/// so that entity framework core can work with it.
/// </summary>
public static void ConfigureSmartEnum(this ModelConfigurationBuilder configurationBuilder)
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
var modelBuilder = configurationBuilder.CreateModelBuilder(null);
var propertyTypes = modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.ClrType.GetProperties())
var properties = entityType.ClrType.GetProperties()
.Where(p => TypeUtil.IsDerived(p.PropertyType, typeof(SmartEnum<,>)))
.Where(p => p.GetCustomAttribute<NotMappedAttribute>() == null)
.Select(p => p.PropertyType)
.Distinct();
.Where(p => p.GetCustomAttribute<NotMappedAttribute>() == null);

foreach (var propertyType in propertyTypes)
foreach (var property in properties)
{
var (enumType, keyType) = TypeUtil.GetEnumAndValueTypes(propertyType, typeof(SmartEnum<,>));
if (enumType != propertyType)
var (enumType, keyType) = TypeUtil.GetEnumAndValueTypes(property.PropertyType, typeof(SmartEnum<,>));
if (enumType != property.PropertyType)
{
// Only enum types 'TEnum' which extend SmartEnum<TEnum, TValue> are currently supported.
continue;
}

var converterType = typeof(SmartEnumConverter<,>).MakeGenericType(propertyType, keyType);
var converterType = typeof(SmartEnumConverter<,>).MakeGenericType(property.PropertyType, keyType);

configurationBuilder.Properties(propertyType)
.HaveConversion(converterType);
}
}
var converter = (ValueConverter)Activator.CreateInstance(converterType);

/// <summary>
/// Adds a converter for all properties derived from <see cref="SmartEnum{TValue, TKey}"/>
/// so that entity framework core can work with it.
/// </summary>
/// <param name="modelBuilder"></param>
public static void ConfigureSmartEnum(this ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
var properties = entityType.ClrType.GetProperties()
.Where(p => TypeUtil.IsDerived(p.PropertyType, typeof(SmartEnum<,>)))
.Where(p => p.GetCustomAttribute<NotMappedAttribute>() == null);

foreach (var property in properties)
var propertyBuilder = GetPropertyBuilder(modelBuilder, entityType, property.Name);
if (propertyBuilder == null)
{
var (enumType, keyType) = TypeUtil.GetEnumAndValueTypes(property.PropertyType, typeof(SmartEnum<,>));
if (enumType != property.PropertyType)
{
// Only enum types 'TEnum' which extend SmartEnum<TEnum, TValue> are currently supported.
continue;
}

var converterType = typeof(SmartEnumConverter<,>).MakeGenericType(property.PropertyType, keyType);
continue;
}

var converter = (ValueConverter)Activator.CreateInstance(converterType);
propertyBuilder.HasConversion(converter);
}
}
}

var propertyBuilder = GetPropertyBuilder(modelBuilder, entityType, property.Name);
if (propertyBuilder == null)
{
continue;
}
private static PropertyBuilder GetPropertyBuilder(
ModelBuilder modelBuilder,
IMutableEntityType entityType,
string propertyName)
{
var ownershipPath = new List<IMutableForeignKey>();

propertyBuilder.HasConversion(converter);
}
var currEntityType = entityType;
while (currEntityType.IsOwned())
{
var ownership = currEntityType.FindOwnership();
if (ownership == null)
{
return null;
}

ownershipPath.Add(ownership);
currEntityType = ownership.PrincipalEntityType;
}

private static PropertyBuilder GetPropertyBuilder(
ModelBuilder modelBuilder,
IMutableEntityType entityType,
string propertyName)
var entityTypeBuilder = modelBuilder.Entity(currEntityType.Name);
if (ownershipPath.Count == 0)
{
var ownershipPath = new List<IMutableForeignKey>();
return entityTypeBuilder.Property(propertyName);
}

var currEntityType = entityType;
while (currEntityType.IsOwned())
{
var ownership = currEntityType.FindOwnership();
if (ownership == null)
{
return null;
}
var ownedNavigationBuilder = GetOwnedNavigationBuilder(entityTypeBuilder, ownershipPath);
if (ownedNavigationBuilder == null)
{
return null;
}

ownershipPath.Add(ownership);
currEntityType = ownership.PrincipalEntityType;
}
return ownedNavigationBuilder.Property(propertyName);
}

var entityTypeBuilder = modelBuilder.Entity(currEntityType.Name);
if (ownershipPath.Count == 0)
{
return entityTypeBuilder.Property(propertyName);
}
private static OwnedNavigationBuilder GetOwnedNavigationBuilder(
EntityTypeBuilder entityTypeBuilder,
List<IMutableForeignKey> ownershipPath)
{
OwnedNavigationBuilder ownedNavigationBuilder = null;
for (int i = ownershipPath.Count - 1; i >= 0; i--)
{
var ownership = ownershipPath[i];

var ownedNavigationBuilder = GetOwnedNavigationBuilder(entityTypeBuilder, ownershipPath);
if (ownedNavigationBuilder == null)
var navigation = ownership.GetNavigation(pointsToPrincipal: false);
if (navigation == null)
{
return null;
}

return ownedNavigationBuilder.Property(propertyName);
}

private static OwnedNavigationBuilder GetOwnedNavigationBuilder(
EntityTypeBuilder entityTypeBuilder,
List<IMutableForeignKey> ownershipPath)
{
OwnedNavigationBuilder ownedNavigationBuilder = null;
for (int i = ownershipPath.Count - 1; i >= 0; i--)
if (ownedNavigationBuilder == null)
{
var ownership = ownershipPath[i];

var navigation = ownership.GetNavigation(pointsToPrincipal: false);
if (navigation == null)
if (ownership.IsUnique)
{
return null;
ownedNavigationBuilder = entityTypeBuilder.OwnsOne(ownership.DeclaringEntityType.Name, navigation.Name);
}

if (ownedNavigationBuilder == null)
else
{
if (ownership.IsUnique)
{
ownedNavigationBuilder = entityTypeBuilder.OwnsOne(ownership.DeclaringEntityType.Name, navigation.Name);
}
else
{
ownedNavigationBuilder = entityTypeBuilder.OwnsMany(ownership.DeclaringEntityType.Name, navigation.Name);
}
ownedNavigationBuilder = entityTypeBuilder.OwnsMany(ownership.DeclaringEntityType.Name, navigation.Name);
}
}
else
{
if (ownership.IsUnique)
{
ownedNavigationBuilder = ownedNavigationBuilder.OwnsOne(ownership.DeclaringEntityType.Name, navigation.Name);
}
else
{
if (ownership.IsUnique)
{
ownedNavigationBuilder = ownedNavigationBuilder.OwnsOne(ownership.DeclaringEntityType.Name, navigation.Name);
}
else
{
ownedNavigationBuilder = ownedNavigationBuilder.OwnsMany(ownership.DeclaringEntityType.Name, navigation.Name);
}
ownedNavigationBuilder = ownedNavigationBuilder.OwnsMany(ownership.DeclaringEntityType.Name, navigation.Name);
}

}

return ownedNavigationBuilder;

}

return ownedNavigationBuilder;
}
}
Loading

0 comments on commit 87241be

Please sign in to comment.