C# needs help to understand - c#

Hi im doing a test program that uses a wrapper dll to communicate .net projects on a c++ dll. I wanted to create a Form Based example but the documentation only shows samples in console. There is a particular part that bothers me the most.
var mgr = new Pump("localhost",1,"test");
var result = mgr.Connect();
mgr.OnStart = sender => { var sga = sender.GetAllInfo(); };
what does sender means and is there anyway to rewrite it?
Thanks...

What you see here is a lambda expression. In short terms the last line means something like:
Assign to mgr.OnStart a handler that takes one parameter sender and executes the given code. The code invokes the GetAllInfo() method on the sender object and assigns the result to the sga variable.
What don't you like about it and why do you want to rewrite it?
Based on your comment I assume that the code in your question is actually itself invoked inside an event handler (for example a button's OnClick evnet handler) that already takes a parameter named sender.
In that case, simply rename the parameter name in either location, for example like this:
mgr.OnStart = sndr => { var sga = sndr.GetAllInfo(); };

To add to the answers I thought it would be worthwhile showing the comparison of lambdas to normal methods...
Example 1 - Method with single parameter and no return value
Lambda
...
mgr.OnStart = sender => { var sga = sender.GetAllInfo(); };
...
Normal method
...
mgr.OnStart = this.Mgr_Start;
...
private void Mgr_Start(object sender)
{
var sga = sender.GetAllInfo();
}
Note that the parameter type of the above method is object. This will need to change depending on the signature of OnStart's delegate.
Example 2 - Method with no parameters, with a return value
Lambda
...
var getDateTime = () => DateTime.Now;
var dateTime = getDateTime();
...
Normal method
...
var dateTime = this.GetDateTime();
...
private DateTime GetDateTime()
{
return DateTime.Now;
}

Related

How to create FUNC Action List with Parameters and Return Values

I am trying to create my first list of actions that I will be able to check a status within the passed object.
But I can't get it to work - its giving me an error on the return type. But if I change the return type to what it wants - then I can't pass values down.
Sample code:
public class Class1
{
public Main()
{
var decisionObject = new DecisionObject();
var decisionList = new List<Func<DecisionObject, DecisionObject>>
{
Method1(decisionObject),
Method2(decisionObject),
Method3(decisionObject)
};
var exitLoop = false;
foreach (var method in decisionList)
{
decisionObject = method(decisionObject);
switch (decisionObject.Status)
{
case Status1:
exitLoop = true;
break;
case Status2:
case Status3:
case Status4:
break;
}
if (exitLoop) break;
}
}
public Func<DecisionObject, DecisionObject> Method1(DecisionObject
decisionObject)
{
decisionObject = SomeOtherMethod(decisionObject);
return decisionObject;
}
}
What am I missing here?
If I'm not mistaken, Method1,Method2, and Method3 are simply supposed to accept a decision object and return a different one. So they would be defined like this (hopefully this is straightforward to you):
DecisionObject Method1(DecisionObject input)
{
var output = SomeMethod(input);
return output;
}
You then want to put all these methods into a list and execute them. To put them into a list, put the method names in the code without parentheses. That tells C# that you want a reference to the method itself, rather than the result of invoking the method.
var decisionList = new List<Func<DecisionObject, DecisionObject>>
{
Method1, //Do not invoke-- just store a reference to the method
Method2,
Method3
};
You can then invoke them by passing the decision object in:
foreach (var func in decisionList)
{
var result = func(decisionObject);
}
The key thing here to remember is that when you put parentheses after a symbol, it tells C# to invoke it. So don't put parentheses if all you want is a reference to the method itself.
decisionObject = SomeOtherMethod(decisionObject)
Isn't probably returning a func but a value.
You could do this:
public Func<DecisionObject, DecisionObject> Method1()
{
var myFunc = (myObject) => SomeOtherMethod(myObject);
return myFunc;
}
That will create and returns a new func that expects one parameter and invokes SomeOtherMethod.
Please note that the parameter of Method1 isn't needed in this approach and so I removed it.

General way to get method parameters values from inside the method [duplicate]

Is there a way in .NET to know what parameters and their values were passed to a method. Reflection way? This will be used from inside the method. It has to be generic so it can be used from any method. This is for logging purposes.
Call MethodBase.GetCurrentMethod().GetParameters().
However, it is not possible to get the parameter values; due to JIT optimization, they might not even exist anymore.
MethodInfo.GetCurrentMethod() will give you information about the current method and then get information about the parameters using GetParameters().
What you're trying to do can be achieved easily using aspect oriented programming. There are good tutorials online, I'll point to two of them:
http://ayende.com/Blog/archive/2008/07/31/Logging--the-AOP-way.aspx
http://www.codeproject.com/KB/cs/UsingAOPInCSharp.aspx
public void FunctionWithParameters(string message, string operationName = null, string subscriptionId = null)
{
var parameters = System.Reflection.MethodBase.GetCurrentMethod().GetParameters();
this.PrintParams(parameters, message, operationName, subscriptionId);
}
public void PrintParams(ParameterInfo[] paramNames, params object[] args)
{
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($"{paramNames[i].Name} : {args[i]}");
}
}
You need AOP to achieve what you are looking for.
in c# you can use DispatchProxy to do that.
Check the following How to wrap existing object instance into DispatchProxy?
Nowadays a feature that could be used to achieve this is Roslyn's Source Generators.
In this way, the code that gets the parameters' values would be generated at compile-time based on the method definition. Could be interpreted as “compile-time reflection”.
Let's show an example to try to explain it better:
public void MethodInspectingItsOwnParameters(
[Description("First parameter")]
string paramName_1,
[Description("Second parameter")]
int paramName_2,
// ...
[Description("N-th parameter")]
object paramName_N,
// ...
[Description("Last parameter")]
bool paramName_M)
{
var paramsAndValues = new List<KeyValuePair<string, object>>();
// -
// => Put here the code that, using Roslyn's compile time
// metaprogramming, inspect the parameters from the method
// definition and at compile time generate the code that
// at run time will get the parameters's values and load
// them into [paramsAndValues]
// -
// #Rosalyn generated code
// · Code autogenerated at compile time
// => loads parameter's values into [paramsAndValues]
// -
// Eg (Hypothetical example of the code generated at compile
// time by Roslyn's metaprogramming):
//
// paramsAndValues.Add("paramName_0", paramName_1);
// ...
// paramsAndValues.Add("paramName_N", paramName_N);
// ...
// paramsAndValues.Add("paramName_M", paramName_M);
//
// - Note: this code will be regenerated with each compilation,
// so there no make sense to do nameof(paramName_N)
// to obtaint parameter's name
// #End Rosalyn generated code
foreach (var param in paramsAndValues)
{
string paramName = param.Key;
object paramValue = param.Value;
// In this section of the normal code (not generated at
// compile time) do what you require with the
// parameters/values already loaded into [paramsAndValues]
// by the compile time generated code
}
}

Convert string to lambda expression that contains variables from other classes

What I've been trying to do is convert a string of the form:
"StudentDatabase.avgHeight > 1.7"
to a lambda expression that looks like this:
() => StudentDatabase.avgHeight > 1.7;
I tried something in the lines of this:
/* String splitting and parsing occurs here */
var comparison = Expression.GreaterThan(
Type.GetType("MyNamespace.StudentDatabase").GetField("avgHeight"),
Expression.Constant(1.7)
);
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
Of course something like this wouldn't work since the GetField() method returns type FieldInfo and not Expression.
Here's a list about useful stuff you might want to know about my sample code:
The StudentDatabase class is a static class that contains a static field avgHeight.
I have already done the part of the code that parses the string so there's no need to include it in any provided solutions.
This is just an example so you can change the string and variable/class names if you wish so.
This is not an assignment so feel free to post source code. In fact, that would be greately appreciated.
TL;DR; What I'm trying to do is use LINQ Expressions to access variables from other places of the code.
I disagree with the following comments, Linq expressions is a viable way to do this sort of thing. The below code accomplishes it. However, please consider the following code:
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
/* String splitting and parsing occurs here */
var comparison = Expression.GreaterThan(
Expression.Field(null, Type.GetType("MyNamespace.StudentDatabase").GetField("avgHeight")),
Expression.Constant(1.7)
);
var lambda = Expression.Lambda<Func<bool>>(comparison).Compile();
StudentDatabase.avgHeight = 1.3;
var result1 = lambda(); //is true
StudentDatabase.avgHeight = 2.0;
var result2 = lambda(); //is false
}
}
class StudentDatabase
{
public static double avgHeight = 1.3;
}
}
Should result2 be true or false? If you want it to be true, then you have more work to do.
I've created this as a sort of framework you can work off of. It does not use LINQ but will output the value specified by the string.
var type = Type.GetType("MyNamespace.StudentDatabase");
if (type != null)
{
var field = type.GetField("avgHeight");
if (field != null)
{
Func<bool> lambda = () => (double)field.GetValue(type) > 1.7;
}
}
There is some error checking you could add/remove. The other areas such as the > and 1.7 can be parsed elsewhere and inserted but this is how you could get a value from the strings.

Updating Expression Parameter

Here's my code:
public static Response<TResult> Create<TResult>(Expression<Func<Response<TResult>>> method)
{
var objectMember = Expression.Convert(((MethodCallExpression)method.Body).Arguments[0], typeof(TResult));
var getterLambda = Expression.Lambda<Func<TResult>>(objectMember);
var getter = getterLambda.Compile();
TResult myObject = getter();
// Do something to 'myObject'
// Call original method with updated 'myObject' as the parameter
}
As you can see from the code snippet above, I have a generic method that accepts a method as a parameter.
Orginally, I was calling method.Compile()() which worked fine. However, I now need to update the parameter ("myObject") first before calling the method. So, I've added the lines above to get the parameter.
I then "Do something to 'myObject'". Finally, I want to call the original passed method, but replace the original parameter with the new, updated parameter.
What am I missing?
UPDATE
So, I've, technically, accomplished my need by the following code:
Response<TResult> result = (Response<TResult>)((MethodCallExpression)method.Body).Method.Invoke(parentType, new object[] { myObject });
But this is using a lot of reflection and casting. Is there a better way to do this?
Thanks,
Joshua

WPF purpose of `(arg) => true)`

While reading this tutorial on Command Binding in DataTemplate, I saw this:
public DelegateCommand<string> AddBrand
{
get
{
return this.addBrand ?? (this.addBrand = new DelegateCommand<string>( this.ExecuteAddBrand, (arg) => true));
}
}
which is a function inside BrandsViewModel.cs to add a Brand. I have questions about the line below:
this.addBrand = new DelegateCommand<string>( this.ExecuteAddBrand, (arg) => true));
My understanding is that AddBrand is a command registered to the Add Brand button in the View, and this adds a delegate method to be called upon the click of the button. Specifically, this.ExecuteAddBrand is the method to be executed. However, what is the purpose of (arg) => true)? What does it even mean? Thanks!
The operator => is used when we want to write a lambda expression.
You can think it of as a normal method, where the things left to => are the parameters (the input) of the method and the thing right the => is that the method returns (output).
For instance
x=>x*x
If we input 3, we will get as output 9.
Lambda expressions are really usefull in LINQ.
For instance, say that we have a collection called customers of objects of type Customer, whose defintion is the following one:
public class Customer
{
public string FirstName {get; set; }
public string LastName {get; set; }
public int Age {get; set;}
}
Let then that we want to get the customers that have age greater than 18. Then we could do this like below:
var adults = from customer in customers
where customer.Age>18
select customer;
However, we could get also the same result, as below:
var adults = customers.Where(x => x.Age>18);
In the latter case, we pass in the Where method a lambda expression.
what is the purpose of (arg) => true)? What does it even mean?
Now in your case the above lambda accepts an argument called arg and always returns true.
That is a lambda that represents a method (or expression) that accepts one argument and always returns true regardless of the input. "Given string arg, return true".
Perhaps a clearer example is on a list:
var names = List<string>(...); // populate, etc
var containsA = names.FindAll(x => x.Contains("A"));
In the above, I'm using a lambda to express a "predicate" - essentially a filter condition; for any name, it returns true if the name contains an A. FindAll returns all the items that match the predicate. We could also do:
var everybody = names.FindAll(x => true);
var nobody = names.FindAll(x => false);
(although that is obviously a bit silly)
More specific to DelegateCommand: basically, the second parameter is canExecuteMethod, and it is basically saying "yes, it can always execute, regardless of the value". In the more general case, this can act as a filter on when it is/isn't appropriate to use the method. The canExecuteMethod parameter can also be omitted or passed as null, if that would be clearer.

Categories