如何让这个课程更可重复使用? (里面的具体例子)

时间:2009-03-09 16:09:07

标签: c# .net refactoring

我有一个方法,当前将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。如果有人对如何标题这篇文章有更好的了解,请随意使用它。

3 个答案:

答案 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);