2009-01-20 78 views
0

我正在學習在C#中使用多態,但無法弄清楚這一點。我正在嘗試編寫一個允許我從存儲庫中獲取文件過濾列表的類。多態搜索文件系統或彙編嵌入式資源中的文件

存儲庫可以是文件系統文件夾或任意已加載程序集中的嵌入式資源(但不是當前正在執行的程序集)。

有什麼建議嗎?

回答

3

您可以定義對接口這樣的:

public interface IReadableFile 
{ 
    Stream OpenRead(); 
} 

public interface IRepository 
{ 
    IEnumerable<IReadableFile> Search(string pattern); 
} 

,並讓他們的兩種不同的實現:

public class FolderFile : IReadableFile 
{ 
    readonly private string _name; 

    public FolderFile(string name) 
    { 
     _name = name; 
    } 

    #region IFile Members 

    public Stream OpenRead() 
    { 
     return File.OpenRead(_name); 
    } 

    #endregion 
} 

public class FolderRepository : IRepository 
{ 
    readonly private string _directory; 

    public FolderRepository(string directory) 
    { 
     _directory = directory; 
    } 

    #region IRepository Members 

    public IEnumerable<IReadableFile> Search(string pattern) 
    { 
     return Array.ConvertAll(Directory.GetFiles(_directory, pattern), name => new FolderFile(name)); 
    } 

    #endregion 
} 

public class AssemblyFile : IReadableFile 
{ 
    readonly private Assembly _assembly; 
    readonly private string _name; 

    public AssemblyFile(Assembly assembly, string name) 
    { 
     _assembly = assembly; 
     _name = name; 
    } 

    #region IReadableFile Members 

    public Stream OpenRead() 
    { 
     return _assembly.GetManifestResourceStream(_name); 
    } 

    #endregion 
} 

public class AssemblyRepository : IRepository 
{ 
    readonly private Assembly _assembly; 

    public AssemblyRepository(Assembly assembly) 
    { 
     _assembly = assembly; 
    } 

    #region IRepository Members 

    public IEnumerable<IReadableFile> Search(string pattern) 
    { 
     return _assembly.GetManifestResourceNames().Where(name => name.Contains(pattern)).Select(name => new AssemblyFile(_assembly, name)).ToArray(); 
    } 

    #endregion 
} 

然後你可以寫你的算法只依賴於這些接口而不是他們的實現。

0
using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.IO; 

namespace Reposes 
{ 
    class ReposeFile 
    { 
     string m_name; 

     public string Name 
     { 
      get { return m_name; } 
     } 

     public ReposeFile(string name) 
     { 
      m_name = name; 
     } 
    } 

    interface IRepose 
    { 
     void RetriveFiles(); 
     ReposeFile[] Files { get; } 
    } 

    class FileSystemRepose : IRepose 
    { 
     string m_path = null; 
     List<ReposeFile> m_files = new List<ReposeFile>(); 

     public FileSystemRepose(string path) 
     { 
      m_path = path; 
     } 

     #region IRepose Members 

     public void RetriveFiles() 
     { 
      string[] files = Directory.GetFiles(m_path); 
      foreach (string file in files) 
      { 
       m_files.Add(new ReposeFile(file)); 
      } 
     } 

     public ReposeFile[] Files 
     { 
      get { return m_files.ToArray(); } 
     } 

     #endregion 
    } 

    class AssemblyRepose : IRepose 
    { 
     string m_assembly = null; 
     List<ReposeFile> m_files = new List<ReposeFile>(); 

     public AssemblyRepose(string assembly) 
     { 
      m_assembly = assembly; 
     } 

     #region IRepose Members 

     public void RetriveFiles() 
     { 
      m_files.Add(new ReposeFile("Stuff")); 
     } 

     public ReposeFile[] Files 
     { 
      get { return m_files.ToArray(); } 
     } 

     #endregion 
    } 

    class Consumer 
    { 
     static void Main() 
     { 
      List<IRepose> reps = new List<IRepose>(); 
      reps.Add(new FileSystemRepose("c:\\")); // would normally be @"c:\" but stackoverflow's syntax highlighter barfed :) 
      reps.Add(new AssemblyRepose("rep.dll")); 

      foreach (IRepose rep in reps) 
      { 
       rep.RetriveFiles(); 

       foreach (ReposeFile file in rep.Files) 
       { 
        Console.WriteLine(file.Name); 
       } 
      } 

      Console.ReadKey(); 
     } 
    } 
} 

這是一個粗糙的例子,但應該指向你在正確的方向:)

+0

尼爾森,我明白你的代碼。但是它並沒有解決困難的部分:我如何從傳遞一個字符串到具有可以調用方法的Assembly對象?如何避免在每次調用時加載該程序集,如果它已經加載? – 2009-01-20 03:47:51