The goal of this is to identify types that are generated by Vogen.
Use Case
I use Vogen alongside EfCore, I like to programmatically add ValueConverters by convention, I need to identity which properties on my entities are generated value objects.
Solution
Vogen decorates the source it generates with the GeneratedCodeAttribute. This provides metadata about the tool which generated the code, this is what we'll use as an identifier.
Note: the code snippets use:
CSharpFunctionalExtensions - to use Maybe<T> BTW - if you're reading this, and have not checked out this library, I highly recommend. You don't need to adopt the pattern 100%, treat it as a buffet and take / use what you want
XUnit, because it's better than NUnit and MSTest 🙃
Code Snippet
// Helper class
internal static class AttributeHelper
{
public static bool IsVogenValueObject(this Type targetType)
{
Maybe<GeneratedCodeAttribute> generatedCodeAttribute =
targetType.GetClassAttribute<GeneratedCodeAttribute>();
return generatedCodeAttribute.HasValue &&
generatedCodeAttribute.Value.Tool == "Vogen";
}
private static Maybe<TAttribute> GetClassAttribute<TAttribute>(
this Type targetType) where TAttribute : Attribute
{
return targetType.GetAttribute<TAttribute>();
}
}
Usage Example (From EfCore)
foreach (IMutableEntityType et in builder.Model.GetEntityTypes())
{
PropertyInfo[] properties = et.ClrType.GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
if (propertyInfo.PropertyType.IsVogenValueObject())
{
// Huzzah!
// Do something with the property that is a value
// object generated by Vogen....
}
}
}
Testing
Data for unit test
[ValueObject<Guid>]
// ReSharper disable once PartialTypeWithSinglePart
public readonly partial struct VogenStronglyTypedId {}
Unit Test
```c#
public class VogenStronglyTypedIdTests
{
[Fact]
public void ShouldIdentityVogenAttributeByHelperMethod()
{
Type vogenType = typeof(VogenStronglyTypedId);
Maybe<GeneratedCodeAttribute> generatedCodeAttribute =
vogenType.GetClassAttribute<GeneratedCodeAttribute>();
Assert.True(generatedCodeAttribute.HasValue);
GeneratedCodeAttribute? valueOfAttribute =
generatedCodeAttribute.Value;
valueOfAttribute.Tool.Should().Be("Vogen");
}
[Fact]
public void ShouldIdentityVogenAttribute()
{
Type vogenType = typeof(VogenStronglyTypedId);
vogenType.IsVogenValueObject()
.Should()
.Be(true);
}
}
Summary
Jeff says:
Adding all value objects to the ModelConfigurationBuilder