如何链接列表中的方法
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());
}
我有一个包含 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());
}