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

时间:2016-01-31 14:43:41

标签: c# enumeration petapoco

我试图创建一个映射器,以便PetaPoco可以使用枚举类属性来保持和保持POCO。详细了解枚举类herehere

例如,参加这门课。

    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);
       }
   }

但是假设我为处置创建了另一个Enumeration子类。

    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) { }
     }

每次创建Enumeration类的新子类时,我都不想更新我的映射器。我更喜欢映射代码可以识别属性类型是Enumeration类的后代,并相应地映射。我假设答案是利用反思,但我不知道如何继续。

1 个答案:

答案 0 :(得分:1)

怎么样?
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();