2016-10-03 118 views
1

我有下面的基类和派生类。有2点,我觉得我的代码有问题:c#避免拳击和重复代码

public class FieldCollection 
{ 
    public FieldCollection() 
    { 
     Fields = new List<FieldBase>(); 
    } 

    public List<FieldBase> Fields { get; set; } 

    public void InitFieldList() 
    { 
     foreach (var item in DbFieldList) 
     { 
      if (item.Type == FieldTypes.int) 
      { 
       Fields.Add(new Field<int>()); 
      } 
      else 
      if (item.Type == FieldTypes.string) 
      { 
       Fields.Add(new Field<string>()); 
      } 
      ... 
     }; 
    } 

    public void SetFieldValue(string fieldName, object value) 
    { 
     FieldBase field = FindField(fieldName); 

     if ((field as FInt) != null) 
     { 
      (field as FInt).SetValue(Convert.ToInt32(value)); 
     } 
     else 
     if ((field as FString) != null) 
     { 
      (field as FString).SetValue(Convert.ToString(value)); 
     } 
     else 
     if ((field as FDate) != null) 
     { 
      (field as FDate).SetValue(Convert.ToDateTime(value)); 
     }; 
    } 

    public FieldBase FindField(string fieldName) 
    { 
     FieldBase field = Fields.FirstOrDefault(f => (String.Equals(f.Name, fieldName, StringComparison.CurrentCultureIgnoreCase))); 

     return field; 
    } 
} 

public abstract class FieldBase 
{ 
    public string Name { get; set; } 
} 

public class FInt : FieldBase 
{ 
    public void SetValue(int value) 
    { 
    } 
} 

public class FString : FieldBase 
{ 
    public void SetValue(string value) 
    { 
    } 
} 

public class FDate : FieldBase 
{ 
    public void SetValue(DateTime value) 
    { 
    } 
} 
  1. 重复:如果未来出现了一个新的派生类,我将有额外的if语句等补充。
if ((field as FInt) != null) 
{ 
    (field as FInt).SetValue(Convert.ToInt32(value)); 
} 
else 
if ((field as FString) != null) 
{ 
    (field as FString).SetValue(Convert.ToString(value)); 
} 
else 
if ((field as FDate) != null) 
{ 
    (field as FDate).SetValue(Convert.ToDateTime(value)); 
}; 
  • 装箱和取消装箱:我被迫对象值转换为基于派生的类的类型的期望类型:
  • (field as FInt).SetValue(Convert.ToInt32(value)); 
    (field as FString).SetValue(Convert.ToString(value)); 
    (field as FDate).SetValue(Convert.ToDateTime(value)); 
    

    我对如何设计这些类以克服上述提及感兴趣编辑问题。

    您的帮助非常感谢。

    +0

    看起来你需要仿制药 –

    回答

    3

    您可以通过重写使用泛型代码一次(代码重复和拳击),解决这两个问题:

    public class FieldCollection 
    { 
        public FieldCollection() 
        { 
         Fields = new List<FieldBase>(); 
        } 
    
        public List<FieldBase> Fields { get; set; } 
    
        public void SetFieldValue<T>(string fieldName, T value) 
        { 
         var field = FindField<T>(fieldName); 
    
         field.SetValue(value); 
        } 
    
        public Field<T> FindField<T>(string fieldName) 
        { 
         return Fields.OfType<Field<T>>() 
          .FirstOrDefault(f => (String.Equals(f.Name, fieldName, StringComparison.CurrentCultureIgnoreCase))); 
        } 
    } 
    
    public abstract class FieldBase 
    { 
        public string Name { get; set; } 
    } 
    
    public class Field<T> : FieldBase 
    { 
        public void SetValue(T value) 
        { 
        } 
    } 
    

    InitFieldList,你可以使用lambda表达式的字典。例如:

    private Dictionary<FieldTypes, Func<FieldBase>> FieldInitializers = new Dictionary<FieldTypes, Func<FieldBase>> 
    { 
        { FieldTypes.int,() => new Field<int>() }, 
        { FieldTypes.string,() => new Field<string>() } 
    } 
    

    然后,它只是一个浏览你的字典的事:

    public void InitFieldList() 
    { 
        foreach (var item in DbFieldList) 
        { 
         Fields.Add(FieldInitializers[item.Type].Invoke()); 
        } 
    } 
    
    +0

    感谢@KooKiz。我忘了在FieldCollection类中添加Fields属性的population方法。我也想问如何避免多个if语句?请参阅原始帖子中的修改。 – Tim

    +0

    @Tim请编辑你的问题,而不是答案。此外,请确切指出条件是 –

    +0

    编辑。谢谢。 – Tim