2009-01-20 73 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