这是我编写的代码,用于在尝试更新数据库之前检查我的viewmodel中的属性是否为null
var channel = _context.Channels.FirstOrDefault(x => x.Id == viewModel.Id);
if (!string.IsNullOrEmpty(viewModel.Part))
{
channel.Part = viewModel.Part;
}
if (!string.IsNullOrEmpty(viewModel.IndexName))
{
channel.IndexName = viewModel.IndexName;
}
if (viewModel.MeasurementId != null)
{
channel.MeasurementId = viewModel.MeasurementId;
}
if (!string.IsNullOrEmpty(viewModel.Direction))
{
channel.Direction = viewModel.Direction;
}
代码工作正常,但我在这里使用了很多if语句,这对我来说看起来并不真正有效。您是否可以建议我使用其他语法或结构而不是if语句来使我的代码更简洁并且更加“专业”?
答案 0 :(得分:3)
只要您的频道对象的属性除了更改值(即触发事件)之外没有任何副作用,您可以这样做:
string PickNonEmptyOrDefault(string value, string deflt)
{
return String.IsNullOrEmpty(value) ? deflt : value;
}
...
channel.Part = PickNonEmptyOrDefault(viewModel.Part, channel.Part);
channel.IndexName = PickNonEmptyOrDefault(viewModel.IndexName, channel.IndexName);
etc.
顺便说一句,我想知道是否有办法可以做到这一点而不会不小心影响你的财产。诀窍是使用反射并使用PropertyInfo
对象来完成您的工作:
class Foo
{
public string Bar { get; set; }
public string Baz { get; set; }
public override string ToString()
{
return (Bar ?? "") + " " + (Baz ?? "");
}
}
delegate void propsetter(string prop, string value);
private static void SetOnNonEmpty(PropertyInfo pi, Object o, string value)
{
if (pi.PropertyType != typeof(string))
throw new ArgumentException("type mismatch on property");
if (!String.IsNullOrEmpty(value))
pi.SetValue(o, value);
}
static void Main(string[] args)
{
var myObj = new Foo();
myObj.Baz = "nothing";
PropertyInfo piBar = myObj.GetType().GetProperty("Bar");
PropertyInfo piBaz = myObj.GetType().GetProperty("Baz");
SetOnNonEmpty(piBar, myObj, "something");
SetOnNonEmpty(piBaz, myObj, null);
Console.WriteLine(myObj);
}
输出something nothing
老实说,我不建议这样做,因为它并没有真正增加可读性,而且感觉相当粗糙。
我更倾向于编写一大堆代码来反映视图模型的属性,并调用Func<string, string>
来获取数据模型中的相应属性名称,然后返回非null并且属性类型匹配,在视图对象上调用getter并将其传递给数据对象上的setter。
如果我这么做很多次,我只会这样做。
答案 1 :(得分:2)
如果它只是困扰你的if
你可以使用条件运算符:
channel.Part = string.IsNullOrEmpty(viewModel.Part) ?
channel.Part : viewModel.Part;
etc.
当然总是调用set
的{{1}}访问者,除非其中有逻辑(更改跟踪等),否则这样会很好如果在值没有真正改变时被调用,那就太糟糕了。
你也可以将条件运算符重构为一个方法,但是没有其他方法有条件地设置值而不使用Part
。
答案 2 :(得分:2)
您编写的代码绝对没有错。
如果您的目标是较少的代码行,您可以这样做,但我认为这只会增加不必要的复杂性。
channel.Part = string.IsNullOrWhiteSpace(viewModel.Part) ? channel.Part : viewModel.Part;
channel.IndexName = string.IsNullOrWhiteSpace(viewModel.IndexName) ? channel.IndexName: viewModel.IndexName;
channel.MeasurementId = viewModel.MeasurementId == null ? channel.MeasurementId : viewModel.MeasurementId;
channel.Direction = string.IsNullOrWhiteSpace(viewModel.Direction) ? channel.Direction : viewModel.Direction;
注意我已将您的通话从IsNullOrEmpty切换到IsNullOrWhiteSpace
值为“”(一个或多个空格)的字符串将通过您可能不想要的IsNullOrEmpty检查。
你也可以使用coalesce运算符为你的可空类型(但不是空字符串)...
channel.MeasurementId = viewModel.MeasurementId ?? channel.MeasurementId;
答案 3 :(得分:2)
你的代码很好。即使Jon Skeet使用if
语句。
如果您想要性能最佳的代码,请保持这样。如果您想让代码看起来像 pro ,请使用其他人在此处提出的任何建议。我的意见是:保持原样。
答案 4 :(得分:0)
如果这些是字段而不是属性,则可以使用以下内容:
void ReplaceIfNotEmpty(ref string destination, string source)
{
if (!string.IsNullOrEmpty(source))
{
destination = source;
}
}
然后只是
ReplaceIfNotEmpty(ref channel.Part, viewModel.Part);