question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ValueConverterAttribute for Smart Enums and simple Value Objects

See original GitHub issue

I work with Smart Enums and Value Objects quite a lot, which have to be persisted in a database. To do so the classes have to provide a ValueConverter. Currently, the ValueConverters can be registered

  • manually via HasConversion or in ConfigureConventions. Both options require some typing if the model is using dozens of different Smart Enums and Value Objects.
  • “automatically” in OnModelCreating by iterating over all entities and all properties
  • “automatically” by passing some conventions (like PropertyAddedConventions and NavigationAddedConventions) to DbContextOptionsBuilder

An ideal solution would be if the developer doesn’t have to do anything besides implementing the Smart Enum or Value Object - similar as with JsonConverterAttribute or MessagePackFormatterAttribute.

The current work flow for JSON is as following:

  • The developer installs a nuget package and implements a Smart Enum or a Value Object.
public partial class ProductType : IEnum<string>
{
   public static readonly ProductType Groceries = new("Groceries");
   public static readonly ProductType Housewares = new("Housewares");
}

A roslyn source generator kicks in and generates a lot of boilerplate code.

  • The developer installs a JSON-specific nuget package, which comes with another roslyn source generator. The source generator applies the JsonConverterAttribute to the Smart Enum/Value Object - the type is json-serializable without further configuration.
[JsonConverterAttribute(typeof(ValueObjectJsonConverterFactory))]
partial class ProductType
{
}

With a ValueConverterAttribute it would be the same as with JSON. A source generator could render a few lines of code making the type convertable.

[ValueConverterAttribute(typeof(MyProductTypeValueConverter))]
partial class ProductType
{
}

A more powerfull solution could be an attribute, which provides not just the ValueConverter but some other configuration settings as well, like max-length, is-unicode and precision.

[ScalarValueAttribute(ValueConverter = typeof(MyProductTypeValueConverter), MaxLength = 20)]
partial class ProductType
{
}

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
rojicommented, Jan 31, 2022

@PawelGerr if you’re simply looking for a way to easily bulk-configure a value converter for all properties of a given type, then you’d probably be interested in the new pre-convention model configuration in EF Core 6.0.

Aside from this, you seem to be asking to configure value converters via an attribute (Data Annotation). This approach would be generally limited, since attributes are very constrained in the parameters they allow (essentially only constants); we tend to provide Data Annotations for the simple/restricted cases (e.g. specifying a string column name), but value converters are quite an open case which may not be a good fit.

Given the new pre-convention model configuration which can be used to do the same thing, do you still think an attribute-based approach is important, especially given the added complexity of the source generator to augment the type with it?

As an aside, I’m curious about the pattern of defining a “smart enum” in this way… I understand the desire to pack additional state with the enum (not possible with built-in .NET enum), but this precludes using the enum in standard C# constructs (e.g. switches, pattern matching) and is quite inefficient (heap allocation for each enum instance, could be mitigated by making it a struct).

0reactions
PawelGerrcommented, Feb 1, 2022

It may indeed make sense to revisit this idea once value objects are implemented

Ok, let’s wait for the value objects.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Value Conversions - EF Core
This conversion can be from one value to another of the same type (for example, encrypting strings) or from a value of one...
Read more >
Persisting a Smart Enum with Entity Framework Core - Blog
A Smart Enum is an enhancement of the C# enum that provides a strongly typed and object oriented approach to enum types. Smart...
Read more >
Smart Enums in C#. Introduction | by Atakan Korez
Easy management of values: Smart Enums can make enum constants more specialized, adding properties and functions. This makes the difference with enum constants ......
Read more >
c# - EF Core - ValueConverter or OwnedType for simple ...
I use value objects to encapsulate validations like maxLength. This is an extract of a sample class without factory method and validation:
Read more >
Way to lambda - Homepage of Florian Rappl
In this article I'll try to cover the following things: A brief introduction - what are lambda expressions exactly and why do they...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found