how to convert Expression<Action> to Action - c#

Hey i was wondering if i can convert an Expression to an Action.
I need to use the Expression to get the details of the lambda expression and at the same time i need to execute it using a different method. I need to get the Expression and the actual action with just using a single parameter (either Action or Expression):
BTW i need this for Getting details on what kind of assert i did. ex(Assert.true, Assert.False)
public void otherMethod()
{
SomeMethod(() => Assert.Equals("Dog","Cat"));
}
public void SomeMethod(Expression<Action> neededAction) //or public void SomeMethod(Action neededAction)
{
//i need to run the neededAction and get the details whether what assert i did and the inputs i used for the assertion
}
So basically i need to run the Action and i need to get its method infos.
Thanks~

You need to call Compile() on the expression.
// Compile it.
var actualNeededAction = neededAction.Compile();
// Execute it.
actualNeededAction();

Related

Check in a method if the parameter equals a specific method

I use the code line:
MethodBase senderMethod = MethodBase.GetCurrentMethod();
inside a method to get the information of the method's identity.
I then invoke another method using the senderMethod as argument in the method call:
RefreshLineSelection(_cursorLocation, senderMethod);
In the method RefreshLineSelection I need to check the identity of the calling method, as this method is invoked from two different methods.
I do this thus:
string name = senderMethod.Name;
if (name == "Panel_MouseMove")
{
}
It seems to me that there should be a more elegant way.
I tried:
if (senderMethod == Panel_MouseMove)
{
}
and also:
if (senderMethod.Equals(Panel_MouseMove))
{
}
but I get error messages I do not know how to resolve.
In one sentence, my question is: What is the correct syntax for:
if (senderMethod.Equals(Panel_MouseMove))
{
}
Any help would be greatly appreciated.
Thank you in advance.

How to do 'out' in a Func<T> in c#

I am using a library which measure metrics for running code.
The usage of the library is something like this.
_Library.Wrap("AnyStringForMetrics", Func<T>);
So whatever I pass into the Func as a lambda will be measured and result of it will be returned.
At the moment, I have method where I want to measure this line where it tries to create or get a user with that id. (newlyCreated will be true if the user was created)
public User GetOrCreate(long id, out bool newlyCreated) {
// some random checks
return UserDatabase.GetOrCreate(id, out newlyCreated);
}
But now, if I try to wrap my code around
public User GetOrCreate(long id, out bool newlyCreated) {
// some random checks
return _Library.Wrap(
"UserGetOrCreate", () => UserDatabase.GetOrCreate(id, out newlyCreated));
}
I will get an exception for using "out" inside lambda expression. How should I resolve this?
If possible please write out a concrete code example... Thanks.
Use a ValueTuple as return type instead and thus avoid using an out parameter.
public (User user, bool newlyCreated) GetOrCreate(long id) {
var user = ....;
bool created = ....;
return (user, created);
}
and map it to Func<(User, bool)>.

Passing a function to another function

I am writing an HTTP wrapper class object in C# and I would like to give the main method the ability to receive a function as a parameter and then execute it on the source HTML returned by the POST/GET.
For example I may want to pass a function that checks the headers for a cookie and only returns true if it's found OR pass a regular expression function that checks the source for a piece of content.
I know in PHP or JS I could easily just pass functions as parameters but I am not sure on how to go about it without creating delegates that match the functions I want to use.
I would like the code to be as "generic" as possible so that it could receive any function e.g Pseudocode would be like
public bool MakeHTTPRequest(string url, object possiblefunction)
{
make HTTP request
if status == 200
{
string response = getresponse
if(object is function){
call object
}
}
}
So the function may OR may NOT be passed in, or I may set a global property with it. Then I need to check IF a function exists and execute it if it does.
The function could be ANYTHING and I want to future proof the code so it can handle any kind of function in the future that maybe passed to it.
Any help would be much appreciated.
Thanks
Use either Func or Action (or Predicate as mentioned by DavidN) to specify the contract of delegates passed as a parameter into your MakeHTTPRequest method.
public bool MakeHTTPRequest(string url, Action possiblefunction)
{
make HTTP request
if status == 200
{
string response = getresponse
if(possiblefunction != null){
possiblefunction();
}
}
}
If your "function" returns a value/result then use Func instead..(where T is the expected return type)...e.g. Func<int>.
If your "function" expects parameters then specify the expected parameter types. So here are some examples:
Func<string,float,int> - a delegate which expects string and float parameters and returns an int result
Action - a delegate that takes no parameters, and doesn't return a value
Action<string,float> - a delegate that doesn't return a value (void), and expects a string and float as parameters.
http://www.blackwasp.co.uk/FuncAction.aspx
Func vs. Action vs. Predicate
If you're trying to pass back the "response" to the possiblefunction then do something like this.
public bool MakeHTTPRequest(string url, Action<string> possiblefunction)
{
make HTTP request
if status == 200
{
string response = getresponse
if(possiblefunction != null){
possiblefunction(response);
}
}
}
Based on the examples you've given, it seems that what you really want is to pass in a set of validators to determine if the HTTP response meets certain criteria. This seems to be further corroborated by the fact that your method is returning bool.
A Predicate<T>, or actually a set of Predicates, should encapsulate criteria rules that you pass in to determine whether the request is valid or not.
The signature for a Predicate<T> is bool Predicate<T>(T t) - meaning that it takes in some type and produces a bool
Using an array of predicates, and making sure they all pass, seems to be a pretty future-proof way for what you want to do
public bool MakeHTTPRequest(string url, params Predicate<WebResponse>[] validators)
{
// make HTTP requrest
var request = HttpWebRequest.Create(url);
var response = (HttpWebResponse)request.GetResponse();
if (response.StatusCode == HttpStatusCode.OK){
foreach(var validator in validators)
if (!validator(response))
return false;
}
return true;
}
The trick is that the params keyword allows you to call the method passing in [0..any number] of values for the params, so all of the following invocations would work:
MakeHTTPRequest("http://stackoverflow.com");
MakeHTTPRequest("http://stackoverflow.com", r => r.Headers.AllKeys.Contains("CookieHeader"));
MakeHTTPRequest("http://stackoverflow.com", r => r.Headers.AllKeys.Contains("CookieHeader"), r => r.ContentLength < 10000);

How do I get arguments passed to a data access layer that uses System.Action as an input parameter?

I'm trying to create some unit tests for an application I've recently inherited. Currently using NSubstitute because that's what the previous programmer used, but I'm not attached to it.
The method I'm testing calls the DataService class' Create method.
Calling Create Method
var contactProductLink = this.dsService.Create<ContactProductLink>(x =>
{
x.ContactRoleId = prod.RoleId;
x.ContactId = contactViewModel.ContactId;
x.ProductId = prod.ProductId;
x.Active = true;
x.InsertDate = DateTime.Now;
x.InsertUserId = user.employeeId;
x.UpdateDate = DateTime.Now;
x.UpdateUserId = user.employeeId;
});
DataService Create Method:
public TEntity Create<TEntity>(Action<TEntity> propertySetter = null) where TEntity : class
{
var tEntity = this.Context.Create<TEntity>();
if (propertySetter != null)
{
propertySetter(tEntity);
}
return tEntity;
}
The approach I've taken (and maybe there's a better way) is to use NSubstitute to mock the DataService. When I'm doing my assertions at the end, I'm checking to make sure that the Create method was called:
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
However, I'd like to also verify the input that was sent to the method is correct, and here's where I'm running into trouble. I can get the System.Action object that was passed to the Create method, but I can't figure out how to pull out the parameters (such as ContactRoleId, ContactId, etc. as posted in the calling create method code snippet).
So after all of that what I'm asking is:
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Is there a better way to do this than what I'm currently trying to do?
Solution
//Arrange
mockDataSupplierService.Create<ContactProductLink>(Arg.Do<Action<ContactProductLink>>(x=> actionToPopulateEntity = x));
//Assert
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
var entity = new ContactProductLink();
actionToPopulateEntity.Invoke(entity);
Assert.AreEqual(ExpectedContactId, entity.ContactId);
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Essentially you can't, as it is not possible to extract "code" details from action (consider what happens when you pass an action that doesn't set any properties - this is totally legal, but would break hypothetical mechanism).
However, you can try this instead:
Create entity with initial values
Use Arg.Invoke argument, telling NSubstitute to use chosen object as action parameter
Verify that entity properties values changed
For example:
// Arrange
var entity = new ContactProductLink
{
ContactRoleId = // ...
// ...
};
mockDataSupplierService
.Create<ContactProductLink>(Arg<ContactProductLink>.Invoke(entity));
// Act
// ...
Assert.That(entity.ContactRoleId, Is.EqualTo(2));
// ...

Is it possible to chain multiple methods to a delegate in one assignment statement?

I want to chain together two (and possibly more in the future) methods to a delegate and just wondered if there is a way to do this in one assignment statement, e.g.
I have a delegate method signature defined as
public delegate void MaskRequestSection(Request request);
...and 2 methods that use this signature, namely...
public void MaskCvnSection(Request request)
{
// do the masking operation
}
public void MaskCardNumberSection(Request request)
{
// do the masking operation
}
At present, I am using the following to instantiate the delegete, chain the 2 methods to it and then invoke them...
private void HideDetailsInRequest(Request request)
{
MaskRequestSection maskRequestSection = MaskCvnSection;
maskRequestSection += MaskCardNumberSection;
maskRequestSection(request);
}
....I am just curious as to why I can't chain both delegates in one statement like below,
MaskRequestSection maskRequestSection = MaskCardNumberSection+ MaskCvnSection;
...but also if there is another way that it can be done within one declaration. I haven't been able to find anything that specifically addresses this on MSDN, and I'm just asking for my own curiosity.
Thanks in advance.
You can do it with a cast:
var maskRequestSection = (MaskRequestSection) MaskCardNumberSection
+ (MaskRequestSection) MaskCvnSection;
... but you can't do it without one, because the + operator here works on delegates, not method groups. When the compiler sees the binary + operator, it has to work out the type of the expression, and that doesn't take the assignment part into account.

Categories

Resources