如何在异常情况下从动作委托访问参数并传递给另一个方法?

时间:2019-05-14 10:56:07

标签: c# delegates

我有2种派生类型:

1)AggregateCalculator

2)AdditionCalculator

上述每个派生类型都有不同的transformation logic for subvariants,并且此过程基本上涉及两个步骤:

1)变形

2)创建和存储版本

如果步骤2中有任何错误,则从当前Left and Right Subvariant的步骤2中删除数据。

我在VariantProcessor中保留了通用代码,以便在上述两种派生类型之间共享,但是现在面临的问题是,如果有错误,那么我该如何传递当前的Left and Right subvariant Id to the DeleteStatistics method

如果我使用Left and Right Subvariant as instance field at class level,则下面的方法将不需要它:

StatisticsModel Process(List<Subvariants> subvariants);

AdditionCalculator的DeleteStatistics方法还需要Left和Right SubvariantId才能删除步骤1的统计信息。

代码:

public interface IVariantProcessor
{
    void Process(Variant model);
    StatisticsModel Process(List<Subvariants> subvariants);
}

public class Variant
{
    public int VariantId { get; set; }
    public int CategoryId { get; set; }
    public string Name { get; set; }
    public List<Subvariants> Subvariants { get; set; }
}

public class Subvariants
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public sealed class VariantProcessor
{
    private string _myAppConnectionString { get; set; }
    private readonly Action _transform;
    private readonly Action _deleteStep1Data;

    public Variant(string _myAppConnectionString,Action transform, Action deleteStep1Data)
    {
         _myAppConnectionString = _myAppConnectionString;
        _transform = transform;
        _deleteStep1Data = deleteStep1Data;
    }

    public void Process(Variant model)
    {
        try
        {
            _transform();
             //version creation shared by both the derived types
        }
        catch (Exception) 
        {
          _deleteStep1Data();//How to pass currently executing left and right subvariants if to this method ?
        }
    }
}

public class AggregateCalculator : IVariantProcessor
{
    private string _myAppConnectionString { get; set; }

    public StatisticsModel Process(List<Subvariants> subvariants)
    {
         //other logic
        //_myAppConnectionString is not needed for this code
    }


    public void Process(Variant model)
        {
            _myAppConnectionString = ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString;
            new VariantProcessor( _myAppConnectionString,
               () => Transform(model),
               () => DeleteStep1Data(model.VariantId));
        }

    private void Transform(Variant model)
    {
         for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
            {
                var left = model.Subvariants[counter];
                var right = model.Subvariants[counter + 1];
                //some sort of transformation process between left and right
            }
    }
    private void DeleteStep1Data(int variantId,int leftSubvariantId,int rightSubvariantId)
    {
        VariantRepo.DeleteStatistics(variantId,leftSubvariantId,rightSubvariantId);
    }
}

因此可以从Action委托访问此左右子变量Id参数,或者周围还有其他方法吗?

1 个答案:

答案 0 :(得分:1)

Action delegate封装了一个没有参数且不返回值的方法。这意味着没有参数可访问。

当您将其作为类型Action的参数传递时:

() => Transform(model)

...您没有通过Action<Variant>。也就是说,您没有传递带有Variant类型参数的方法。

您正在传递一个Action,它代表一个带有无参数的匿名方法。这就是()的意思。如果有参数,它们将放在这些括号内。该匿名方法的 body 是对带有参数的方法的调用。

接收到Action的代码不知道该方法中的内容。它只是执行它。不知道

之间的区别
() => Transform(model)

() => {} // does nothing

另一种描述方式是,通过传递类型为Action的参数,您已经隐藏了Action表示的方法的主体。可能是任何东西。它可能是多个语句-方法内部几乎所有内容。如果您不想想要公开Action内部正在发生的事情,这正是您要做的。

如果您想同时使用参数来使用该参数来调用方法,则可以通过传递两个参数来代替传递类型为Action的参数:

Variant variant, Action<Variant> action

现在您已经有了参数(Variant)和可以将其传递给(Action<Variant>)的方法。您会打action(variant)