代码之家  ›  专栏  ›  技术社区  ›  Aheho

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

  •  1
  • Aheho  · 技术社区  · 9 年前

    我正在尝试创建一个映射器,以便PetaPoco可以使用 枚举类 属性。查看有关枚举类的详细信息 here here .

    例如,以这个类为例。

        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 回复  |  直到 9 年前
        1
  •  2
  •   Aheho    9 年前

    那么...怎么样

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