虽然看一下我正在研究的项目的一些代码,但我遇到了一个非常重要的方法, 以下内容:
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
if (data != null)
{
if (data.A == null)
{
data.A = fieldName;
_dataRepository.InsertOrUpdate(data);
return "A";
}
if (data.B == null)
{
data.B = fieldName;
_dataRepository.InsertOrUpdate(data);
return "B";
}
// keep going data.C through data.Z doing the exact same code
}
}
显然有26个if语句只是为了确定属性是否为null然后更新该属性并进行数据库调用 在实施中可能非常天真。做这个工作单元的更好方法是什么?
答案 0 :(得分:3)
谢天谢地C# is able to inspect and assign class members dynamically,所以一个选项就是创建一个 map 列表并迭代它。
public string DataField(int id, string fieldName)
{
var data = _dataRepository.Find(id);
List<string> props = new List<string>();
props.Add("A");
props.Add("B");
props.Add("C");
if (data != null)
{
Type t = typeof(data).GetType();
foreach (String entry in props) {
PropertyInfo pi = t.GetProperty(entry);
if (pi.GetValue(data) == null) {
pi.SetValue(data, fieldName);
_dataRepository.InsertOrUpdate(data);
return entry;
}
}
}
}
答案 1 :(得分:1)
你可以循环遍历从'A'到'Z'的所有角色。这很难,因为你想用相应的名称访问你的'data'对象的属性,但是(据我所知)这应该可以通过C#反射功能。
当你摆脱连续的if语句时,这仍然不会使你的代码变得更好:P
答案 2 :(得分:1)
使用反射为您的问题提供了一个花哨的linq解决方案:
但正如之前所说的那样:您的数据结构没有经过深思熟虑
public String DataField(int id, string fieldName)
{
var data = new { Z = "test", B="asd"};
Type p = data.GetType();
var value = (from System.Reflection.PropertyInfo fi
in p.GetProperties().OrderBy((fi) => fi.Name)
where fi.Name.Length == 1 && fi.GetValue(data, null) != null
select fi.Name).FirstOrDefault();
return value;
}
ta taaaaaaaaa
就像你得到了财产但更新尚未完成。
答案 3 :(得分:0)
由于您始终先设置最低字母字段并返回,因此您可以在班级中使用跟踪第一个可用字段的其他字段。例如,这可以是整数lowest_alphabet_unset
,您可以在设置数据时更新它。{X}:
初始化:
lowest_alphabet_unset = 0;
在DataField中:
lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {
case 1:
/* A is free */
/* do something */
return 'A';
[...]
case 7:
/* A through F taken */
data.G = fieldName;
_dataRepository.InsertOrUpdate(data);
return 'G';
[...]
}
答案 4 :(得分:0)
var data = _dataRepository.Find(id);
如果可能,您应该使用另一个没有这26个属性的DataType。新的DataType应该有1个属性,而Find方法应该返回该新DataType的实例;那么,如果以更自然的方式,你可以摆脱26。
要返回“A”,“B”......“Z”,您可以使用:
return (char)65; //In this example this si an "A"
使用从data.Value到65到90之间的数字(A到Z)的转换。
答案 5 :(得分:-1)
<强> N.B。 - 如果数据是对象而不是结构,请不要使用。
我想到的是,如果A-Z都是相同的类型,那么理论上你可以直接访问内存以检查非空值。
start = &data;
for (i = 0; i < 26; i++){
if ((typeof_elem) *(start + sizeof(elem)*i) != null){
*(start + sizeof(elem)*i) = fieldName;
return (char) (65 + i);
}
}
没有经过测试,但提出了一个想法;)