简体   繁体   English

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

[英]How do I make this class more reusable? (specific example inside)

I've got a method which currently takes an IList as a parameter, where UserBO is similar to the following:我有一个当前将 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
    }
}

This method then uses the Username/Pin pairs to create some XML used by another program (we'll use the above method as an example).然后,此方法使用用户名/Pin 对创建一些 XML 供另一个程序使用(我们将以上述方法为例)。

The thing is, now I need to be able to produce the same code except using the Password field instead of the Pin field (there's a good reason for having both fields).问题是,现在我需要能够生成相同的代码,除了使用 Password 字段而不是 Pin 字段(有两个字段的充分理由)。

Instead of just creating another method with a similar name, I'd prefer to refactor the code so as to remove the BO specific code from this class entirely, and make it so that the decision about what class/members to use are made not in the method itself but the code calling it.我宁愿重构代码,以便完全从此 class 中删除 BO 特定代码,而不是仅仅创建另一个具有相似名称的方法,并做出关于使用哪些类/成员的决定不在方法本身,但调用它的代码。

One option would be to pass an IDictionary and use the Linq ToDictionary method to create a dictionary on the fly in the calling code.一种选择是传递一个 IDictionary 并使用 Linq ToDictionary 方法在调用代码中动态创建字典。 This would however lose the ordering of the items (which would be nice but not essential to keep).但是,这会丢失物品的顺序(这很好但不是必须保留)。 I could use an IList or something, but that would be more difficult to convert the IList into.我可以使用 IList 或其他东西,但是将 IList 转换为更困难。

Does anybody have any good suggestions of how to do this?有人对如何做到这一点有任何好的建议吗?

PS If anybody has a better idea of how to title this post, feel free to have a go at it. PS 如果有人对如何为这篇文章命名有更好的想法,请随时在上面写一个 go。

It's not clear exactly what you need to do with the strings after formatting.目前尚不清楚格式化后需要对字符串做什么。 You could make the method take an IEnumerable<string> , and then make the calling code:您可以使该方法采用IEnumerable<string> ,然后进行调用代码:

WriteUsers(users.Select(user => string.Format("{0}: {1}", 
                                              users.Username, users.Pin)));

Whether that works for you or not will depend on the details.这是否适合您将取决于细节。

You could also use Expressions:您还可以使用表达式:

 WriteUsers(IList<T> users, u => u.Username, u => u.Password);

if you're using Net 3.5.如果您使用的是 Net 3.5。

First off, for usability, I recommend switching your IList to an IEnumerable.首先,为了可用性,我建议将您的 IList 切换为 IEnumerable。 Provided you're not doing any other logic that requires the list, it opens up your class to being usable by more users, and has no downside.如果您不执行任何需要列表的其他逻辑,它会打开您的 class 以供更多用户使用,并且没有缺点。

If you want to completely eliminate the selection of what is being printed from your class, I can think of a couple of options.如果您想完全消除从 class 打印的内容的选择,我可以想到几个选项。

One (although potentially less usable) would be to use reflection.一种(尽管可能不太有用)是使用反射。 If perf.如果性能。 isn't a huge issue, you could refactor it to have something like:不是一个大问题,您可以将其重构为:

WriteElements(IEnumerable elements, params string[] propertiesToWrite) WriteElements(IEnumerable 元素,参数 string[] propertiesToWrite)

Then you could just refactor the method so that it uses reflection to get the properties from the type specifier for T, and write out any number of them.然后,您可以重构该方法,以便它使用反射从 T 的类型说明符中获取属性,并写出任意数量的属性。 The caller would then do:然后调用者会这样做:

WriteElements(listOfUsers, "Username", "Password");

A second, probably cleaner, option would be to refactor it to take:第二个可能更清洁的选择是重构它以采取:

WriteElements(IEnumerable<UserBO>, Func<UserBO,string>);

You could then call it with:然后你可以调用它:

// Call using password
WriteElements(listOfUsers, user => user.Password);

// or call using pin
WriteElements(listOfUsers, user => user.Pin);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM