我有3/4个不同的模型,每个模型都包含自己的嵌套模型。我需要一种迭代所有字段的方法,包括嵌套模型的字段并进行字符串替换(尽管并非所有字段都是字符串)。
我最初的想法是编写一种方法,允许动态的'要传递的类型。
输入型号:
Name = Joe
Surname = Smith
Address = new ClientAddress
{
Line1: Item A
Line2: mistake
Line3: mistake
}
我的示例方法:
MyMethod (dynamic passInModel)
{
....
passInModel.Replace("mistake","correction");
return passInModel;
}
输出:
Name = Joe
Surname = Smith
Address = new ClientAddress
{
Line1: Item A
Line2: correction
Line3: correction
}
尽管尝试了各种方法,但我没有成功地写出能够完成工作的东西。
答案 0 :(得分:1)
您可以编写一个接受object
并使用反射来迭代所有字段的方法,但是您会在那里进入凌乱的领域。在我看来,即使在这里使用dynamic
也很麻烦。
请考虑在此处使用修改后的visitor pattern。如果您的域对象如下所示:
public class ModelBase
{
}
public class MyModel1 : ModelBase
{
public string Name { get; set; }
public string Surname { get; set; }
public ClientAddress Address { get; set; }
}
public class MyModel2 : ModelBase
{
public string CompanyName { get; set; }
public string Region { get; set; }
public CompanyAddress Address { get; set; }
}
public class ClientAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}
public class CompanyAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public List<string> AdditionalLines { get; set; }
}
撰写一个抽象ModelBase
的访问者并发送正确的类型安全访问者:
public class ModelFixVisitor
{
public ModelBase Visit(ModelBase model)
{
var asModel1 = model as MyModel1;
if (asModel1 != null)
{
return new Model1FixVisitor().Visit(asModel1);
}
var asModel2 = model as MyModel2;
if (asModel2 != null)
{
return new Model2FixVisitor().Visit(asModel2);
}
throw new NotImplementedException("Unknown model type.");
}
}
然后为您需要访问的每种类型(和子类型)编写一个简单的类:
public class Model1FixVisitor
{
public MyModel1 Visit(MyModel1 model)
{
model.Name = new StringFixVisitor().Visit(model.Name);
model.Surname = new StringFixVisitor().Visit(model.Surname);
model.Address = new ClientAddressFixVisitor().Visit(model.Address);
return model;
}
}
public class Model2FixVisitor
{
public MyModel2 Visit(MyModel2 model)
{
model.CompanyName = new StringFixVisitor().Visit(model.CompanyName);
model.Region = new StringFixVisitor().Visit(model.Region);
model.Address = new CompanyAddressFixVisitor().Visit(model.Address);
return model;
}
}
public class ClientAddressFixVisitor
{
public ClientAddress Visit(ClientAddress address)
{
address.Line1 = new StringFixVisitor().Visit(address.Line1);
address.Line2 = new StringFixVisitor().Visit(address.Line2);
address.Line3 = new StringFixVisitor().Visit(address.Line3);
return address;
}
}
public class CompanyAddressFixVisitor
{
public CompanyAddress Visit(CompanyAddress address)
{
address.Line1 = new StringFixVisitor().Visit(address.Line1);
address.Line2 = new StringFixVisitor().Visit(address.Line2);
address.AdditionalLines = new StringListFixVisitor().Visit(address.AdditionalLines);
return address;
}
}
public class StringFixVisitor
{
public string Visit(string element)
{
return element.Replace("mistake", "correction");
}
}
public class StringListFixVisitor
{
public List<string> Visit(List<string> elements)
{
return elements
.Select(x => new StringFixVisitor().Visit(x))
.ToList();
}
}
我确信代码可以重构和优化,但它应该表达一般的想法。
我喜欢这种类型的解决方案,它将问题分解为小的,可管理的块:如何修复string
?如何修复ClientAddress
?
修复整个模型然后变成这些较小类的简单组合。它有点冗长,但你要保持类型安全,不要乱用反射。
答案 1 :(得分:1)
你可以使用.Net反射的力量来解决这个问题。
我创建了一个名为DeepStringReplacer的类。使用反射它会遍历对象属性,如果类型是字符串,则执行字符串替换。
检查以下代码:
public class DeepStringReplacer
{
public object Replace(object input, string oldValue, string newValue)
{
if (input is string)
{
return input.ToString().Replace(oldValue, newValue);
}
var fields = input.GetType().GetProperties();
foreach (var field in fields)
{
var fieldValue = field.GetValue(input);
field.SetValue(input, Replace(fieldValue, oldValue, newValue));
}
return input;
}
}
public class Person
{
public string Name { get; set; }
public string Surname { get; set; }
public ClientAddress Address { get; set; }
}
public class ClientAddress
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}