c#避免拳击和重复代码

时间:2016-10-03 10:51:18

标签: c# oop interface func boxing

我有基类和派生类。有两点我觉得我的代码有问题:

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语句等等。
  2. 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));
    };
    
    1. 装箱和拆箱:我被迫根据派生类的类型将对象值转换为所需类型:
    2. (field as FInt).SetValue(Convert.ToInt32(value));
      (field as FString).SetValue(Convert.ToString(value));
      (field as FDate).SetValue(Convert.ToDateTime(value));
      

      我对如何设计这些类以解决上述问题感兴趣。

      非常感谢您的帮助。

1 个答案:

答案 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,您可以使用lambdas字典。例如:

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