基于条件的类型创建对象

时间:2014-07-29 06:31:05

标签: c# dependency-injection inversion-of-control

我面临一个独特的问题。我们的应用程序中有一个下载功能,我们有一个下拉列表,其中包含用户需要下载的文件类型,即pdf,csv或excel

为了实现这个问题,我们创建了一个接口IFileDownaload和三个不同的类clsCSV,ClsPDF和clsExcel,它们由IFileDownaload实现

现在我的问题是如何根据Dropdown值启动一个类,因为我不想写下if-else语句

if(option ==" pdf")type

因为将来如果我们引入新的文件下载类型,那么它将影响我们重新编写整个逻辑

任何建议

2 个答案:

答案 0 :(得分:1)

您可以为您拥有的每个班级定义缩写,以便您拥有以下内容:

public interface IFileDownload
{
    string Abbreviation { get; }
}

public class PDFDonwload : IFileDownload
{
    public string Abbreviation { get; private set; }
}

然后你可以制作一些类,即工厂,它拥有你拥有的所有文件下载程序的实例,并通过它们的缩写迭代,直到找到合适的类。它可以像这样实现:

public static class DownloadHander
    {

    private static List<IFileDownload> _handlers; 
    static DownloadHander()
    {
        _handlers = new List<IFileDownload>();
    }

    public static void Initialize()
    {
        _handlers.Add(new PDFDonwload());
    }

    public static Stream HandleDownload(string abbreviation)
    {
        foreach (var fileDownload in _handlers)
        {
            if (fileDownload.Abbreviation == abbreviation)
            {
                //and here you make a stream for client
            }
        }
        throw new Exception("No Handler");
    }
}

答案 1 :(得分:1)

当我有许多实现某种类型的类而这些类是无状态services而不是entities时,我使用的是Registry而不是Factory

您的注册表中包含所有IFileDownload实例类的实例:

public class FileDownloaderRegistry
{
    private readonly IFileDownload[] _downloaders;

    public FileDownloaderRegistry(IFileDownload[] downloaders)
    {
        _downloaders = downloaders;
    }
}

然后,您在IFileDownload上有一个属性,表示下载程序处理的文件类型:

public interface IFileDownload
{
    string FileType { get; }
    // etc.
}

最后,您的注册表中的方法采用文件类型并将工作委托给相应的下载程序:

public string DownloadFile(string fileName, string fileType)
{
    var handlingDownloader = _downloaders
        .FirstOrDefault(d => d.FileType == fileType);

    if (handlingDownloader == null) 
    {
        // Probably throw an Exception
    }

    return handlingDownloader.Download(fileName);
}

DI容器通常会隐式理解数组,因此只需注册各种IFileDownload s就应该在注入到Registry的构造函数中的数组中使用它们。使用StructureMap的例如

For<IFileDownload>().Use<ClsCSV>();
For<IFileDownload>().Use<ClsPDF>();
For<IFileDownload>().Use<ClsExcel>();

添加新的IFileDownload是一个问题,用你的DI容器编写课程和adding it to the set of IFileDownloads registered。您还可以让容器管理每个对象的生命周期(如果它们是无状态的),它们只在每个对象首次需要时进行实例化。