C#: passing parameters to callbacks

2019-07-05 05:50发布

I have a fairly generic class (Record) that I have added a callback handler to, so I can do something like the following.

record.Save(AfterSaveMethod);

Which also returns the identity number of the record created. The issue I have now is that I have this nested save routine in a loop, and I need to use/pass the i variable!

for (int i; i < count ;i++)
{
    record.Save(AfterSaveMethod2) //but I need to pass i through as well
}  

What do I do here?

A\ rewrite the save method and include it in this class (yuk),

B\ have an overloaded save option that takes an object as a parameter, so I can pass it through to my record class, and then merge it with the identity number. Returning both the identity number and anything extra contained in the passed through object (hmm, sounds a bit messy),

C\ is there a sexier option?

3条回答
贼婆χ
2楼-- · 2019-07-05 06:20
    class SexierSaveMethod
    {
        public Int32 Index { get; set; }

        public SexierSaveMethod(Int32 i)
        {
            Index = i;
        }

        public void AfterSaveMethod()
        { 
            // Use i here
        }
    }

    record.Save(new SexierSaveMethod(i).AfterSaveMethod);
查看更多
Animai°情兽
3楼-- · 2019-07-05 06:25

You could also create a (thread-static) context object, which stores your "state" (in this case, the index variable value), which you can access using a static property (say MyContext.Current). Depends on the complexity of the context ...

WCF uses something like this with OperationContext.Current, ASP.NET, TransactionScope et al.

If the context is a bit more complex than yours and you don't want to pollute the signatures of several methods, I think this model is quite neat.

Use:

// init context
MyContext.Current = new MyContext();
for (var idx = 0; idx < 99; idx++) {
    MyContext.Current.Idx = idx;
    record.Save(AfterSaveMethod);        

}
// uninitialize context
MyContext.Current = null;

(very simplistic sample)

If the context is [ThreadStatic] you could have multiple concurrent calls which won't affect each other

查看更多
贼婆χ
4楼-- · 2019-07-05 06:27

This is where anonymous methods or lambda expressions are really handy :)

Try this (assuming C# 3):

for (int i = 0; i < count; i++)
{
    int index = i;
    record.Save(id => AfterSaveMethod2(id, index));
}

Note that the lambda expression here is capturing index, not i - that's to avoid the problems inherent in closing over the loop variable.

查看更多
登录 后发表回答