多态搜索文件系统或程序集嵌入式资源中的文件

时间:2009-01-20 03:16:42

标签: c# polymorphism embedded-resource

我正在学习在C#中使用多态,但无法弄清楚这一点。我正在尝试编写一个允许我从存储库中获取过滤文件列表的类。

存储库可以是文件系统文件夹,也可以是任意已加载程序集中的嵌入资源(但它不是当前正在执行的程序集)。

有什么建议吗?

2 个答案:

答案 0 :(得分: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
}

然后你可以编写你的算法只依赖于这些接口而不是它们的实现。

答案 1 :(得分: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();
        }
    }
}

这是一个粗略的例子,但应该指出正确的方向:)