How to replace lambda delegate - c#

(removed unnecessary clutter)
Edit 1
Seems that my questions are not very clear... doh... :)
So ....
How to write this:
instance.Method(e => OtherClass.Fill(e, instance2.A, instance3.B));
with something like this:
instance.Method(new Action<IDataReader>(OtherClass.Fill));
When "Method" signature is:
void Method(Action<IDataReader> reader)
and "Fill" signature is:
void Fill(IDataReader reader, string a, string b);
Update
I figured out one alternative implementation, but it still causes debugger to step in to that Fill call. There's no anymore lambda notation but it still seems to step in, argh...
instance.Method(delegate(IDataReader e) { OtherClass.Fill(e, instance2.A, instance3.B); });
Solution
Seems that I just need one additional method which is called from delegate and that method then passes call to next method (Fill) with two more parameters:
instance.Method(this.Foo);
[DebuggerStepThrough()]
private void Foo(IDataReader reader)
{
OtherClass.Fill(reader, this.instance2.A, this.instance3.B)
}

The thing is, somewhere your code must pass those extra parameters, and your debugging experience will walk over that process. The best I can offer you is to wrap the parameter passing a little.
Either:
Action<IDataReader> wrapper = reader => this.Fill(reader, instance2.A, instance3.B);
instance.Method(wrapper);
or:
Func<Action<IDataReader, string, string>, Action<IDataReader>> reducer = arity3 => reader => arity3(reader, instance2.A, instance3.B);
instance.Method(reducer(this.Fill));
But obviously, either solution is still going to have the debugger 'walk' over the code. You can't pass parameters without actually passing the parameters.

Related

TargetParameterCountException: Parameter count mismatch on invoke - delegate

I have the following code (removed unrelated)
//top of class declaration
private delegate void UpdateFormElements(string status, bool addEmptyRow);
//inside a function in my class
if(lboImages.InvokeRequired)
{
lboImages.Invoke((UpdateFormElements)delegate { UpdateListBox("some text", true); });
}
private void UpdateListBox(string line, bool addEmptyRow)
{
lboImages.Items.Add(line);
if (addEmptyRow)
{
lboImages.Items.Add("");
}
}
Basically I'm trying to pass two parameters to the UpdateListBox function to test whether to add an empty line or not to my listbox, but I am getting the error in the title. I have tried putting the two values in an object[] but it doesn't seem to change anything as I still get the error.
I'm still new to using threads so not really sure where I'm going wrong here.
It's not clear why you're trying to use an anonymous method here. The problem is that you're creating a delegate type with two parameters, but you're not passing arguments (values for those parameters) into Invoke.
I suspect you just want:
lboImages.Invoke((UpdateFormElements) UpdateListBox, "some text", true));
That uses a method group conversion to create an UpdateFormElements delegate, and provides it the two arguments it needs.
Alternatively, you could just use a lambda expression:
MethodInvoker invoker = () => UpdateListBox(line, addEmptyRow);
lboImages.Invoke(invoker);

How to know the Variable/Property Name which was passed to a Method?

private static void AssertNotNullAndAreEqual<T, TK>(T expected, TK actual)
{
Assert.IsNotNull(expected);
Assert.AreEqual(expected, actual);
}
I can call it using:
AssertNotNullAndAreEqual(expected.FirstName, actual.FirstName);
Is there any simple way that I can know the "FirstName" text of the expected object from within this method?
I'd need it for logging purposes and giving proper error messages from within this method.
The C# caller information doesn't help here.
I would rethink that approach, because this might bite back at some point - but if you're really keen on getting some degree of automation, you could try this:
private static void AssertNotNullAndAreEqual<T, TK>(Expression<Func<T>> expected,
Expression<Func<TK>> actual)
{
var memberExpression = expected.Body as MemberExpression;
if (memberExpression != null)
{
var expectedMemberName = memberExpression.Member.Name;
var expectedVal = expected.Compile()();
var actualVal = actual.Compile()();
Assert.IsNotNull(expectedVal);
Assert.AreEqual(expectedVal, actualVal);
//...
}
}
Now your calls would have to look as follows:
AssertNotNullAndAreEqual(() => expected.FirstName, () => actual.FirstName);
Few more caveat
a lot of stuff will not be checked until compile time (luckily type-safety is preserved). It's easy to write calls that will compile correctly, but fail at runtime.
as this is written, it won't work with variables - but if you decide to go this way, it would be pretty easy to write.
Please use at your own discretion :)
If you're using ToString() for another purpose (which I assume you are), you can define an interface and use it as a type constraint on AssertNotNullAndAreEqual(...), or alternately check to see if the objects passed to AssertNotNullAndAreEqual(...) have the interface.
You define an interface, say IDebugString, which has a ToDebugString() method, then you call that to retrieve the info to log.

Pattern to reuse logic regardless of number of parms

I have some logging logic I want to call before and after several methods. Each method accepts different number/type of parameters. I'm trying to set it up so I don't have to duplicate the logging logic when I call each method. I've been able to reduce the amount of duplication by creating some delegates. I've created a delegate for each number/type of parms used and I have a method that accepts each delegate and does the logging. However, I still have around 6 different delegates and so the logic is duplicated for those six.
I think there is away to modify this so regardless of the number of parms, I have one method that does the logging and calls the method. But I haven't been able to figure it out.
Below is an example of one of the delegates and the logic I'm trying not to duplicate.
public delegate void LineOfBusinessHandler(DateTime runDate, LineOfBusinessCode lineOfBusinessCode);
public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);
try
{
del(runDate, lineOfBusinessCode);
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
}
catch (Exception e)
{
int errorId = SystemManager.LogError(e, process.ToString());
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
}
}
I realize this maybe beyond the scope and/or the capabilities of what you're looking for. But if you have a generic logging logic that you want to reuse over different method calls, without losing typesafety (i.e. NOT passing your arguments around in object[]) the way to go is interception. You need a framework (I don't recommend writing your own at first!) that can provide AOP, Dependency Injection or something similiar. Those things can usually deal with interception.
For example I have a logging interceptor I use with Ninject:
public void Intercept(IInvocation invocation)
{
var logger = LoggerFactory.GetLogger(invocation.Request.Method.DeclaringType);
var debug = !invocation.Request.Method.IsSpecialName && logger.IsDebugEnabled;
if (debug)
logger.Debug(invocation.Request.Method.Name);
try
{
invocation.Proceed();
if (debug)
logger.Debug(invocation.Request.Method.Name + " FINISH");
}
catch (Exception)
{
logger.Error(invocation.Request.Method.Name + " ERROR");
throw;
}
}
Then I create my objects by getting them with Ninject (if you don't know about it, check out some tutorials), while adding some Interception to them, for example: Kernel.Bind<MyTypeToLog>().ToSelf().Intercept().With<LoggingInterceptor>(); where LoggingInterceptor implements IInterceptor with the method shown above...
Just say if you need more in details help!
EDIT: just realized that my example doesn't show this, but you can access the arguments (as an object collection though) of the invocation too!!
It depends on what is common among the different versions, but assuming runDate and process are common you could do something like this:
public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, lineOfBusinessCode));
}
public void DoRun(DateTime runDate, ProcessCode process, Action<DateTime, ProcessCode> action)
{
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);
try
{
action(runDate, process);
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
}
catch (Exception e)
{
int errorId = SystemManager.LogError(e, process.ToString());
this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
}
}
You can even generalize so you don't have do define custom delegates as this:
public void Run<T1>(DateTime runDate, ProcessCode process, T1 param1, Action<DateTime, ProcessCode, T1> del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, param1));
}
public void Run<T1, T2>(DateTime runDate, ProcessCode process, T1 param1, T2 param2, Action<DateTime, ProcessCode, T1, T2> del)
{
this.DoRun(runDate, process, (d, p) => del(d, p, param1, param2));
}
The C# language doesn't have any syntax for metaprogramming. You'll have to use reflection. You certainly can reflect against an arbitrary method/delegate to determine the parameter types, then build a method that logs parameters and calls the original method, compile this new wrapper method, and return a delegate with the same call signature as the original.
You can do this at runtime (return a delegate) or build a new assembly with all the wrapper functions, that can then be referenced by your code and used normally.
You should look at the code-weaving tools used for Aspect-Oriented-Programming. Some of them already do this.
Unlike using a params array, this gives you a wrapper with the same signature (or delegate type) as the original method, so it is type safe and Intellisense works (as much as for any other delegate).
If I understand your question correctly it sounds like you could use the C# params keyword. See this for a reference on how to use it: http://msdn.microsoft.com/en-us/library/w5zay9db.aspx
One of the requirements when using params is that it has to be placed last in the signature of the function. Then, inside of the function you can enumerate and iterate over the variable parameters list as if it were an array.
EDIT
To expand on a comment posted by #Ben Voigt, another limitation of using the params keyword is that it requires the variable parameter list to be of the same type. This however can be mitigated in your case since all you care about is logging. In this case presumably you would be invoking the ToString() method on the objects you need to log so you could make the variable parameters list of type object.
In case calling the ToString() is not enough and you have different types of objects you could make all these objects implement a common interface. Let's call it ILoggableObject which exposes a method to provide the logging output. That's if you have the ability to change those objects.

Need help with RX:Convert System.Diagnostics.Process.OutputDataReceived to an Observable

I want to start a subprocess and watch it's redirected output. That not
a problem for me in C#, but I try to understand RX, so the game begins ...
I have a static extension method for process, which looks like this:
public static IObservable<IEvent<DataReceivedEventArgs>> GetOutput(this Process that)
{
return Observable.FromEvent<DataReceivedEventArgs>(that, "OutputDataReceived");
}
I create an observable and subscribe to it like this:
Process p = ........
var outObs = p.GetOutput();
var outSub = outObs.Subscribe(data => Console.WriteLine(data));
This is not completely wrong, but I am getting:
System.Collections.Generic.Event`1[System.Diagnostics.DataReceivedEventArgs]
while I am expecting to get strings :-(
So, I think, my extensionmethod returns the wrong type.
It would be really good, if someone could explain me, what's
wong with my extension methods signature.
Thanks a lot,
++mabra
So, I think, my extensionmethod returns the wrong type
That's exactly it.
IEvent wraps both the sender and the EventArgs parameters of a tradition Event delegate. So you need to modify your code to look something like
public static IObservable<string> GetOutput(this Process that)
{
return Observable.FromEvent<DataReceivedEventArgs>(that, "OutputDataReceived")
.Select(ep => ep.EventArgs.Data);
}
If you're using the latest Rx, then the code is a bit different
public static IObservable<string> GetOutput(this Process that)
{
return Observable.FromEventPattern<DataReceivedEventArgs>(that, "OutputDataReceived")
.Select(ep => ep.EventArgs.Data);
}
the key here is to Select the EventArgs from the EventPattern/IEvent, and then grab the Data

Redirect method call within delegate

I have a protected method in a base class which accepts a Func<T> and then turns around and executes with some added goodness. Example usage:
public MyResponse DoSomething(MyRequest request)
{
return base.Execute(() => this.Channel.DoSomething(request));
}
What I'm looking to do is take the func delegate instance and redirect the method call in the expression to another instance besides this.Channel, so something like:
protected TResponse Execute<TResponse>(Func<TResponse> command)
{
return command.Method.Invoke(this.otherInstanceOfChannel, command.Target);
}
Here the "this.otherInstanceOfChannel" would be an instance of a different concrete class than the "this.channel" passed in the original call but implements the same interface. I just need to figure out what method is being called and execute that on another instance passing in the original arguments from the caller. I started down the path of MethodCallExpressions and the like but my expression-foo is weak...
Edited/rewrote for clarity - hope this version makes more sense.
Thanks,
Matt
Yes you can do this. No time right now to give you the full solution but here is a skeleton of what you would do:
protected TResponse Execute<TResponse>(Expression<Func<TResponse>> command)
{
// Check that the expression is in the correct format (ie you are calling a method off of a type Channel
// Get the name of the method call. Something like:
var node = expr.Body as MemberExpression;
if (object.ReferenceEquals(null, node))
throw new InvalidOperationException("Expression must be of member access");
var methodName = node.Member.Name;
// Use reflection to invoke methodName on otherInstanceOfChannel
// Cast the results to TResponse and return
}
As you can see the only real trick is the use of Expression<>. The type change is transparent to any client code - they don't have to change at all. Here is some code to get you started with parsing expression trees.
I believe that you can provide the instance in the lambda expression like so:
IMyChannel myChannelInstance = MyChannelInstanceFactory.Create();
Execute(() => myChannelInstance.DoSomething(request))
If this can not be done with lambda expressions and I am sure they can you can change this to a delegate and it would work fine. The lambda expression is pointing to a code execution block and as such you can put whatever matches the expression arguments in that code block.

Categories