重构某种泛型方法

本文关键字:泛型方法 重构 | 更新日期: 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");

在使用该方法之前,我必须再次转换该方法的返回类型

重构某种泛型方法

只写两个方法:getFileContentAsStringgetFileContentAsList。如果您只能支持两种类型,那么您在这里就无法获得泛型的任何好处。

如果你想要有任意数量的返回类型,你可以使用策略模式。

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();
        }
    }

我确信这是容易出错的,因为我有它,但想法是传递一个转换器函数,将处理任何类型你想返回。

假设:

  1. 只读,转发访问是所有需要从列表;和
  2. 希望在应用程序代码中以相同的方式处理两种可能性的结果。

那么下面的语句就可以了:

  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分配存储空间;每个文本行都由迭代器读取并返回。