Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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#设计指南-基于字符串值调用适当的方法_C#_Oop_Design Patterns_Code Design - Fatal编程技术网

C#设计指南-基于字符串值调用适当的方法

C#设计指南-基于字符串值调用适当的方法,c#,oop,design-patterns,code-design,C#,Oop,Design Patterns,Code Design,寻找以下问题的设计指南。 我收到两个字符串值-action和message,必须调用处理字符串消息的适当方法(processM1MessageVer1、processM1MessageVer2、processM2MessageVer1…)。我必须调用的方法取决于给定的字符串操作。每个处理方法有两个版本(但将来可能会有更多)。我必须调用的方法的版本由全局变量版本决定。每个方法都返回不同类型的对象(ResultObject1、ResultObject2…)。结果必须序列化、转换为base64并返回

寻找以下问题的设计指南。 我收到两个字符串值-action和message,必须调用处理字符串消息的适当方法(processM1MessageVer1、processM1MessageVer2、processM2MessageVer1…)。我必须调用的方法取决于给定的字符串操作。每个处理方法有两个版本(但将来可能会有更多)。我必须调用的方法的版本由全局变量版本决定。每个方法都返回不同类型的对象(ResultObject1、ResultObject2…)。结果必须序列化、转换为base64并返回

是否有更优雅的编写方法(消除重复代码,使将来可能的更改更容易,减少代码…):

如果必须处理的消息是不同的对象类型而不是字符串,那么就更简单了,这样就可以以多态方式调用相应的方法。每个流程方法返回不同的对象类型这一事实也使事情变得更加复杂。但是这些并不取决于我,我无法改变它。

我的方法(使其更面向对象,并且您应该根据您的处理逻辑有多复杂来证明创建类结构是否合适。如果您的处理逻辑很小,那么这可能是过度工程):

对于序列化并转换为Base64,我假设您有一些逻辑以通用方式执行这些任务。如果不是,也将其移动到子类

 public interface IRequestProcessorFactory
{
    IRequestProcessor GetProcessor(string action);
}

public class FactoryVersion1 : IRequestProcessorFactory
{
    public IRequestProcessor GetProcessor(string action)
    {
        switch(action)
        {
            case "m1":
                return new M1Ver1RequestProcessor();
            case "m2":
                return new M2Ver1RequestProcessor();
            case "m3":
                return new M3Ver1RequestProcessor();
            default:
                throw new NotSupportedException();
        }
    }
}

public class FactoryVersion2 : IRequestProcessorFactory
{
    public IRequestProcessor GetProcessor(string action)
    {
        switch(action)
        {
            case "m1":
                return new M1Ver2RequestProcessor();
            case "m2":
                return new M2Ver2RequestProcessor();
            case "m3":
                return new M3Ver2RequestProcessor();
            default:
                throw new NotSupportedException();
        }
    }
}

public interface IRequestProcessor
{
    string ProcessRequest(string message);
}

public class RequestProcessorBase<T>
{
    public string ProcessRequest(string message)
    {
        T result = Process(message);
        string serializedResult = Serialize(result);
        return ConvertToB64(serializedResult);
    }

    protected abstract T Process(string message);

    private string Serialize(T result)
    {
        //Serialize
    }

    private string ConvertToB64(string serializedResult)
    {
        //Convert
    }
}

public class M1Ver1RequestProcessor : RequestProcessorBase<ResultObject1>
{
    protected ResultObject1 Process(string message)
    {
        //processing
    }
}

public class M2Ver1RequestProcessor : RequestProcessorBase<ResultObject2>
{
    protected ResultObject2 Process(string message)
    {
        //processing
    }
}

public class M3Ver1RequestProcessor : RequestProcessorBase<ResultObject3>
{
    protected ResultObject3 Process(string message)
    {
        //processing
    }
}

public class M1Ver2RequestProcessor : RequestProcessorBase<ResultObject1>
{
    protected ResultObject1 Process(string message)
    {
        //processing
    }
}

public class M2Ver2RequestProcessor : RequestProcessorBase<ResultObject2>
{
    protected ResultObject2 Process(string message)
    {
        //processing
    }
}

public class M3Ver2RequestProcessor : RequestProcessorBase<ResultObject3>
{
    protected ResultObject3 Process(string message)
    {
        //processing
    }
}

该开关仍在factory类中,但它只返回处理器,不执行实际工作,因此我认为它很好

首先定义最适合您的接口,如下所示

    public interface IProcessMessage
    {
        string ActionVersion { get; }
        string AlgorithmVersion { get; }
        string ProcessMessage(string message);
    }
然后根据需要创建尽可能多的实现

public class processorM1Ver1 : IProcessMessage
{
    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }

    public string ActionVersion {get { return "m1"; }}

    public string AlgorithmVersion {get { return "ver1"; }}
}

public class processorM2Ver1 : IProcessMessage
{
    public string ActionVersion {get { return "m2"; }}

    public string AlgorithmVersion {get { return "ver1"; }}

    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM2MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}

public class processorM1Ver2 : IProcessMessage
{
    public string ActionVersion {get { return "m1"; }}

    public string AlgorithmVersion {get { return "ver2"; }}

    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer2(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}
现在,您需要知道在当前上下文中哪个实现是最好的

public class MessageProcessorFactory
{
    private MessageProcessorFactory() { }
    private static readonly MessageProcessorFactory _instance = new MessageProcessorFactory();
    public static MessageProcessorFactory Instance { get { return _instance; }}

    private IEnumerable<IProcessMessage> _processorCollection;
    IEnumerable<IProcessMessage> ProcessorCollection
    {
        get
        {
            if (_processorCollection == null)
            {
                //use reflection to find all imlementation of IProcessMessage
                //or initialize it manualy
                _processorCollection = new List<IProcessMessage>()
                {
                    new processorM1Ver1(),
                    new processorM2Ver1(),
                    new processorM1Ver2()
                };
            }
            return _processorCollection;
        }
    } 

    internal IProcessMessage GetProcessor(string action)
    {
        var algorithVersion = ReadAlgorithVersion();
        var processor = ProcessorCollection.FirstOrDefault(x => x.AlgorithmVersion == algorithVersion && x.ActionVersion == action);
        return processor;
    }

    private string ReadAlgorithVersion()
    {
        //read from config file
        //or from database
        //or where this info it is kept
        return "ver1";
    }
}

在性能方面,使用开关是非常好和有效的。如果您在编译时知道所有的可能性,那么这是一个不错的选择。在某些情况下,人们可能更喜欢字典,例如,在您的情况下,字典中填充了键(即,如果没有键,则是
case
标签),而
Func
委托实例用于执行适当处理的方法(即获取
消息
并生成
结果
)。这不会比
开关
的性能更好,但作为首选,有些人可能更喜欢它。
public class processorM1Ver1 : IProcessMessage
{
    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }

    public string ActionVersion {get { return "m1"; }}

    public string AlgorithmVersion {get { return "ver1"; }}
}

public class processorM2Ver1 : IProcessMessage
{
    public string ActionVersion {get { return "m2"; }}

    public string AlgorithmVersion {get { return "ver1"; }}

    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM2MessageVer1(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}

public class processorM1Ver2 : IProcessMessage
{
    public string ActionVersion {get { return "m1"; }}

    public string AlgorithmVersion {get { return "ver2"; }}

    public string ProcessMessage(string message)
    {
        ResultObject1 ro1 = processM1MessageVer2(message);
        var result = serialize(ro1);
        result = convertToB64(result);
        return result;
    }
}
public class MessageProcessorFactory
{
    private MessageProcessorFactory() { }
    private static readonly MessageProcessorFactory _instance = new MessageProcessorFactory();
    public static MessageProcessorFactory Instance { get { return _instance; }}

    private IEnumerable<IProcessMessage> _processorCollection;
    IEnumerable<IProcessMessage> ProcessorCollection
    {
        get
        {
            if (_processorCollection == null)
            {
                //use reflection to find all imlementation of IProcessMessage
                //or initialize it manualy
                _processorCollection = new List<IProcessMessage>()
                {
                    new processorM1Ver1(),
                    new processorM2Ver1(),
                    new processorM1Ver2()
                };
            }
            return _processorCollection;
        }
    } 

    internal IProcessMessage GetProcessor(string action)
    {
        var algorithVersion = ReadAlgorithVersion();
        var processor = ProcessorCollection.FirstOrDefault(x => x.AlgorithmVersion == algorithVersion && x.ActionVersion == action);
        return processor;
    }

    private string ReadAlgorithVersion()
    {
        //read from config file
        //or from database
        //or where this info it is kept
        return "ver1";
    }
}
public class Client
{
    public string ProcessRequest(string action, string message)
    {
        IProcessMessage processor = MessageProcessorFactory.Instance.GetProcessor(action);
        return processor.ProcessMessage(message);
    }
}