To seed type tables in Entity Framework Core, I am rewriting this same code in the function 'StopLightColorTypeList' for every database type table that I need seed. I'm looking to create a generic method.
modelBuilder.Entity<StopLightColorType>
().HasData(WLProgramSeed.StopLightColorTypeList());
The StopLightColorTypeList takes each enumeration member creates a new StopLightColorType object and adds it to the list before:
Setting the object ID property to the int value of the Enum Setting the Name property to the string value of the Enum
I am looking to use generics in such a way where I can
- Specify the enumeration type (in this case it's StopLightColorsEnum)
- Specify the return type object (in this case it's StopLightColorType)
- Specify what property to set for the ID (must be integer) (in this case it's StopLightColorID)
- Specify what property to set for the name (must be a string) (in this case it's StopLightColorName)
- Optionally specify a function to parse the enumeration name
using System;
using System.Collections.Generic;
using System.Linq;
namespace GenericEnumToTypeList
{
class Program
{
static void Main(string[] args)
{
List<StopLightColorType> stopLightColorTypes = EFTools.StopLightColorTypes();
foreach(var stopLightColorType in stopLightColorTypes)
{
Console.WriteLine("ID: {0} Name: {1}", stopLightColorType.StopLightColorID, stopLightColorType.StopLightColorName);
}
Console.ReadLine();
}
}
public enum StopLightColorsEnum
{
Red = 1,
Yellow = 2,
Green = 3
}
public class StopLightColorType
{
public StopLightColorsEnum StopLightColorID { get; set; }
public string StopLightColorName { get; set; }
}
public class EFTools
{
public static List<StopLightColorType> StopLightColorTypes()
{
List<StopLightColorType> stopLightColorTypes = new List<StopLightColorType>();
foreach(StopLightColorsEnum stopLightColor in System.Enum.GetValues(typeof(StopLightColorsEnum))
{
StopLightColorType stopLightColorType = new StopLightColorType
{
StopLightColorID = stopLightColor,
StopLightColorName = ParseCapitalizedEnumName(stopLightColor.ToString())
};
stopLightColorTypes.Add(stopLightColorType);
}
return stopLightColorTypes;
}
public static string ParseUnderScoreName(string stringName)
{
return stringName.Replace("_", " "); ;
}
public static string ParseCapitalizedEnumName(string enumName)
{
string typeName = enumName[0].ToString();
for(int i = 1; i <= enumName.Length; i )
{
if(Char.ToUpper(enumName[i]) == enumName[i])
{
typeName = typeName " " enumName[i].ToString();
}
}
return typeName;
}
}
}
I re-write this code for each database type, I'm looking for a generic to take care of this operation.
CodePudding user response:
The core function you need is this:
IEnumerable<TResult> ListEnumMembers<TEnum, TResult>(string valueName, string nameName)
where TEnum : System.Enum
{
var enumInfos = Enum.GetValues(typeof(TEnum)).Cast<int>()
.Zip(Enum.GetNames(typeof(TEnum)), (i, s) => (Value: i, Name: s));
var typ = typeof(TResult);
var piValue = typ.GetProperty(valueName);
var piName = typ.GetProperty(nameName);
return enumInfos.Select(i =>
{
var instance = (TResult)Activator.CreateInstance(typ);
piValue.SetValue(instance, i.Value);
piName.SetValue(instance, i.Name);
return instance;
});
}
With this generic result type...
class EnumInfo
{
public int Value { get; set; }
public string Name { get; set; }
}
...and this code:
var enumInfos = ListEnumMembers<DayOfWeek, EnumInfo>("Value", "Name").ToList();
You get this result:
| Value | Name |
|---|---|
| 0 | Sunday |
| 1 | Monday |
| 2 | Tuesday |
| 3 | Wednesday |
| 4 | Thursday |
| 5 | Friday |
| 6 | Saturday |
I guess this will put you on the right track. Of course the code needs a couple of checks for the property names and types.
