1

我有一个很长的条件声明:

  public static DataGridColumn CreateAppropreateColumn(string path, PropertyInfo info, string header, IRepository repository)
    {
        DataGridColumn column = null;

        if (info.GetCustomAttributes(typeof(DbComboBoxAttribute), true).Any())
        {
            column = CreateComboBoxColumn(path, info, header, repository);
        }
        else if (info.GetCustomAttributes(typeof(DescribedByteEnumComboBoxAttribute), true).Any())
        {
            column = CreateEnumComboBoxColumn(path, info, header);
        }
        else if (info.GetCustomAttributes(typeof(DropDownLazyLoadingDataGridAttribute), true).Any())
        {
            column = CreateDataGridDropDownLazyLoadingDataGridColumn(path, info, header, repository);
        }
        else if (info.GetCustomAttributes(typeof(DropDownTreeViewAttribute), true).Any())
        {
            column = CreateDataGridTreeViewColumn(path, info, header, repository);
        }
        //Other controls (Like drop down panels ... and so on ) can add here . . .
        //}
        else if (info.GetCustomAttributes(typeof(DatePickerAttribute), true).Any())
        {
            column = CreateDataGridDateColumn(path, info, header);
        }
        else if (info.GetCustomAttributes(typeof(YearPickerAttribute), true).Any())
        {
            column = CreateDataGridYearColumn(path, info, header);
        }
        else if (info.PropertyType == typeof(bool) || info.PropertyType == typeof(bool?))
        {
            column = CreateDataGridCheckBoxColumn(path, info, header);
        }
        else
        {
            column = CreateTextBoxColumn(path, info, header);
        }
return Column;

}

我可以删除 ifs 吗?

谢谢你。

4

4 回答 4

3

我经常做这些事情的一种方法是创建一个字典,将类型映射到创建结果的函数(您的字典将是 a Dictionary<Type, Func<string, PropertyInfo, string, IRepository, DataGridColumn>>),然后遍历该元素以查找现有属性。

由于迭代继承链上的属性以查找特定类型的属性需要大量工作,因此迭代一次以创建属性列表更有意义,然后对其进行迭代并调用适当的函数,如果你在你的字典里找到一个。只有在字典(或属性)用尽后,您才需要拥有if.

map = new Dictionary<Type, Func<string, PropertyInfo, string, IRepository, DataGridColumn>>
{
    { typeof(DbComboBoxAttribute), CreateComboBoxColumn }, // no lambda needed if CreateComboBoxColumn already matches our Func<,,,,> type
    { typeof(DescribedByteEnumComboBoxAttribute), (p, i, h, r) => CreateEnumComboBoxColumn(p, i, h) },
    ...
};

然后像这样使用地图:

public static DataGridColumn CreateAppropriateColumn(string path, PropertyInfo info, string header, IRepository repository)
{
    Func<string, PropertyInfo, string, IRepository, DataGridColumn>
        colfunc = null;

    // iterate over all the attributes, looking for one in our dictionary;
    // use Attribute.GetCustomAttributes because it doesn't ignore 'inherit'
    foreach (var attr in Attribute.GetCustomAttributes(info, true))
        if (map.TryGetValue(attr.GetType(), out colfunc))
            return colfunc(path, info, header, repository);

    if (info.PropertyType == typeof(bool) || info.PropertyType == typeof(bool?))
        return CreateDataGridCheckBoxColumn(path, info, header);

    return CreateTextBoxColumn(path, info, header);
}
于 2013-08-27T06:32:05.043 回答
1

我能想到的最少代码量将类似于 Gabes 的答案,但在映射中带有参数信息。

public static DataGridColumn CreateAppropreateColumn(string path, PropertyInfo info, string header, IRepository repository)
{
    //Dictionary of methods to call. Add in all your different column types here with their respective creation functions
    var columnCreationStrategy = new Dictionary<Type, Func<DataGridColumn>>()
        {
            {typeof(DbComboBoxAttribute), () => CreateComboBoxColumn(path,info,header)},
            {typeof(DescribedByteEnumComboBoxAttribute), () => CreateEnumComboBoxColumn(path,info,header, repository)}
        };

    //Just get all attributes here, then return the first successful match
    var attributeList = info.GetCustomAttributes(true).ToList();
    foreach (var attribute in attributeList)
    {
        var type = attribute.GetType();
        if (columnCreationStrategy.ContainsKey(type))
            return columnCreationStrategy[type].Invoke();
    }
    //Maybe throw some exception here? Depends on how you want to handle it. You could even have a default column generation method here
    return null;
}
于 2013-08-27T06:39:46.013 回答
0

我不确定它会更好,但你会使用三元运算符:

DataGridColumn column = info.GetCustomAttributes(typeof(DbComboBoxAttribute), true).Any()
        ? CreateComboBoxColumn(path, info, header, repository)
    : info.GetCustomAttributes(typeof(DescribedByteEnumComboBoxAttribute), true).Any()
        ? CreateEnumComboBoxColumn(path, info, header)
    : info.GetCustomAttributes(typeof(DropDownLazyLoadingDataGridAttribute), true).Any()
        ? CreateDataGridDropDownLazyLoadingDataGridColumn(path, info, header, repository)
    : info.GetCustomAttributes(typeof(DropDownTreeViewAttribute), true).Any()
    ...
        : CreateTextBoxColumn(path, info, header);

基本形式是

value = condition ? valueIfTrue : valueIfFalse;

它可以被链接:

value = condition ? valueIfTrue : condition2 ? valueIfCond2True : valueIfBothFalse

虽然我听说它说三元运算符是为了混淆可怜的计算机科学学生而发明的。在这种情况下,我不确定它是否更清楚。

于 2013-08-27T06:05:17.720 回答
0

我通常收集所有的东西,然后循环:

    public static DataGridColumn CreateAppropreateColumn(string path, PropertyInfo info, string header, IRepository repository)
    {
        var criteria = new Dictionary<Type, Func<string, PropertyInfo, string, IRepository, DataGridColumn>>();

        criteria.Add(typeof(DbComboBoxAttribute), CreateComboBoxColumn);
        criteria.Add(typeof(DescribedByteEnumComboBoxAttribute)), CreateEnumComboBoxColumn);
        criteria.Add(typeof(DropDownLazyLoadingDataGridAttribute), CreateDataGridDropDownLazyLoadingDataGridColumn);
        // add more here - in the order you desired...            

        // loop through and return out if there is a matched one
        foreach (Type t in criteria.Keys)
        {
            if (info.GetCustomAttributes(t, true).Any())
            {
                return criteria[t].Invoke(path, info, header, repository);
            }
        }

        // Default Return here:
        return CreateTextBoxColumn(path, info, header);
    }

编辑:没有看到 Gabe 的答案,看起来更优雅。

于 2013-08-27T06:37:58.703 回答