The EnumValueObject is based on the ValueObject
class from here (credits to: vkhorikov).
This library lets you create strong typed enums, which can only be in a valid state. Furthermore it allows you to define methods on top of your enum and computed property. See the sample section or the quick start tutorial below.
PM> Install-Package LinkDotNet.EnumValueObject
With this EnumValueObject
you can only create a valid state of the object itself. Imagine this small EnumValueObject
public class Language : EnumValueObject<Language>
{
public static readonly Language German = new Language("de");
public static readonly Language English = new Language("en");
protected Language(string key) : base(key)
{
}
}
To create an EnumValueObject
you have to call the static Create
method. Define your constructor always protected or private so that the consumer has to take the Create
method.
var languageResult = Language.Create("en");
This will return you a Result
object. You can check with languageResult.IsFailure
if we had an error (yes no exceptions). If not you can just access the EnumValueObject
with languageResult.Value
.
One downside of the regular enum
struct is that you can just give it arbitrary values. The following example will not result in any error:
public enum Language
{
English = 0,
German = 1,
}
...
var language = (Language)500;
With the EnumValueObject
you will not receive a valid Result.
If you have a valid EnumValueObject
you can compare it in two ways:
- Checking against the
EnumValueObject
itself
if (language == Language.English)
{
...
}
- Checking against the key
if (language == "en")
{
...
}
The second option can come in handy if you need to test against direct user input.
No need for extension methods. Because it is a normal class
you can just define functions and also have properties which will make your life easier. Remember the Language
example. Lets extend this a bit.
public class Language : EnumValueObject<Language>
{
public static readonly Language German = new Language("de", "€");
public static readonly Language English = new Language("en", "£");
public string Currency { get; }
protected Language(string key, string currency) : base(key)
{
Currency = currency;
}
}
Once a valid EnumValueObject
is created, you can just access those properties and work with it.
var language = Language.Create("de").Result;
var currency = language.Currency; // €
It is enough to store the key to the database. When the EnumValueObject
is populated it will automatically set all the dependent properties (like the currency in the last example).
See the samples how to use EnumValueObjects
with the System.Text.Json.JsonSerializer
without any problems (and without any parameterless constructor). With the extension you don't have to provide a private or public parameterless constructor. Just add the attribute to your property and you are done.
public class MyDto
{
[JsonConverter(typeof(EnumValueObjectJsonConverter<MyEnumValueObject>))]
public MyEnumValueObject MyEnumValueObject { get; set; }
}
If you wanna persist your EnumValueObjects
with RavenDb, equip them with the Newtonsoft.Json.JsonConverter
attribute add the Converter:
public class EntityWhichGetsPersistedWithRavenDb
{
public string Id { get; set; }
[JsonConverter(typeof(EnumValueObjectNewtonsoftJsonConverter<MyEnumValueObject>))]
public MyEnumValueObject MyEnumValueObject { get; set; }
}