如何链接列表中的方法

How to chain methods in a List

我有一个包含 Actions 的列表,我想将它们链接在一起,我应该怎么做?

List<Action> actions = new List<Action>();
_imageEditor.ProcessImage(_image, factory => factory.AllTheMethodsInActions));

这是我在不使用列表的情况下进行的:

_imageEditor.ProcessImage(_image, factory => factory.Resize(_currentSize).Rotate(_currentDegrees).Flip(_currentFlipVertically))

这可能吗?是否可以 "Add" 方法来代替?伪代码

Action original = () => _imageEditor.ProcessImage(_image, factory => factory.Resize(_currentSize));
Action toAdd = () => Rotate(_currentDegrees);
Action newAction = original + toAdd
// Result would look like this //
_imageEditor.ProcessImage(_image, factory => factory.Resize(_currentSize).Rotate(_currentDegrees));

以下是可能有用的其余代码:

public Image ProcessImage(Image image, Func<ImageFactory, ImageFactory> process)
    {
        using (var imageFactory = new ImageFactory(preserveExifData: true))
        {
            using (var imageStream = new MemoryStream())
            {
                var loadResult = imageFactory.Load(image);
                var processResult = process(loadResult.agg);
                processResult.Save(imageStream);

                return Image.FromStream(imageStream);
            }
        }
    }

public void Resize(Size size)
    {
        _currentSize = size;

        // SCALE _image and fire event:
        OnImageChanged(_imageEditor.ProcessImage(_image, factory => factory.Resize(_currentSize)));
    }

public void Rotate(int degrees)
    {
        _currentDegrees = degrees;

        // Rotate _image and fire event:
        OnImageChanged(_imageEditor.ProcessImage(_image, factory => factory.Rotate(_currentDegrees)));
    }

我建议您可以将每个 Action 转换为 Func

那么你可以有如下格式。这是一个通用版本,考虑到并非每个链接步骤 returns 都是相同类型的实例:

var actions=new List<Func<object,object>>[]{ 
    (input, output)=> { (input as FactoryType).Resize(_currentSize); return input},
    (input, output)=> { (input as FactoryType).Rotate(_currentDegrees); return output}
};

// TODO: Add more steps here individually

_imageEditor.ProcessImage(_image, factory => {
    object input=factory;
    foreach( var action in actions)
    {
        input=action.Invoke(input);
    }
});

foreach循环也可以转换为IEnumerable.Aggregate调用,比如

_imageEditor.ProcessImage(_image, factory => {
    actions.Aggregate<Func<object,object>,object,object>(factory, (input, step)=>{input=step(input)}, input=>input);
    });

如果您确定每一步都会输出与输入类型相同类型的结果,那么我们可以将类型从对象缩小到您在操作定义中自定义的 FactoryType。

不完全是我想要的,但我找到了解决这个问题的好方法。我会将另一个答案保留为已接受的答案,但这可能对其他人有用。

    List<Func<Image, Image>> _currentEditFuncs;

    public void Rotate(int degrees)
    {
        _currentDegrees = degrees;

        AddNewFunc((image) => _imageEditor.ProcessImage(image, factory => factory.Rotate(_currentDegrees)));
    }

    void AddNewFunc(Func<Image, Image> newEditFunc)
    {
        bool containsAction = _currentEditFuncs.Contains(newEditFunc);

        if (!containsAction)
        {
            _currentEditFuncs.Add(newEditFunc);
        }
    }

    Image ApplyEdits()
    {
        // Declare the image to be edited (using the original):
        Image newImage = _image;

        // Loop through the current edit functions and apply them to the newImage:
        _currentEditFuncs.ForEach(action => newImage = action.Invoke(newImage));

        return newImage;
    }

    void EditImage()
    {
        // Fire the event that updates the image passing the method that applies the edits:
        OnImageChanged(ApplyEdits());
    }