Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.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#_Asp.net_Design Patterns - Fatal编程技术网

C# 如何为策略模式动态调用函数?

C# 如何为策略模式动态调用函数?,c#,asp.net,design-patterns,C#,Asp.net,Design Patterns,我正在使用.NETCoreWithRazorPages(MVVM)开发一个Web应用程序,用户可以在其中为我提供4个选项 这些选项中的每一个都执行相同的操作,但在执行方面有一点不同——这就是我想要实现策略模式的原因 有没有办法以某种方式动态生成函数名?这可能是一个愚蠢的问题,但我只是理解基本的问题 // option = A // option = B // option = C // option = D public async Task<IActionResult> OnPo

我正在使用.NETCoreWithRazorPages(MVVM)开发一个Web应用程序,用户可以在其中为我提供4个选项

这些选项中的每一个都执行相同的操作,但在执行方面有一点不同——这就是我想要实现策略模式的原因

有没有办法以某种方式动态生成函数名?这可能是一个愚蠢的问题,但我只是理解基本的问题

// option = A
// option = B
// option = C
// option = D

public async Task<IActionResult> OnPostAsync()
{

    ...

    var option = Input.Option // from model
    if(option == "A") {
        A.DoAlgorithm(input)
    } else if(option = "B") {
        B.DoAlgorithm(ïnput)
    } else if(option = "c") {
        C.DoAlgorithm(input) 
    } else {
        D.DoAlgorithm(input) 
    }

    ...
}
//选项=A
//选项=B
//选项=C
//选项=D
公共异步任务OnPostAsync()
{
...
var option=Input.option//from model
如果(选项==“A”){
A.DoAlgorithm(输入)
}否则,如果(选项=“B”){
B.DoAlgorithm(ïnput)
}否则,如果(选项=“c”){
C.DoAlgorithm(输入)
}否则{
D.DoAlgorithm(输入)
}
...
}

如果我这样做的话,我觉得我错过了这个模式的要点,所以我的问题是:是否有一些方法可以基于输入选项动态调用函数?如果我使用了错误的模式,请纠正我

您可以使用一个工厂,根据所选选项创建策略,然后使用一个基本策略类a、B、C和D进行扩展,以执行算法的特定实例

伪代码:

interface Strategy
{
    void DoAlgorithm()
}

class A : Strategy
{   
}

class B : Strategy
{
}

abstract class Creator
{
 public abstract Strategy FactoryMethod(string option);
}

class ConcreteCreator : Creator
{
 public override Strategy FactoryMethod(string option)
 {
 switch (option)
 {
 case "A": return new A();
 case "B": return new B();
 default: throw new ArgumentException("Invalid type", "option");
 }
 }
}

虽然您可以按照“四人帮”策略模式死记硬背,但现在有其他工具可以做同样的事情,而无需创建工厂,也无需依赖继承子类或实现接口的类的激增,例如,由于函数现在可以用作变量,我们可以根据您的输入类型提供
操作
的地图:

public static readonly IDictionary<string, Action<InputType>> HandlerMap = 
    new Dictionary<string, Action<InputType>>
 {
    ["A"] = DoAlgorithmA,
    ["B"] = DoAlgorithmB,
    ["C"] = DoAlgorithmC,
    ["D"] = (input) => Console.WriteLine("Too simple to need a method")
    ...
 };
然后调用将如下所示:

public async Task<IActionResult> OnPostAsync()
{
    if (HandlerMap.TryGetValue(option, out var algorithm))
    {
         algorithm(input);
    }
    // .. else this isn't a valid option.
}
公共异步任务OnPostAsync() { if(HandlerMap.TryGetValue(选项,输出var算法)) { 算法(输入); } //…否则这不是一个有效的选项。 }
谢谢您的回答。这似乎解决了我的问题,尽管下面的答案也是一个不错的选择。出于好奇,在推理和使用方面——为什么这个实现(没有设计模式)会比实际的更好?代码更少——GoF策略是在20世纪90年代制定的,当时函数式编程并不流行。Louis有下面的普通模式,您可以看到您需要一个接口(或基本/抽象类)、每个algo的多个子类(通常只有一个方法)、一个工厂(以创建正确的实例)。通常你也会想要抽象工厂,否则你只会得到原始的粗糙,只是工厂。本质上,任何只使用一个方法的
接口
抽象都可以用委托/Func/Action代替。保持简单:)因此,结果保持不变,但避免写得太多。谢谢你的解释。向上投票!:)显然,您可以增强/重构相当简单的算法查找步骤,即将
if(HandlerMap.TryGetValue(option,out-var-algorithm))
移动到一个方法调用中,如
FindMeTheAlgoForThisInput
,但您明白了。
public async Task<IActionResult> OnPostAsync()
{
    if (HandlerMap.TryGetValue(option, out var algorithm))
    {
         algorithm(input);
    }
    // .. else this isn't a valid option.
}