C# 正在使用大型switch语句将数据分配给属性。。。有没有一种更具活力的方式来做到这一点?
因此,我从数据库中提取一些信息,并需要将其映射到模型的属性。我的第一次尝试产生了一个大型switch语句,它遵循一个明显的模式。我想知道这个脆弱的代码是否可以用更动态的方式表达C# 正在使用大型switch语句将数据分配给属性。。。有没有一种更具活力的方式来做到这一点?,c#,reflection,refactoring,C#,Reflection,Refactoring,因此,我从数据库中提取一些信息,并需要将其映射到模型的属性。我的第一次尝试产生了一个大型switch语句,它遵循一个明显的模式。我想知道这个脆弱的代码是否可以用更动态的方式表达 foreach (AttributeValue attributeValue in attributeValues) { string label = attributes.First(a => a.ID == attributeValue.AttributeID).Name; switch (at
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;
}
}
基本上,我的想法是“将标签映射到具有标签值的属性+“标签”您可以通过反射来实现:
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);
}
您可以将标签存储在字典中,并通过相应的键检索所需的标签。这可以看作是战略模式的一个非常简单的实现
var labels=newdictionary();
标签。添加(“TaskSequence”,TaskSequenceLabel);
标签。添加(“TaskStatus”,TaskStatusLabel);
//等等。
AttributeValue.ForEach(值=>{
字符串标签=attributes.First(a=>a.ID==value.AttributeID).Name;
标签[value.AttributeName]=标签;
});
如果您在多个地方需要它,您可以将其重构为自己的类:
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;
});
公共类MyLabel
{
公共词典标签=
新字典();
公共MyLabels(){
_标签。添加(“TaskSequence”,TaskSequenceLabel);
_标签。添加(“TaskStatus”,TaskStatusLabel);
//等等。
}
名为的公共标签(字符串名称){
返回标签[名称];
}
}
//用法:
var labels=新的MyLabels();
AttributeValue.ForEach(值=>{
字符串标签=attributes.First(a=>a.ID==value.AttributeID).Name;
labels.Named(value.AttributeName)=标签;
});
一个仅反射的解决方案当然可以做到这一点
但是,我会评估自定义属性的使用,您可以使用它装饰感兴趣的成员。可以用来指定当前打开的属性名称的内容
对我来说,这是一个比只使用反射更健壮的解决方案,因为它独立于TaskSequence
->TaskSequenceLabel
基于约定的映射
如果采用仅反射的方法,如果有人更改了TaskSequence
的名称,那么弄清楚事情为什么不再起作用可能比必要的更困难。然而,如果你有一个属性,你根本不在乎。当然,如果数据库中字段的名称发生更改,您会很在意
编辑
让我添加一些代码来澄清(实际上是伪代码,我这里没有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
和friends.您不使用类似于NHibernate
或实体框架的东西有什么原因吗?我们部分使用NHibernate。它用于新代码,但不幸的是,在我们项目的某些领域,我仍然需要处理技术债务。
// 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))