设计支持 HeadSprings 枚举类的自定义 PetaPoco 映射器

本文关键字:自定义 PetaPoco 映射 支持 HeadSprings 枚举 | 更新日期: 2023-09-27 18:32:34

我正在尝试创建一个映射器,以便PetaPoco可以使用枚举类属性来补充和持久化POCO。在此处或此处查看有关枚举类的详细信息。

例如,参加这门课。

    public class PetType : Headspring.Enumeration<PetType>
    {
       public static readonly PetType Frog = new PetType(1, "Frog");
       public static readonly PetType Cat = new PetType(2, "Cat");
       public static readonly PetType Fish = new PetType(3, "Fish");
       public static readonly PetType Dog = new PetType(4, "Dog");
       private PetType(int value, string displayName) : base(value, displayName) { }
     }

可以这样使用:

var MyPet = PetType.Dog;

这是我想要用数据库补水/持久化的 Poco:

    public class Pet
    {
         public int ID { get; set; }
         public string OwnerName { get; set; }
         public DateTime DateOfBirth { get; set; }
         public string PetName{ get; set; }
         public PetType PetType{ get; set; }
    }

我设计了一个自定义映射器,可以与PetType一起使用:

    class EnumClassMapper :  PetaPoco.StandardMapper 
    {
       public override Func<object, object> GetFromDbConverter(System.Reflection.PropertyInfo targetProperty, Type sourceType)
       {
           if (targetProperty.PropertyType == typeof(PetType))
           {
               return (x) => PetType.FromValue((int) x);
           }
           return base.GetFromDbConverter(targetProperty, sourceType);
       }
       public override Func<object, object> GetToDbConverter(System.Reflection.PropertyInfo sourceProperty)
       {
           if (sourceProperty.PropertyType == typeof(PetType))
           {
               return (x) => ((PetType)x).Value;
           }
           return base.GetToDbConverter(sourceProperty);
       }
   }

但是,假设我创建了另一个枚举子类用于处置。

    public class Disposition: Headspring.Enumeration<Disposition>
    {
       public static readonly Friendly = new Disposition(1, "Friendly");
       public static readonly Timid = new Disposition(2, "Timid");
       public static readonly Aggressive = new Disposition(3, "Aggressive");
       private Disposition(int value, string displayName) : base(value, displayName) { }
     }

我不想每次创建枚举类的新子类时都必须更新映射器。我希望映射代码能够识别属性类型是枚举类的后代,并相应地进行映射。我认为答案是利用反思,但我不知道如何进行。

设计支持 HeadSprings 枚举类的自定义 PetaPoco 映射器

怎么样

public class EnumClassMapper<T> :  PetaPoco.StandardMapper 
    where T : Headspring.Enumeration<T>   
{
   public override Func<object, object> GetFromDbConverter(System.Reflection.PropertyInfo targetProperty, Type sourceType)
   {
       return (x) => Enumeration<T, int>.FromValue((int) x);
   }
   public override Func<object, object> GetToDbConverter(System.Reflection.PropertyInfo sourceProperty)
   {
       return (x) => ((T)x).Value;
   }
}
var builder = DatabaseConfiguration.Build()
    .UsingConnectionStringName("sqlite")
    .UsingDefaultMapper<ConventionMapper>(m =>
    {
        m.FromDbConverter = (targetProperty, sourceType) =>
        {
            if (targetProperty == null)
                return null;
            var t = targetProperty.PropertyType;
                    if (t.BaseType == null || ! t.BaseType.IsGenericType) 
                        return null;
                    if (t.BaseType.GetGenericTypeDefinition() != typeof(Headspring.Enumeration<>))
                        return null;
                    return ((IMapper)Activator.CreateInstance(typeof(EnumClassMapper<>).MakeGenericType(t))).GetFromDbConverter(targetProperty, sourceType);
        };
        m.ToDbConverter = sourceProperty =>
        {
            if (sourceProperty == null)
                return null;
            var t = sourceProperty.PropertyType;
                    if (t.BaseType == null || !t.BaseType.IsGenericType)
                        return null;
                    if (t.BaseType.GetGenericTypeDefinition() != typeof(Headspring.Enumeration<>))
                        return null;
                    return ((IMapper)Activator.CreateInstance(typeof(EnumClassMapper<>).MakeGenericType(t))).GetToDbConverter(sourceProperty);
        };
    });
var db = builder.Create();