将方法作为参数传递

本文关键字:参数传递 方法 | 更新日期: 2023-09-27 18:10:48

我有一个方法SaveChanges<T>(T object),在我的代码中经常被调用,除了根据调用该方法的操作,在SaveChanges中会有一个不同的方法被调用。像这样的。。。

protected void SaveChanges<T>(T mlaObject, SomeFunction(arg))
    where T : WebObject
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        SomeFunction(arg);
    }
}

用法示例:

SaveChanges<MlaArticle>(article, article.Authors.Remove(person)) //person is an object of type MlaPerson
//OR
SaveChanges<MlaArticle>(article, article.RelatedTags.Remove(tag)) //tag is an object of type Tag
//OR
SaveChanges<MlaArticle>(article, article.RelatedWebObjects.Remove(location)) //location is an object of type MlaLocation

我已经阅读了委托方法,但我有点困惑于如何用我的需求来实现它,或者我的需求是否值得委托使用。

编辑:还有,可以通过多个操作吗?

将方法作为参数传递

怎么样:

protected void SaveChanges<T>(T mlaObject, Action<T> rollback)
    where T : WebObject
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        rollback(mlaObject);
    }
}

调用类似:

this.SaveChanges(myObj, x => article.Authors.Remove(x));

现在,从你的问题的二读来看,我认为通过mlaObject没有任何意义,因为它从未被使用过。

// this.SaveChanges(
//     () => article.Authors.Remove(author),
//     () => article.RelatedTags.Remove(tag));
protected void SaveChanges(params Action[] rollbacks)
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        foreach (var rollback in rollbacks) rollback();
    }
}
// Overload to support rollback with an argument
// this.SaveChanges(
//     author,
//     article.Authors.Remove,
//     authorCache.Remove);
protected void SaveChanges<T>(T arg, params Action<T>[] rollbacks)
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        foreach (var rollback in rollbacks) rollback(arg);
    }
}

UPDATE从您的问题中,我有点不清楚传入的arg是否在方法中的其他任何地方使用,它看起来不像是,所以您可以只使用Action并使用lambda指定要使用捕获的参数调用的委托:

protected void SaveChanges<T, TArg>(T mlaObject, TArg arg, Action undoFunction)
    where T : WebObject
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        undoFunction();
    }
}

你可以通过:

SaveChanges(article, () => article.Authors.Remove(person));

或者,如果是myObj本身,在这种情况下(六个字母的变量已经回答(,您可以根据委托的代码将其传递回委托。

或者,arg是否与mlaObject不同,并且您还想在代码中对它做其他事情,在这种情况下,您可以这样做:

protected void SaveChanges<T, TArg>(T mlaObject, TArg arg, Action undoFunction)
    where T : WebObject
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        undoFunction(arg);
    }
}

然后有:

SaveChanges(article, person, article.Authors.Remove);
protected void SaveChanges<T,U>(T mlaObject, Action<U> action, U arg)
    where T : WebObject
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        action(arg);
    }
}

希望我能正确理解这个问题。。。

您的SaveChanges方法看起来像:

protected void SaveChanges<T,TArg>(T mlaObject, TArg arg, Action<T,TArg> someFunction)
    where T : WebObject
{
   ...
}

调用类似:

SaveChanges<MlaArticle,Person>(article,person, (article,person) =>  article.Authors.Remove(person))

如果我的要求值得代表们使用的话。

如果你想让SaveChanges方法执行一些功能,你有两个选项

  • 让它直接执行函数(方法内部的代码,或者从方法内部调用第二个方法(;或
  • 将函数作为委托提供给CCD_ 6方法

何时使用其中的每一个都是您的设计选择,取决于场景、整体解决方案和您的偏好。

第一个的好处

  • 能够在一个地方看到SaveChanges方法的所有可能结果
  • 对于不知道代表如何工作的人来说,不那么令人困惑

第二次的好处

  • 能够从SaveChanges方法中排除所有可能的函数(它不需要巨大的caseif else if else if(
  • 传递给SaveChanges方法的函数可以在调用堆栈中位于它之上,它不需要知道它们是什么或如何工作,它们可以做它不理解的事情,并且它们可以被重用-在其他地方调用或用作其他函数中的委托

我认为第一点是最主要的一点。如果你只处理几个场景,那么有一个if else if else if是可以的,但如果你有很多选项,并且更喜欢一个更通用的SaveChanges方法,那么就对该委托进行psdd。

protected void SaveChanges<T>(T mlaObject, Action<T> functionToCall)
{
    try { this._db.SaveChanges(); }
    catch (Exception e)
    {
        Console.WriteLine("Error: " + e);
        functionToCall(mlaObject);
    } 
}

这样调用:

SaveChanges(actualArticle, article => article.Authors.Remove(person));

我省略了WebObject部分,因为它根本没有在函数中使用。