1

Background:

  • I have 1...* objects of the same class (X).
  • The objects are given a delegate that fetches data for it.
  • All objects of class X uses the same delegate.
  • Each object of class X wants a different set of data.
  • The SDK I'm using have declared the delegate to have no parameters.

I somehow need to check which object that is calling the delegate and act according to that.

Code section 1: The following section shows a snippet where objects of class X is created. As noted by the comment getRows is defined to be the "callback"

public void getTables() { foreach(X currentTable in mapper.getTables()) { MTables.Add(new X { TableName = currentTable.getName(), GetRows = getRows, //This is the delegate Fields = Fields.ToArray() }); } } 

Code section 2: Class X declares the delegate like this:

public X.GetRowsHandler GetRows { get; set; } public delegate IEnumerable<QvxDataRow> GetRowsHandler(); 

Code section 3: Here is pseudo code for function "getRows"

private IEnumerable<QvxDataRow> getRows() { // foreach row belonging to calling instance of class X //yield return row; } 

Section 3 and section 1 is declared in the same class, using the SDK examples.

I have looked for a solution for the last 5 hours, but I can't wrap my head around delegates. Some previous post on SO suggested that delegare.Caller can be used, but I don't understand how it is used and I'm not even sure it's applicable in this case?

Any suggestion how to deal with this?

1
  • Not really clear what you are trying to do here. What exactly is your problem? Commented Oct 15, 2013 at 11:33

2 Answers 2

1

You can wrap the code in getRows() into a method accepting a parameter, using a closure:

public void getTables() { foreach(X currentTable in mapper.getTables()) { MTables.Add(new X { TableName = currentTable.getName(), GetRows = getRows(currentTable.getName()), Fields = Fields.ToArray() }); } } // this method now returns another method that matches GetRowsHandler private GetRowsHandler getRows(string tablename) { // this lambda method uses the tablename parameter return () => { // something with foreach row in table tablename }; } 

If you need the instance of X in getRows, you could do something like:

public void getTables() { foreach(X currentTable in mapper.getTables()) { var x = new X { TableName = currentTable.getName(), Fields = Fields.ToArray() }); x.GetRows = getRows(x), MTables.Add(x); } } private GetRowsHandler getRows(X instance) { return () => { // something with instance }; } 

Since itertator blocks (a.k.a. yield) don't work inside anonymous functions, you could create a class to capture the parameter instead of using a closure:

class GetRowsWrapper { X _instance; public Something(X instance) { _instance = instance; } public IEnumerable<QvxDataRow> getRows() { // do something with _instance yield return yourstuff; } } public void getTables() { foreach(X currentTable in mapper.getTables()) { var x = new X { TableName = currentTable.getName(), Fields = Fields.ToArray() }); // lambda to wrap getRows into a GetRowsHandler x.GetRows = () => new GetRowsWrapper(x).getRows(); MTables.Add(x); } } 
Sign up to request clarification or add additional context in comments.

3 Comments

This appears to be a valid approach. However I need a little bit more guidance. Visual studio complain about the yield statement. "The yield statement cannot be used inside a lambda expression" I'm feeling so stupid right now
@Anders Ah, yeah, yield will not work in an anonymous function. I'll update my answer if you really need yield to work.
Thank you for your help! I was able to work around the need for yield. (Pretty simple once I started thinking). Anyhow everything works exactly as I wanted. Thanks once again!
0

If you have control over the class exposing the delegate then just change the delegate to accept an argument for the caller. Otherwise you are out of luck.

Regardless, this architecture is questionable at best.

1 Comment

I am able to extend it. Is it possible to overload the delegate signature just as any other method like this: public delegate IEnumerable<QvxDataRow> GetRowsHandler(List<IRowMapper> data);? Visual studio seems to be satisfied at least. However I'm not sure how to supply the argument to the delegate when using this method.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.