我有一个很长的条件声明:
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吗?
谢谢。
答案 0 :(得分:3)
我经常这样做的一种方法是创建一个字典,将类型映射到创建结果的函数(您的字典将是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);
}
答案 1 :(得分: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;
}
答案 2 :(得分: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
虽然我听说它说三元运算符是为了混淆贫困的comp-sci学生而发明的。在这种情况下,我不确定它是否更清楚。
答案 3 :(得分: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的答案,看起来更优雅。