Passing a method as an argument

I have a SaveChanges<T>(T object) method that is often called in all of my code, except that depending on the action calling the method, another method will be used inside SaveChanges. Something like that...

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

Examples of using:

 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 

I read about delegate methods, but I got a little confused about how to implement this with my requirements or if my requirements require use for delegates in general.

EDIT: Also, is it possible to pass multiple actions?

+8
c # delegates
source share
6 answers

What about:

 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); } } 

Called as:

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

Now, from the second reading of your question, I see no reason to pass mlaObject , since it is never used.

 // 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); } } 
+10
source share

UPDATE . I was a bit obscure from your question, if the arg argument was used elsewhere in the method, it doesn't look like it, so you can just take Action and use lambda to specify the delegate to call with the argument captured:

 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(); } } 

To which you can pass:

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

Or, if he himself is myObj, and in this case (as six variable variables have already been indicated), you can simply pass it back to the delegate according to its code.

Or, if arg is different from mlaObject, and you want to do other things on it in the code too, in which case you could do:

 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); } } 

And then:

 SaveChanges(article, person, article.Authors.Remove); 
+7
source share
 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); } } 

I hope I understood the question correctly ...

+5
source share

Your SaveChanges method will look something like this:

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

Called as:

 SaveChanges<MlaArticle,Person>(article,person, (article,person) => article.Authors.Remove(person)) 
+4
source share
 protected void SaveChanges<T>(T mlaObject, Action<T> functionToCall) { try { this._db.SaveChanges(); } catch (Exception e) { Console.WriteLine("Error: " + e); functionToCall(mlaObject); } } 

Call:

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

I left the WebObject bit since it was not used at all in this function.

0
source share

if my requirements require use for delegates at all.

If you want the SaveChanges method to execute some function, you have two options

  • execute the function directly (code inside the method or call the second method from within the method); or
  • provides a function to the SaveChanges method as a delegate.

When to use each of them is a design choice that is up to you and will depend on the scenario, overall solution and your preferences.

First benefits

  • The ability to see all the possible results of the SaveChanges method in one place
  • Less confusing for those who don’t know how delegates work.

The advantages of the second

  • The ability to exclude all possible functions from the SaveChanges method (this does not require a huge case or if else if else if )
  • The functions that are passed to the SaveChanges method may be higher than it in the call stack, it does not need to know what they are or how they work, they can do what they do not understand, and they can be reused - called elsewhere or used as delegates in other functions.

I think the first point is the main one. If you work with only a few scripts, then it is good to have a if else if else if , but if you get more than a few options, and prefer the more general SaveChanges method, then psdd, which delegates.

0
source share

All Articles