Returning a method from a C# method - c#

I found this post that explains how to pass methods as parameters in C#.
What I need to know is how to return a method as the result of another method invocation.
method = DoSomething()
result = method()

you need to use either Action<T> or Func<T>
Like this:
private Action<string> Returns(string user)
{
return () =>
{
Console.WriteLine("Hey {0}", user);
};
}
or this:
private Func<bool> TestsIsThirty(int value)
{
return () => value == 30;
}

Most probably you want your return type to be a Delegate.

Check out the Action and Func delegates.

var method =()=> DoSomething();
result = method();

Related

How to wrap any function

What I want.
Invoke(Action action);
Invoke(Func func);
Invoke(Action action)
{
some action before
action()
some action after
}
Invoke(Func func)
{
some action before
res = func()
some action after
return res;
}
Call example:
Invoke(() => Tread.Sleep(1000));
var res = Invoke(() => return 5);
But in instead of Func there can be Func , Func <T,R> and so on.
The main idea is to wrap any code inside common blocks.
Reflection is possible.
I can write many methods like:
Invoke(Action<T> action)
{
some action before
action()
some action after
}
Invoke(Action<T,T1> action)
{
some action before
action()
some action after
}
Invoke(Action<T, T1, T2> action)
{
some action before
action()
some action after
}
but it is too annoying.
You can pass in an instance of Delegate to your method:
void Invoke(Delegate d, params object[] args)
{
// do soemthing beforehand
d.DynamicInvoke(args);
// do something aferwards
}
However you lose any type-safety and have to check the number and types of the args being passed yourself.
The solution depends on whether your Invoke method needs to modify the delegate's arguments or not.
If it does not, then you can persist type-safety like this:
void Invoke(Action action)
{
// some action before
action();
// some action after
}
TResult Invoke<TResult>(Func<TResult> func)
{
// some action before
TResult res = func();
// some action after
return res;
}
Then you can use lambda expressions if you need to close over the arguments:
Invoke(() => Thread.Sleep(1000));
int res = Invoke(() => int.Parse("5"));
If your Invoke method does modify the arguments, then that cannot be done in a type-safe way that accommodates any function.

Make Predicate return a bool value from async method C#

How can I make the Predicate return a bool value from async method C#
private void OnFilterTextBoxTextChangedHandler(object oSender, TextChangedEventArgs oArgs)
{
//Other operations
_oCollectionView.Filter = new Predicate<object>(DoFilter); //wrong return type
}
Returning method
private async Task<bool> DoFilter(object oObject)
{
if (_sFilterText == "")
{
return true;
}
return false;
}
Predicate<T> is a delegate. You don't need to instantiate a new predicate when adding a filter to your CollectionView. Instead, you can add your filter like this:
_oCollectionView.Filter = DoFilter;
Second, the signature of the CollectionView.Filter delegate is public delegate bool Predicate<object>(object obj). The parameter obj is the element of the CollectionView that is being evaluated. You cannot alter this signature to make it asynchronous.
In your example, I would look at doing the following:
constructor()
{
InitializeComponent();
// Alternatively put this in an initialization method.
_oCollectionView.Filter = DoFilter;
}
private async void OnFilterTextBoxTextChangedHandler(object oSender, TextChangedEventArgs oArgs)
{
// Other operations
// Asynchronous processing
await SetupFilterAsync();
_oCollectionView.Refresh();
}
private async Task SetupFilterAsync()
{
// Do whatever you need to do async.
}
private bool DoFilter(object obj)
{
// Cast object to the type your CollectionView is holding
var myObj = (MyType) obj;
// Determine whether that element should be filtered
return myObj.ShouldBeFiltered;
}
You can also define your filter as a lambda, which would look like this and eliminate the DoFilter method:
_oCollectionView.Filter = x => ((MyType)x).ShouldBeFiltered;

Invoking class method in Generic method

I have the following code:
private void StartTask<T>(string parameter)
{
dynamic instance = (T) Activator.CreateInstance(typeof(T), parameter);
Task.Factory.StartNew(() => instance.DoCompare());
}
This does not work and the "DoCompare()" method does not get called...How do I call a method in a class with parameters in a generic type method?
Class I am initiating:
public class Something {
private string _parameter;
public Something(string parameter) {
_parameter = parameter;
}
public void DoCompare(){
//Do longrunning task
}
}
EDIT: Removed constraint BaseClass5 because of confusion
EDIT2: I get: A first chance exception of type
'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException'
EDIT3:
This seems to work, the issue seems to be Task.Factory.StartNew:
private void StartTaskAwesomium<T>() where T
{
dynamic instance = (T) Activator.CreateInstance(typeof (T), parameter);
instance.Test();
}
In theory your code should work, but it is a "fire-and-forget" pattern, meaning it will be executed sometime, but you have no control over that or can check if it actually was executed or if there was an exception.
Maybe change it to:
private async void StartTask<T>(string parameter) where T : BaseClass5
{
BaseClass5 instance = (T)Activator.CreateInstance(typeof(T), parameter);
await Task.Factory.StartNew(() => instance.DoCompare());
}
No need for the dynamic as because of your generic constraint you know that T must be BaseClass5 or based on it.
Or return the task to await (or task.Wait()) it elsewhere:
private Task StartTask<T>(string parameter)
{
T instance = (T)Activator.CreateInstance(typeof(T), parameter);
return Task.Factory.StartNew(() => instance.DoCompare());
}
The solution was to wrap the creation of the class in the Task itself like this:
private void StartTask<T>(string connectionId) where T : BaseClass5
{
Task.Factory.StartNew(() =>
{
dynamic instance = (T) Activator.CreateInstance(typeof (T), connectionId);
instance.DoCompare();
});
}
private void StartTask<T>(string parameter)
{
dynamic instance = (T) Activator.CreateInstance(typeof(T), parameter);
Task.Factory.StartNew(() => {instance.DoCompare();});
}
This seems to work.

C#: Convert a generic function to a Func object

I have the following function:
private int GetEnumTypeUnderlyingId<T>()
{
return (int)Enum.Parse(typeof(T), Enum.GetName(typeof(T), _franchise.LogonDialog));
}
I want to convert it to a Func type. I write something like:
Func<int> GetEnumTypeUnderlyingIdFunc<T> = () => (int)Enum.Parse(typeof(T), Enum.GetName(typeof(T), _franchise.LogonDialog));
But this does not work. I am not really comfortable when working with Func<>, Generics and lambda expressions so any help will be greatly appreciated
You can define your own delegate. Here is what you are looking for:
//Your function type
delegate int GetEnumTypeUnderlyingIdFunc<T>();
//An instance of your function type
GetEnumTypeUnderlyingIdFunc<int> myFunction = () => //some code to return an int ;
Also this works too.
//An instance of Func delegate
Func<int> GetEnumTypeUnderlyingIdFunc = () => //some code to return an int;
Another solution would be
public Func<int> GetTheFunc<T>(T val)
{
Func<int> func = () => (int)Enum.Parse(typeof(T),Enum.GetName(typeof(T),val));
return func;
}
Then
var func = GetTheFunc<_franchise>(_franchise.LoginDialog);
//Now you can use the func, pass it around or whatever..
var intValue = func();

o => o.MethodWithParameters | is it possible to use a method in a lambda without () and parameters

i have a method that takes as a parameter an expression because I need the method string name, and I don't care about the parameters of that method, is it possible to do that ?
I don't think that there is. You can however make a generic helper method that you can put in place of the parameters:
public T Any<T>(){
return default(T);
}
and you can call it like so:
YourMethod((YourClass yc) => yc.SomeMethod(Any<SomeClass>(), Any<SomeOtherClass>());
Yes, it's possible. Here is a concept proof test.
private static T RunExpression<T>(Expression<Func<T>> run )
{
var callExpression = (MethodCallExpression) run.Body;
var procedureName = callExpression.Method.Name;
Trace.WriteLine(procedureName);
foreach (var argument in callExpression.Arguments)
{
Trace.WriteLine(argument);
}
Trace.WriteLine(callExpression.Arguments.Count);
// Some really wicked stuff to assign out parameter
// Just for demonstration purposes
var outMember = (MemberExpression)callExpression.Arguments[1];
var e = Expression.Lambda<Func<object>>(outMember.Expression);
var o = e.Compile().Invoke();
var prop = o.GetType().GetField("s");
prop.SetValue(o, "Hello from magic method call!");
Trace.WriteLine(run.Body);
return default(T);
}
[TestMethod]
public void TestExpressionInvocation()
{
var action = new MyActionObject();
string s = null;
RunExpression(() => action.Create(1, out s));
Assert.AreEqual("Hello from magic method call!", s);
}
The easiest way to do this doesn't even use expression trees:
void Main()
{
Console.Out.WriteLine(GetNameOfMethod(new Action(Main)));
Console.Out.WriteLine(GetNameOfMethod(new Func<Delegate, string>(GetNameOfMethod)));
Console.Out.WriteLine(GetNameOfMethod(new Func<int, short, long>(AddNumber)));
Console.Out.WriteLine(GetNameOfMethod(new Action<int, short>(SwallowNumber)));
}
string GetNameOfMethod(Delegate d){
return d.Method.Name;
}
long AddNumber(int x, short y){ return x+y; }
void SwallowNumber(int x, short y){}
yields:
Main
GetNameOfMethod
AddNumber
SwallowNumber
I use this to build a BDD framework on http://storyq.codeplex.com.
Click here to see the file where I do this.
You can use this method without parameters but parentheses (even empty) are required, because without them you tell the compiler to access a property of that name.
You can use something like:
(credits go to klausbyskov)
But it's less verbose.
Also you will need to provide overloads for various argument lists.
[TestClass]
public class TestExpressions
{
public class MyClass
{
public bool MyMethod(string arg)
{
throw new NotImplementedException();
}
}
private static string UseExpression<T, Ta1>(Expression<Action<T,Ta1>> run)
{
return ((MethodCallExpression)run.Body).Method.Name;
}
[TestMethod]
public void TestExpressionParser()
{
Assert.AreEqual("MyMethod",
UseExpression<MyClass,string>((c,fakeString) => c.MyMethod(fakeString)));
}
}

Categories