所以我从数据库中提取一些信息,我需要将它映射到我的模型的属性。我对此的第一次尝试产生了一个大的switch语句,它遵循一个明显的模式。我想知道这个脆弱的代码是否能以更动态的方式表达。
foreach (AttributeValue attributeValue in attributeValues)
{
string label = attributes.First(a => a.ID == attributeValue.AttributeID).Name;
switch (attributeValue.AttributeName)
{
case "TaskSequence":
TaskSequenceLabel = label;
break;
case "TaskStatus":
TaskStatusLabel = label;
break;
case "InstallChangeNumber":
InstallChangeNumberLabel = label;
break;
case "InstallChangeStart":
InstallChangeStartLabel = label;
break;
case "InstallChangeEnd":
InstallChangeEndLabel = label;
break;
case "SubmittedDateTime":
SubmittedDateTimeLabel = label;
break;
case "InstalledDateTime":
InstalledDateTimeLabel = label;
break;
}
}
基本上我的想法是“将标签映射到标签值为+”的标签“”
答案 0 :(得分:2)
你可以用反射来做到这一点:
foreach (AttributeValue attributeValue in attributeValues)
{
string label = attributes.First(a => a.ID == attributeValue.AttributeID).Name;
string propertyName = attributeValue.AttributeName + "Label";
PropertyInfo pi = GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
// check for null, if it is possible that property not exists
pi.SetValue(this, label, null);
}
答案 1 :(得分:2)
您可以将标签存储在字典中,并通过相应的密钥检索所需的标签。这可以被视为策略模式的一个非常简单的实现。
var labels = new Dictionary<string, Label>();
labels.Add("TaskSequence", TaskSequenceLabel);
labels.Add("TaskStatus", TaskStatusLabel);
// etc.
attributeValues.ForEach(value => {
string label = attributes.First(a => a.ID == value.AttributeID).Name;
labels[value.AttributeName] = label;
});
如果你需要在多个地方,你可以将它重构为自己的类:
public class MyLabels
{
public Dictionary<string, Label> _labels =
new Dictionary<string< Label>();
public MyLabels() {
_labels.Add("TaskSequence", TaskSequenceLabel);
_labels.Add("TaskStatus", TaskStatusLabel);
// etc.
}
public Label Named(string name) {
return _labels[name];
}
}
// Usage:
var labels = new MyLabels();
attributeValues.ForEach(value => {
string label = attributes.First(a => a.ID == value.AttributeID).Name;
labels.Named(value.AttributeName) = label;
});
答案 2 :(得分:2)
只有反射的解决方案当然可以解决问题。
但是,我会评估使用自定义属性来装饰感兴趣的成员。您可以用来指定当前正在启用的属性名称的东西。
对我而言,看起来比仅使用反射更强大的解决方案,因为它独立于TaskSequence
- &gt; TaskSequenceLabel
基于约定的映射。
使用仅反射方法,如果有人更改TaskSequence
的名称,找出原因不再有效的原因可能比必要时更难。但是,如果你有一个属性,你根本就不在乎。当然,如果db中字段的名称发生了变化,你做。
修改
让我添加一些代码来澄清(实际上是伪代码,我这里没有Visual Studio的副本)。 我会假设你要填充它的属性。
// here's the custom attribute. Ok, should probably be sealed and bla bla bla.
public class MapToAttribute : Attribute {
readonly string _fieldName;
public MapToAttribute(string fieldName) {
_fieldName = fieldName;
}
}
// here's your model
public class SomeModel {
[MapTo("TaskSequence")]
public int TaskSequence { get; set; }
}
// here's how you figure out which property have the MapTo attribute
from p in typeof(SomeModel).GetProperties() where p.IsDefined(typeof(MapToAttribute))
其余部分留给读者练习。 PropertyInfo.SetValue
和朋友们。