我有一个方法,当前将IList作为参数,其中UserBO类似于以下内容:
public class UserBO {
public string Username { get; set; }
public string Password { get; set; }
public string Pin { get; set; }
}
public class SomeClass {
// An example method giving the basic idea of what I need to do
public void WriteUsers(IList<UserBO> users) {
// Do stuff with users
for (var user in users) {
Console.WriteLine(String.Format(User: {0}: {1}, users.Username, Hash(users.Pin)); // Now needs to optionally be users.Password
}
}
private string Hash(string pin) {
return // Hashed Pin
}
}
然后,此方法使用Username / Pin对创建另一个程序使用的XML(我们将使用上述方法作为示例)。
问题是,现在我需要能够生成相同的代码,除了使用密码字段而不是Pin字段(这两个字段都有充分的理由)。
我不想仅仅使用类似的名称创建另一个方法,而是希望重构代码,以便完全从这个类中删除BO特定代码,并使其成为关于使用哪个类/成员的决定不是在方法本身而是在代码调用它。
一种选择是传递IDictionary并使用Linq ToDictionary方法在调用代码中动态创建字典。然而,这将失去物品的排序(这将是好的,但不是必须保持)。我可以使用IList或其他东西,但将IList转换为更难。
有人对如何做到有什么好的建议吗?
P.S。如果有人对如何标题这篇文章有更好的了解,请随意使用它。
答案 0 :(得分:2)
格式化之后,完全您需要对字符串做什么并不清楚。您可以使方法采用IEnumerable<string>
,然后生成调用代码:
WriteUsers(users.Select(user => string.Format("{0}: {1}",
users.Username, users.Pin)));
是否适合您将取决于具体细节。
答案 1 :(得分:2)
你也可以使用表达式:
WriteUsers(IList<T> users, u => u.Username, u => u.Password);
如果您使用的是Net 3.5。
答案 2 :(得分:1)
首先,为了实用性,我建议将IList切换为IEnumerable。如果你没有做任何其他需要列表的逻辑,它会打开你的课程以供更多用户使用,并且没有任何缺点。
如果你想完全取消选择课堂上的内容,我可以考虑几种选择。
一个(尽管可能不太可用)将使用反射。如果是。这不是一个大问题,你可以重构它有类似的东西:
WriteElements(IEnumerable elements,params string [] propertiesToWrite)
然后你可以重构方法,以便它使用反射从T的类型说明符中获取属性,并写出任意数量的属性。然后呼叫者会这样做:
WriteElements(listOfUsers, "Username", "Password");
第二种,可能更干净的选择是重构它:
WriteElements(IEnumerable<UserBO>, Func<UserBO,string>);
然后你可以用:
来调用它// Call using password
WriteElements(listOfUsers, user => user.Password);
// or call using pin
WriteElements(listOfUsers, user => user.Pin);