Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何设计一个包含大量IF';s或Switch语句_C# - Fatal编程技术网

C# 如何设计一个包含大量IF';s或Switch语句

C# 如何设计一个包含大量IF';s或Switch语句,c#,C#,如何使此类的设计更具动态性,以便根据需要添加新的扩展和类型 public class Processor { public Processor(string fileName) { string extension = Path.GetExtension(fileName); if(extension == "jpg" || extension == "gif" || extension == "png") {

如何使此类的设计更具动态性,以便根据需要添加新的扩展和类型

public class Processor
{
    public Processor(string fileName)
    {
        string extension = Path.GetExtension(fileName);
        if(extension == "jpg" || extension == "gif" || extension == "png")
        {
            //Process Image file type
        } 
        else if(extension == "xls" || extension == "xlsx")
        {
            //Process spreadsheet type
        }
        else if(extension == "doc" || extension == "docx")
        {
            //Process document file type
        }       
        //and so forth ...
    }   
}
我们将来可能需要处理.tiff文件,或者我们可能需要处理视频文件,这意味着一个新的if分支

else if(extension == "avi" || extension == "mp4")
{
    //Process video file type
}
正如你所见,这可能会持续很长时间

有效的文件类型和组存储在数据库中

有人能推荐一些模式或聪明的想法来解决这个问题吗?
干杯

对于这个特殊的案例,我会构建如下内容

List<string> excelExtensions = new List<string>(){ "xls", "xlsx" };
List<string> wordExtensions = new List<string>(){ "doc", "docx" };

if(excelExtensions.Contains(extension))
{
}

if(wordExtensions.Contains(extension))
{
}
listextensions=newlist(){“xls”,“xlsx”};
List wordExtensions=newlist(){“doc”,“docx”};
if(excelExtensions.Contains(扩展))
{
}
if(wordExtensions.Contains(扩展名))
{
}
等等?

使用字典

Dictionary<string, IFileHandler> fileHandlers = new Dictionary<string, IFileHandler>
{
    { "jpg", imageHander },
    { "gif", imageHander },
    { "xls", spreadsheetHander },
    // ...
};

有效的文件类型和组存储在数据库中


然后,您可能希望查询数据库以从扩展名中获取正确的组,并将该组用作字典键而不是扩展名。

一种方法可能是构建一个表(列表),其中每个项都包含扩展名以及有关如何使用该扩展名的信息

然后可以编写一个简单的循环,与表中的每个扩展进行比较


如果您对每个扩展所做的工作很复杂,并且无法在简单的表中定义,那么您可以改为包含一个委托。当循环找到匹配的扩展名时,它可以调用相应的委托来处理该名称。

如果出于您陈述的原因(主要是必须返回并添加代码分支),这种结构通常是一件坏事

我将把它实现为一个字典,键入文件扩展名字符串,并包含方法委托作为值。如果设计得当,这将允许您在不影响旧代码的情况下添加新的扩展,因为新代码将位于一个完全不同的方法中,甚至可以位于具有此逻辑的类之外。然后,只需通过文件扩展名查找要调用的适当委托

基本示例:

//Put this in your class somewhere
public readonly Dictionary<string, Action<FileInfo>> fileHandlers = new Dictionary<string, Action<FileInfo>>();

...

//depending on the dictionary's visibility, you can add these from pretty much anywhere
fileHandlers.Add("xls", ProcessExcelFile);
fileHandlers.Add("xlsx", ProcessExcelFile);
fileHandlers.Add("jpg", ProcessImageFile);

...

//Then all you have to do to invoke the logic is...
fileHandlers[extension](fileInfo);
//把它放在你的类中的某个地方
public readonly Dictionary fileHandlers=new Dictionary();
...
//根据字典的可见性,您几乎可以在任何地方添加这些内容
添加(“xls”,ProcessExcelFile);
添加(“xlsx”,ProcessExcelFile);
添加(“jpg”,ProcessImageFile);
...
//那么你所要做的就是调用逻辑。。。
fileHandlers[扩展](fileInfo);

我建议为您的各种文件处理器提供一个接口,以实现:

public interface IFileProcessor
{
    void Process(string fileName);
    IEnumerable<string> FileExtensions {get;}
}
公共接口IFileProcessor { 作废进程(字符串文件名); IEnumerable文件扩展名{get;} } 然后使用工厂为特定文件名获取适当的处理器。像其他回答者一样,我建议您使用字典来保持处理器及其文件名的映射。本例使用反射来注册它在加载的程序集中找到的每个文件处理器。这非常适合您的扩展性需求,因为您所需要的只是一些加载的程序集拥有一个实现此接口的类,并且它将自动向工厂注册。但是,您可以使用任何系统来注册这些类型:

public class ProcessorFactory
{
    static IDictionary<string, IFileProcessor> ProcessorsByExtension = 
        new Dictionary<string, IFileProcessor>();

    static ProcessorFactory() 
    {
        var processorTypes = 
            from a in AppDomain.CurrentDomain.GetAssemblies()
            from t in a.GetTypes()
            where typeof(IFileProcessor).IsAssignableFrom(t)
            select t;
        foreach(var t in processorTypes)
        {
            // Preferably use your DI framework to generate this.
            var processor = (IFileProcessor)Activator.CreateInstance(t);
            foreach(var ext in processor.FileExtensions)
            {
                if(ProcessorsByExtension.ContainsKey(ext))
                {
                    throw new InvalidOperationException(
                        "Multiple processors are registered to extension " + ext);
                }
                ProcessorsByExtension[ext] = processor;
            }
        }
    }

    public IFileProcessor GetProcessorForFile(string fileName)
    {
        string extension = Path.GetExtension(fileName);
        return ProcessorsByExtension[extension];
    }   
}
公共类处理器工厂
{
静态IDictionary ProcessorsByExtension=
新字典();
静态处理器工厂()
{
变量处理器类型=
从AppDomain.CurrentDomain.GetAssemblys()中的
从a.GetTypes()中的t开始
其中typeof(IFileProcessor).IsAssignableFrom(t)
选择t;
foreach(processorTypes中的var t)
{
//最好使用您的DI框架来生成这个。
var processor=(IFileProcessor)Activator.CreateInstance(t);
foreach(processor.FileExtensions中的var ext)
{
if(ProcessorsByExtension.ContainsKey(ext))
{
抛出新的InvalidOperationException(
“多处理器注册到扩展”+ext);
}
ProcessorsByExtension[ext]=处理器;
}
}
}
公共IFileProcessor GetProcessorForFile(字符串文件名)
{
字符串扩展名=Path.GetExtension(文件名);
返回处理器ByExtension[扩展];
}   
}
文件处理器接口的典型实现可能如下所示:

public class ImageFileProcessor : IFileProcessor
{
    public IEnumerable<string> FileExtensions 
    {
        get {return new[]{"jpg", "gif", "png"};}
    }
    public void Process(string fileName) 
    {
        // Process Image file type
    }
}
公共类ImageFileProcessor:IFileProcessor
{
公共IEnumerable文件扩展名
{
获取{returnnew[]{“jpg”、“gif”、“png”};}
}
公共作废进程(字符串文件名)
{
//处理图像文件类型
}
}

这种方法使您的代码保持模块化和可扩展性,同时提供优异的性能,即使您有大量的文件处理器。

这种重构有一条规则--

  • 用多态性/策略替换条件。 if/switch的明显问题是,此类代码中很可能存在错误,并且很难维护或增强
考虑到相同和“开闭主体”(-类应为扩展开放,但为修改关闭)

我建议使用下面的代码

public class Processor
    {
        private Dictionary<string,FileParserBase> _fileExtension2FileParser;

        public Processor() {
            _fileExtension2FileParser = new Dictionary<string, FileParserBase>();

            AddParser(new DocExtensionWordParser());
            AddParser(new DocXExtensionWordParser());
            //..more,more
        }

        private void AddParser(FileParserBase fileParserBase) {

            _fileExtension2FileParser.Add(fileParserBase.Extension, fileParserBase);
        }


    public void Process(string fileName)
    {
        string extension = Path.GetExtension(fileName);
        FileParserBase fileParser;
        if (_fileExtension2FileParser.TryGetValue(extension, out fileParser)) {
            fileParser.Process(fileName);
        }

    }
    }

    public interface FileParserBase
    {
        string Extension { get; }
        void Process(string filePath);
    }

    public abstract class WordParserBase : FileParserBase
    {
        private string _extension;

        public WordParserBase(string extension)
        {
            _extension = extension;
        }

        public override void Process(string filePath)
        {
            //Do the processing for WORD Document
        }

        public override string Extension
        {
            get { return _extension; }
        }
    }

    public class DocExtensionWordParser : WordParserBase
    {

        public DocExtensionWordParser():base("doc"){}
    }

    public class DocXExtensionWordParser : WordParserBase
    {

        public DocXExtensionWordParser() : base("docx") { }
    }
公共类处理器
{
专用字典_fileExtension2FileParser;
公共处理器(){
_fileExtension2FileParser=新字典();
AddParser(新的DocExtensionWordParser());
AddParser(新的DocXExtensionWordParser());
//…更多,更多
}
私有void AddParser(FileParserBase FileParserBase){
_fileExtension2FileParser.Add(fileParserBase.Extension,fileParserBase);
}
公共作废进程(字符串文件名)
{
字符串扩展名=Path.GetExtension(文件名);
文件标准
public class Processor
    {
        private Dictionary<string,FileParserBase> _fileExtension2FileParser;

        public Processor() {
            _fileExtension2FileParser = new Dictionary<string, FileParserBase>();

            AddParser(new DocExtensionWordParser());
            AddParser(new DocXExtensionWordParser());
            //..more,more
        }

        private void AddParser(FileParserBase fileParserBase) {

            _fileExtension2FileParser.Add(fileParserBase.Extension, fileParserBase);
        }


    public void Process(string fileName)
    {
        string extension = Path.GetExtension(fileName);
        FileParserBase fileParser;
        if (_fileExtension2FileParser.TryGetValue(extension, out fileParser)) {
            fileParser.Process(fileName);
        }

    }
    }

    public interface FileParserBase
    {
        string Extension { get; }
        void Process(string filePath);
    }

    public abstract class WordParserBase : FileParserBase
    {
        private string _extension;

        public WordParserBase(string extension)
        {
            _extension = extension;
        }

        public override void Process(string filePath)
        {
            //Do the processing for WORD Document
        }

        public override string Extension
        {
            get { return _extension; }
        }
    }

    public class DocExtensionWordParser : WordParserBase
    {

        public DocExtensionWordParser():base("doc"){}
    }

    public class DocXExtensionWordParser : WordParserBase
    {

        public DocXExtensionWordParser() : base("docx") { }
    }