Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.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#_Inheritance_Overriding_Virtual - Fatal编程技术网

C# 如何根据条件调用不同版本的覆盖方法?

C# 如何根据条件调用不同版本的覆盖方法?,c#,inheritance,overriding,virtual,C#,Inheritance,Overriding,Virtual,我有一个类库,它有一些代码来执行一些操作。例如,它将执行2个操作,如: - Add - Multiply 在未来可能是我可以有更多的业务,如部门为eg 上面只是一个例子,因为我对每个加法、乘法操作都有一些长时间运行的操作 所以这个库的思想是接收输入,然后针对这些输入执行长时间运行的代码 这就是我的想法: public class Input { //input properties } public interface IOperations { public abstra

我有一个类库,它有一些代码来执行一些操作。例如,它将执行2个操作,如:

- Add  
- Multiply
在未来可能是我可以有更多的业务,如部门为eg

上面只是一个例子,因为我对每个加法、乘法操作都有一些长时间运行的操作

所以这个库的思想是接收输入,然后针对这些输入执行长时间运行的代码

这就是我的想法:

public class Input
{
   //input properties
}

public interface IOperations
{
    public abstract void Process(Input obj);
}


public class Add : IOperations
{
    Input obj;
    public Add(Input obj)
    {
        this.obj = obj;    
    }
    public override void Process(Input obj)
    {
       //Add method implementation
    }
}


public class Multiply : IOperations
{
    Input obj;
    public Multiply(Input obj)
    {
        this.obj = obj;    
    }
    public override void Process(Input obj)
    {
       //Multiply method implementation
    }
}
现在假设如果我想执行加法运算或乘法运算,那么我将如何根据以下类型调用相应的方法:

string type;
if(type=="Add")
   //perform add operation 
else if(type=="Multiply")
  //perform multiply operation 
但我并没有找到合适的方法来为上述需求设计代码结构

注意:创建
IOperations
作为
接口的原因是为了
依赖项注入

如前所述,可以

为输入和结果定义类

public class Input
{
}

public class Result
{
}
定义你的界面

public interface IOperations
{
    Result Process(Input obj);
}
定义工厂以返回所需的实现

public class MathFactory
{
    public IOperations GetOperatorByType(string type)
    {
        switch (type)
        {
            case "Add":
                return new Add(new Input());
            case "Multiply":
                return new Multiply(new Input());
        }

        throw new Exception("Unknown type.");
    }
}
定义您的具体实现

public class Add : IOperations
{
    Input obj;
    public Add(Input obj)
    {
        this.obj = obj;
    }

    public Result Process(Input obj)
    {
        //Perform Add here
        return new Result();
    }
}

public class Multiply : IOperations
{
    Input obj;
    public Multiply(Input obj)
    {
        this.obj = obj;
    }

    public Result Process(Input obj)
    {
        //Perform multiply  here
        return new Result();
    }
}
最后从代码中调用

 private void button1_Click(object sender, EventArgs e)
 {
     var mathFactory = new MathFactory();
     var operation = mathFactory.GetOperatorByType("Add");
     var result = operation.Process(new Input());
}
显然,您将不得不修改输入对象的使用方式(构造器与现在一样,或者可能在接口上)。。。以及如何构造结果并将答案作为属性公开


希望能有所帮助。

这是一个很好的候选人

定义一系列算法,封装每一种算法,并使其可互换

接口 操作 策略 用法 与工厂设计相比,使用此模式的优点之一是不需要更改设计来添加或删除操作。在工厂设计中,有一个硬编码的switch case语句,每次添加操作时都需要更改

当然,如果您对每个
IOOperation
使用相同的类型,那么输入和输出的设置方式实际上没有任何限制。我只是以这种方式展示它,因为将输出作为
过程
方法的返回值是明智的,但是您使用的实现可能不同

其他示例

你的代码没有编译?!你的接口中有一个公共声明,你还试图覆盖接口实现@vc74抱歉,但这只是我脑海中的一个抽象想法,我已经分享过了,因此我有疑问地写道,我没有找到合适的方法来设计这个需求的结构。接口的原因是依赖性injection@Wheels73对不起,这只是我头脑中的一个抽象概念,我已经分享过了,所以我写了这个问题我并没有找到合适的方法来设计这个需求的结构。使用接口的原因是为了依赖注入。你们可以实现策略模式,类似于这样。除此之外,您还可以使用名称/类型字符串属性丰富接口。之后,您将能够注入(使用DI容器)所有接口实现,只需按名称/类型propertyOk过滤掉您需要的实现。我会忘记抽象的阶级观念。如果您只想为每个数学运算实现一个类,那么让每个特定的类实现IOperations,这将执行必要的函数。您可以使用一个简单的工厂模式,根据“类型”给出您需要的实现。这是GOF模式吗?是的,它是。看到了。感谢你为帮助我所做的努力,请继续这样帮助。感谢:)感谢你为帮助我所做的努力,请继续这样帮助。感谢:@Learning Overthinker困惑-谢谢。。不客气。。这就是这个网站的全部内容。。。我每天都用!
public interface IOperation
{
    Output Process(Input input);
    bool AppliesTo(string operation);
}

public interface IOperationStrategy
{
    Output Process(string operation, Input input);
}
public class Add : IOperation
{
    public bool AppliesTo(string operation)
    {
        return nameof(Add).Equals(operation, StringComparison.OrdinalIgnoreCase);
    }

    public Output Process(Input input)
    {
        // Implementation
        return new Output();
    }
}

public class Multiply : IOperation
{
    public bool AppliesTo(string operation)
    {
        return nameof(Multiply).Equals(operation, StringComparison.OrdinalIgnoreCase);
    }

    public Output Process(Input input)
    {
        // Implementation
        return new Output();
    }
}
public class OperationStrategy : IOperationStrategy
{
    private readonly IOperation[] operations;

    public OperationStrategy(params IOperation[] operations)
    {
        if (operations == null)
            throw new ArgumentNullException(nameof(operations));
        this.operations = operations;
    }

    public Output Process(string operation, Input input)
    {
        var op = operations.FirstOrDefault(o => o.AppliesTo(operation));
        if (op == null)
            throw new InvalidOperationException($"{operation} not registered.");

        return op.Process(input);
    }
}
// I am showing this in code, but you would normally 
// do this with your DI container in your composition 
// root, and the instance would be created by injecting 
// it somewhere.
var strategy = new OperationStrategy(
    new Add(), // Inject any dependencies for operation here
    new Multiply()); // Inject any dependencies for operation here

// And then once it is injected, you would simply do this.
// Note that it would not be appropriate to use an Enum for
// the operation, because the compiled Enum would have to 
// remain in sync with the runtime operation values (not possible).
// That said, the data type doesn't necessarily need to be string.

var input = new Input { Value1 = 2, Value2 = 3 };

var output = strategy.Process("add", input);
// output.Value is 5

var output = strategy.Process("multiply", input);
// output.Value is 6