重构某种泛型方法
本文关键字:泛型方法 重构 | 更新日期: 2023-09-27 18:04:47
我一遍又一遍地使用我的某种方法。因此,我倾向于将这个类导入到我所有的项目中,在这些项目中我必须访问Windows Phone-Device的IsolatedStorage。
但是,它对我来说并不优雅。看一下:
public static Object getFileContent (String filename, String returntype)
{
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
Object returnobj = new Object();
List<String> list = new List<String>();
String r;
IsolatedStorageFileStream fileStream = isf.OpenFile(filename, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fileStream);
if (returntype.Equals("list"))
{
while ((r = reader.ReadLine()) != null)
{
list.Add(r);
}
returnobj = list;
}
else if (returntype.Equals("string"))
{
r = reader.ReadLine();
returnobj = r;
}
fileStream.Close();
reader.Close();
return returnobj;
}
我的主要问题是参数returntype
。它显然是一个字符串。我想把它直接设为型号。但这在我最后一次尝试中不起作用。
同样,当我使用这个方法时,例如:
string random = (string) MyFavClass.getFileContent("randomFile","string");
在使用该方法之前,我必须再次转换该方法的返回类型
只写两个方法:getFileContentAsString
和getFileContentAsList
。如果您只能支持两种类型,那么您在这里就无法获得泛型的任何好处。
如果你想要有任意数量的返回类型,你可以使用策略模式。
public static T GetFileContents<T>(String filename, Func<StreamReader, T> readMethod)
{
// initialize stuff
using (StreamReader reader = new StreamReader(...))
{
return readMethod(reader);
}
}
public static string ReadStreamAsString(StreamReader reader)
{
return reader.ReadLine();
}
public static List<string> ReadStreamAsList(StreamReader reader)
{
var list = new List<string>();
while ((r = reader.ReadLine()) != null)
{
list.Add(r);
}
return list;
}
使用它:
string myString = GetFileContents("foo.txt", ReadStreamAsString);
List<string> myList = GetFileContents("bar.xml", ReadStreamAsList);
我的泛型可能是关闭的,但希望它传达了正确的想法。
未经测试,但我会尝试这样做:
public static T getFileContent (String filename, Func<StreamReader, T> process)
{
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
Object returnobj = new Object();
List<String> list = new List<String>();
String r;
IsolatedStorageFileStream fileStream = isf.OpenFile(filename, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fileStream);
try{
return process(reader);
}
finally{
fileStream.Close();
reader.Close();
}
}
我确信这是容易出错的,因为我有它,但想法是传递一个转换器函数,将处理任何类型你想返回。
假设:
- 只读,转发访问是所有需要从列表;和
- 希望在应用程序代码中以相同的方式处理两种可能性的结果。
那么下面的语句就可以了:
public abstract class MySequence : IEnumerable<string> {
protected string Filename { get; private set; }
public MySequence(string filename) {
Filename = filename;
}
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
public IEnumerator<string> GetEnumerator() {
using (var isf = IsolatedStorageFile.GetUserStoreForApplication())
using (var stream = isf.OpenFile(Filename, FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream)) {
return GetEnumerator(reader);
}
}
protected abstract IEnumerator<string> GetEnumerator(StreamReader reader);
}
public class MyListSequence : MySequence, IEnumerable<string> {
public MyListSequence(string filename) : base(filename) {}
protected override IEnumerator<string> GetEnumerator(StreamReader reader) {
while (! reader.EndOfStream) yield return reader.ReadLine();
}
}
public class MyStringSequence : MySequence, IEnumerable<string> {
public MyStringSequence(string filename) : base(filename) {}
protected override IEnumerator<string> GetEnumerator(StreamReader reader) {
yield return reader.ReadLine();
}
}
的用法如下:
foreach (var s in (new MyListSequence("fred"))) { Console.WriteLine(s); }
foreach (var s in (new MyStringSequence("fred"))) { Console.WriteLine(s); }
这种机制的一个特别的优点是,当它被应用时,不需要为List分配存储空间;每个文本行都由迭代器读取并返回。