我正在尝试重构一个由多个具有不同条件的if语句组成的方法。 该方法如下所示:
private void DeserializeProperty(object value,
PropertyInfo property, Format format) {
if (value == DBNull.Value || value == null) {
property.SetValue(this, null);
return;
}
if (property.PropertyType == typeof(Id)) {
SetIdProperty(value, property);
return;
}
if (property.PropertyType.BaseType == typeof(BaseProperty)) {
SetBaseProperty(value, property);
return;
}
if (property.PropertyType == typeof(Data)) {
DeserializeData(value, property, format);
return;
}
DeserializeNormalProperty(property, value);
}
用multiorphism替换这些If语句将不起作用(不确定如果它能起作用是否明智)因为条件涉及PropertyType
使用类型为Dictionery<Type,Action<object, PropertyInfo>>
的词典替换它们将不起作用
DeserializeData(value, property, format);
不适合行动
此外,上述任何解决方案都不会处理value == DBNull.Value || value == null
条件
我该如何解决这个问题?
答案 0 :(得分:1)
只是一个快速警告 - 以下都不是重构,只是重写你已有的方法。鉴于条件的可变性及其强加的排序(例如基本属性的基本类型优先于数据),很难想象比if-else更好或更清楚的东西。 IMO通过重构一个函数,你无法真正改善你所拥有的东西。但无论如何,我会提出一些可能的重写,以防上诉。
注意:根据一些编码指南,这不如您已有的优先。就个人而言,我觉得它更具可读性。
private void DeserializeProperty(object value,
PropertyInfo property, Format format) {
if (value == DBNull.Value || value == null) {
property.SetValue(this, null);
}
else if (property.PropertyType == typeof(Id)) {
SetIdProperty(value, property);
}
else if (property.PropertyType.BaseType == typeof(BaseProperty)) {
SetBaseProperty(value, property);
}
else if (property.PropertyType == typeof(Data)) {
DeserializeData(value, property, format);
}
else {
DeserializeNormalProperty(property, value);
}
}
如果您正在使用类似于此的自定义CleverSwitch
类来执行大量类似的切换:
https://stackoverflow.com/a/299120/3940783
可能适合你。它与你对动作词典的想法非常相似 - 但是由于你的条件的变化,让动作没有输入是最干净的,只使用DeserializeProperty范围内的变量而不将它们传递给动作
因此,例如,您可以使用以下内容替换该函数:
private void DeserializeProperty(object value,
PropertyInfo property, Format format) {
CleverSwitch.Do(
CleverSwitch.If(() => value == DBNull.Value || value == null, () => property.SetValue(this, null))
CleverSwitch.IsType<Id>(property.PropertyType, () => SetIdProperty(value, property)),
CleverSwitch.IsType<BaseProperty>(property.PropertyType.BaseType, () => SetBaseProperty(value, property)),
CleverSwitch.IsType<Data>(property.PropertyType, () => DeserializeData(value, property, format)),
CleverSwitch.Default(() => DeserializeNormalProperty(property,value))
);
}
CleverSwitch在上述链接上的工作方式与JaredPar的TypeSwitch类似 - 可编码如下:
static class CleverSwitch {
public class CaseInfo {
public Func<bool> Condition { get; set; }
public Action Action { get; set; }
}
public static void Do(object source, params CaseInfo[] cases) {
var type = source.GetType();
foreach (var entry in cases) {
if (entry.Condition()) {
entry.Action();
break;
}
}
}
public static CaseInfo IsType<T>(Type T2, Action action) {
return new CaseInfo() { Condition = () => T2 == typeof(T), Action = action };
}
public static CaseInfo If(Func<bool> condition, Action action) {
return new CaseInfo() { Condition = condition, Action = action };
}
public static CaseInfo Default(Action action) {
return new CaseInfo() { Condition = () => true, Action = action };
}
}
在这种情况下,任何帮助你以字典方式重构它的类都必须是相当普遍的,所以基本上只是混淆并增加性能开销。 因此,虽然上面的代码应该可行,但实际上我无法看到它在以下任何方面的if语句中如何改进:
事实上,我认为简单的if,return或if,else组合更具可读性,可维护性且更容易直接写出......但这只是我的两分钱!