Is there a way to pass a method name in a generic manner, without passing its parameters, so it can be invoked by the method, with passed arguments?
Consider this example:
public class Client
{
public string Convert(int value)
{
return value.ToString();
}
}
public class Wrapper<TClient>
{
TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
{
return action(Client, arg);
}
}
I want to be able to pass to the wrapper the method of TClient I want to invoke, and pass the actual arguments along, all generically:
var wrapper = new Wrapper<Client>();
wrapper.Invoke(c => c.Convert, 5);
Is there any possible way to achieve that, without hard coding the method name, or losing its genericness (i.e. by using Delegate)?
Notes:
The Client is an external sealed class that exposes a gazillion methods each of many parameters. I want wrap its behavior and I don't mind writing all the necessary code in the wrapper, but the usage of the wrapper should be as clean as possible.
Update
I want to avoid the need to specify the parameters. The whole idea is having them inferred from the specified action.
You're very close to getting your code to run. There are two options.
First, you can try this:
public class Wrapper<TClient>
{
public TResult Invoke<TArg, TResult>(Func<TArg, TResult> action, TArg arg)
{
return action(arg);
}
}
Then call it like this:
var wrapper = new Wrapper<Client>();
wrapper.Invoke(wrapper.client.Convert, 5);
Or, alternatively, you can do this:
public class Wrapper<TClient>
{
public Wrapper(TClient client)
{
this.Client = client;
}
private TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
{
if (operation.Target != Client)
throw new ArgumentException(nameof(operation));
return action(this.Client, arg);
}
}
And call it like this:
var client = new Client();
var wrapper = new Wrapper<Client>(client);
wrapper.Invoke((c, a) => c.Convert(a), 5);
But, from your description of your problem, I don't see how either of these help and I don't see how to implement what you're asking. Perhaps you need to provide more detail as to what the underlying need you're trying to solve?
You want the expression being passed to Invoke to return a Func that accepts TArg. In code:
public class Wrapper<TClient>
{
TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg)
{
return action(Client)(arg);
}
}
You can then invoke it like so:
class Program
{
static void Main(string[] args)
{
var wrapper = new Wrapper<Client>();
string result = wrapper.Invoke<int, string>(c => c.Convert, 5);
}
}
Since you don't like the approach of having to explicitly specify type arguments, you can use a slightly different API (which comes with its own annoyances):
public class Wrapper<TClient>
{
TClient Client;
public void Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg, out TResult result)
{
return action(Client)(arg);
}
}
You can call this like so, with the return type inferred from the out parameter:
class Program
{
static void Main(string[] args)
{
var wrapper = new Wrapper<Client>();
string result;
wrapper.Invoke(c => c.Convert, 5, out result);
}
}
Related
I’m building a class named CommandHandler that have ExecuteCommand method that have Command as input parameter.
The Idea is that ExcecuteCommand will check command name and execute proper class method by the name pattern so when command name is Test class should have corresponding TestHandler method.
On initialization I’m using reflection to find all methods and create a mapping between command name and created Func<Command, Task<object>>. For now I have achieve this by making all methods return Task<object> and use Delegate.CreateDelegate to create Func<Command, Task<object>> from reflected method but I would like to clean code and allow methods to return simple types like int or Task<custom class>.
I would like to build some simple Expression that for simple types will execute method and do Task.FromResult dynamically so class method remains clean. For Task with specific type result I would like to create expression that will result Task<object> so all could be cached as Dictionary<string, Func<Command, Task<object>>.
public class CommandHandler
{
public Dictionary<string, Func<Command, Task<object>>> methodCache = new Dictionary<string, Func<Command, Task<object>>>();
public int IntCommandHandler(Command c)
{
return 5;
}
public string StringCommandHandler(Command c)
{
return "5";
}
public Task<int> AsyncIntCommandHandler(Command c)
{
return Task.Run(() => 5);
}
public async Task<object> OldWayCommandHandler(Command c)
{
return "5";
}
private void RegisterAsyncQueryHandlers(Dictionary<string, MethodInfo> handlers)
{
var filtered = handlers.Where(h => h.Value.ReturnType == typeof(Task<object>)).ToList();
foreach (var handler in filtered)
{
methodCache.Add(handler.Key, (Func<Command, Task<object>>)Delegate.CreateDelegate(typeof(Func<Command, Task<object>>), this, handler.Value, false));
}
}
public void FillCache()
{
// Get all methods with proper pattern and pass it to RegisterAsyncQueryHandlers in dictionary of command name and MethodInfo
//RegisterAsyncQueryHandlers
}
public Task<object> ExecuteCommand(Command c)
{
return methodCache[c.Name].Invoke(c);
}
}
public class Command
{
public string Name { get; set; }
}
I have no experience with using Expressions and most of the samples I found are using basic operators and static methods. Maybe someone can help me ho w to build such expression?
If I understand correctly, the question is how to convert Task<TResult> to Task<object>.
It can be done for instance using the Task<TResult>.ContinueWith method as follows:
static Task<object> Convert<TResult>(Task<TResult> source)
{
return source.ContinueWith(t => (object)t.Result);
}
It's possible to dynamically build such expression, but the easier would be to put the above method in your class and "call" it via the following Expression.Call overload.
The method that builds expression and compiles a delegate from it could be like this:
Func<Command, Task<object>> MakeFunc(MethodInfo handler)
{
var c = Expression.Parameter(typeof(Command), "c");
var task = Expression.Call(Expression.Constant(this), handler, c);
if (task.Type != typeof(Task<object>))
task = Expression.Call(GetType(), "Convert", new[] { task.Type.GetGenericArguments().Single() }, task);
var expr = Expression.Lambda<Func<Command, Task<object>>>(task, c);
return expr.Compile();
}
I am wondering if there is some way to optimize the using statement to declare and assign its output together (when it is a single value).
For instance, something similar to the new way to inline declare the result variable of an out parameter.
//What I am currently doing:
string myResult;
using(var disposableInstance = new myDisposableType()){
myResult = disposableInstance.GetResult();
}
//That would be ideal
var myResult = using(var disposableInstance = new myDisposableType()){
return disposableInstance.GetResult();
}
//That would be great too
using(var disposableInstance = new myDisposableType(), out var myResult){
myResult = disposableInstance.GetResult();
}
Thanks for your input.
You can use extension method to "simplify" this usage pattern:
public static class Extensions {
public static TResult GetThenDispose<TDisposable, TResult>(
this TDisposable d,
Func<TDisposable, TResult> func)
where TDisposable : IDisposable {
using (d) {
return func(d);
}
}
}
Then you use it like this:
string myResult = new myDisposableType().GetThenDispose(c => c.GetResult());
This is funny, because I started reading Functional Programming in C# a couple of days ago, and one of the first examples is along the lines of:
public static TResult Using<TDisposable, TResult>(TDisposable disposable, Func<TDisposable, TResult> func)
where TDisposable : IDisposable
{
using (disposable)
{
return func(disposable);
}
}
Usage:
var result = Using(new DbConnection(), x => x.GetResult());
Notice that, unlike the other answers posted, this function has absolutely no responsibility but get the result of func, regardless of TDisposable.
No, there is no such shortcut. Your original way is right.
You could wrap this in a function if you do it often enough
public class Utilities
{
public static TReturn GetValueFromUsing<T,TReturn>(Func<T,TReturn> func) where T : IDisposable, new()
{
TReturn result = default(TReturn)
using(var instance = new T())
result = func(instance);
return result;
}
}
usage
var result = Utilities.GetValueFromUsing<myDisposableType,string>(x => x.GetResult());
But man would that be overkill.
The using instruction cannot be used as r-value, and therefore there is no way to assign a value from it.
However, there is a special case to this, and you can use it where convenient: You can return a result from inside the using block.
int F(int arg)
{
using (disposable = GetObj())
{
return disposable.Calculate(arg);
}
}
This form is often communicating the purpose better than a local variable assignment. You can even turn it into a template method, where the method would apply the using construct and then call a strategy and return its result.
class Useful<TDisposable> where TDisposable : IDisposable
{
private Func<TDisposable> Factory { get; }
public Useful(Func<TDisposable> factory)
{
this.Fatory = factory;
}
public TResult SafeDo<TResult>(Func<TDisposable, TResult> operation)
{
using (TDisposable obj = this.Factory())
{
return operation(obj);
}
}
}
This class is completely reusable and its single responsibility is to ensure that disposable components are disposed on use. Instead of working directly with a disposable class, you can wrap it into this wrapper class and consume it that way and you'll have a strict lifetime control over the disposable objects:
void Worker(Useful<MyDisposableClass> wrapper)
{
int arg = 5;
wrapper.SafeDo(disp => disp.Calculate(arg);
}
In this piece of code, the disp object would be constructed and disposed correctly. A concrete argument that would be required by the operation arg is taken from the closure.
Hey I try to cast my object to interface which this object should implements. But during executing code I have following error:
Unable to cast object of type GetTreeHandler to IQueryHandler, IQuery<Tree>.
Why? Everything seems to be ok.
Any idea without using dynamic?
QueryDispatcher
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
if (query == null)
{
throw new ArgumentNullException("Query can not be null.");
}
var handlerType = typeof (IQueryHandler<,>).MakeGenericType(query.GetType(), typeof (TResult));
var handler = _context.Resolve(handlerType);
IQueryHandler<IQuery<TResult>, TResult> castedHandler = (IQueryHandler<IQuery<TResult>, TResult>) handler;
return (TResult) await castedHandler.ExecuteAsync(query);
}
GetTreeHandler
public class GetTreeHandler : IQueryHandler<GetTree, Tree>
{
private readonly ProductContext _context;
public string Name { get; set; }
public GetTreeHandler(ProductContext context)
{
_context = context;
}
public async Task<Tree> ExecuteAsync(GetTree query)
=> await Task.FromResult(
_context.Trees.FirstOrDefault(x => x.Id == query.Id)
);
}
EDIT
My current solution(partially works):
public async Task<TResult> ExecuteAsync<TResult>(IQuery query) where TResult : class
{
if (query == null)
{
throw new ArgumentNullException("Query can not be null.");
}
var handlerType = typeof (IQueryHandler<,>).MakeGenericType(query.GetType(), typeof (TResult));
var handler = _context.Resolve(handlerType);
return await (Task<TResult>)
handler.GetType()
.GetMethod("ExecuteAsync")
.Invoke(handler, new object[]{query});
}
Why partially?
Eg. handlers:
Doesn't work:
public class GetIndexesHandler : IQueryHandler<GetIndexes, IEnumerable<AssocIndexDto>>
Works:
public class GetIndexesHandler : IQueryHandler<GetIndexes,AssocIndexDto>
As you can see these two classes implements the same interface but with different second parameter type.
The problem is that Resolve method cannot find the registered service, but if I try to debug this code, I can see that the wanted service is registed correctly, but it can't be found.
Have you any idea how to solve it?
You are trying to cast an IQueryHandler<GetTree, Tree> to an IQueryHandler<IQuery<Tree>, Tree>, but that would only work when IQueryHandler<TQuery, TResult> was specified as:
interface IQueryHandler<out TQuery, TResult>
Notice the out argument here.
The out keyword marks TQuery as an output argument. In case a generic type argument is marked as output argument, it allows us to cast the interface to something more generic. An IEnumerable<string> for instance can be casted to IEnumerable<object> since IEnumerable<string> will return strings, and they can be represented as objects.
For in arguments however, the opposite holds. When looking at an Action<in T> for intance, we are allowed to cast an Action<BaseType> to Action<SubType>, since the action would always be able to process SubTypes as well. On the other hand, it would be impossible to cast Action<BaseType> to Action<object> since that would allow us to pass in a string to the action as well (since string is an object), but that would then obviously fail at runtime.
So casting an IQueryHandler<GetTree, Tree> to IQueryHandler<IQuery<Tree>, Tree> would only be possible if TQuery is marked with an out keyword, but clearly TQuery is an input argument. The CLR therefore forbids the conversion, since it could lead to errors at runtime.
In your case however, this problem would not exist, because you know that the passed in type always fits. But remember, the CLR is unable to check this, and is therefore blocking the conversion.
One solution is, as I described on my blog, to use the dynamic keyword as follows:
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var handlerType =
typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = _context.Resolve(handlerType);
return (TResult)await castedHandler.ExecuteAsync((dynamic)query);
}
Another option is to specify and register a generic wrapper type that implements an interface that lacks the TQuery generic type. This way you can prevent using dynamic altogether:
public interface IWrapper<TResult>
{
Task<TResult> ExecuteAsync(IQuery<TResult> query);
}
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var wrapperType =
typeof(Wrapper<,>).MakeGenericType(query.GetType(), typeof(TResult));
var wrapper = (IWrapper<TResult>)_context.Resolve(wrapperType);
return wrapper.ExecuteAsync(query);
}
// Don't forget to register this type by itself in Autofac.
public class Wrapper<TQuery, TResult> : IWrapper<TResult>
{
private readonly IQueryHandler<TQuery, TResult> handler;
public Wrapper(IQueryHandler<TQuery, TResult> handler) { this.handler = handler; }
Task<TResult> IWrapper<TResult>.ExecuteAsync(IQuery<TResult> query) =>
this.handler.ExecuteAsync((TQuery)query);
}
I wanted to create an extension method that would efficiently wrap single objects as IEnumerables. This was to avoid the cases where you end up putting a new [] {} in the middle of an expression. This is easy enough to do using the following method:
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this TSource source)
{
return new[] { source };
}
The problem is that this will be applied to any and all types (which is the expected behavior), but this will also have the side effect of making the method available on IEnumerable <T> instances. In the case where the resolved extended type is an IEnumerable<T>, I would simply like to return this IEnumerable, since the aternative is finding myself with a IEnumerable<IEnumerable<T>>, which is not really what you'd expect when calling the method.
Instinctively (and perhaps sleepily), I first created an overload that looked like this
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
in order to handle the case where the type to wrap is an IEnumerable<T>, But of course, the control flow always resolves to the first method.
So, the question is: how could I create such a wrapping method that handles both the case where the extended parameter instance is an IEnumerable<T> and when it is not ?
Here is another attempt, inspired from Eric Lippert's excellent post at: https://stackoverflow.com/a/1451184/4955425.
You can control the overloading resolution by placing your 2 extension methods at different levels in the namespace hierarchy.
namespace MyExtensions
{
public static class HighPrecendenceExtensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
}
namespace LowerPrecedenceNamespace
{
public static class LowPrecedenceExtensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this TSource source)
{
return new[] { source };
}
}
}
}
However, the downside is that you'll always need to refer to both namespaces to get the right method invocation behavior.
using MyExtensions;
using MyExtensions.LowerPrecedenceNamespace;
Have you considered changing your signature a little bit, makes the code a little more complicated but makes the usage extremely simple.
public static class Extensions
{
public static IEnumerable<TSource> WrapAsEnumerable<TSource>(this object source)
{
var allInterfaces = source.GetType().GetInterfaces();
IEnumerable<Type> allEnumerableInterfaces = allInterfaces.Where(t => t.Name.StartsWith("IEnumerable"));
if (!allEnumerableInterfaces.Any())
return new[] { (TSource)source };
IEnumerable<Type> genericEnumerableOfTSource = allEnumerableInterfaces.Where(t => t.GenericTypeArguments.Contains(typeof(TSource)));
// we have a generic implementation
if (genericEnumerableOfTSource.Any())
{
return (IEnumerable<TSource>) source;
}
return new[] { (TSource)source }; ;
}
}
[TestFixture]
public class Tests
{
[Test]
public void should_return_string_an_enumerable()
{
const string aString = "Hello World";
var wrapped = aString.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] {"Hello World"});
}
[Test]
public void should_return_generic_enumerable_unwrapped()
{
var aStringList = new List<string> { "Hello", "World" };
var wrapped = aStringList.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] { "Hello", "World" });
}
[Test]
public void should_return_non_generic_enumerable_unwrapped()
{
var aStringArray = new[] {"Hello", "World"};
var wrapped = aStringArray.WrapAsEnumerable<string>();
wrapped.ShouldAllBeEquivalentTo(new[] { "Hello", "World" });
}
}
I would like to specify a parameter that can accept a method without having to specify generic arguments to produce the MethodInfo of the given method.
For example, I'd like to write code like this:
interface IService
{
object AMethod(int p1, int p2);
}
IThingy<IService>() thingy;
thingy.Add(svc => svc.AMethod);
The closest options I can produce are:
interface IThingy<TService>
{
void Add1<T0, T1, TResult>(Expression<Func<TService, Func<T0, T1, TResult>>> expression);
void Add2(Expression<Func<TService, Func<int, int, object>>> expression);
void Add3(Expression<Action<TService>> expression);
}
thingy.Add1<int, int, object>(svc => svc.AMethod);
thingy.Add2(svc => svc.AMethod);
thingy.Add3(svc => svc.AMethod(0, 0));
Add1 implies many Func overloads, which I'm ok with, but cannot be called without specifying the generic parameters.
Add2 requires no generic parameters, but implies a specific overload for every parameter signature.
Add3 requires a call to the method, including fake parameters.
FYI, I will process the expression to get the MethodInfo of the given method like this:
MemberInfo GetMemberFromExpression<T>(Expression<ActionT>> expression)
{
return ((MethodCallExpression)expression.Body).Method
}
GetMemberFromExpression(svc => svc.AMethod(0, 0));
Passing methods to expressions with their invoked values
You can use the GetMemberFromExpression method as you have it, and then simply remove the Generic parameter. As follows:
static void Main(string[] args)
{
var memberInfo1 = GetMemberFromExpression(() => Method1(10, 20));
var memberInfo2 = GetMemberFromExpression(() => Method2());
var memberInfo3 = GetMemberFromExpression(() => Method3("string", 15, DateTime.Now));
Console.WriteLine(memberInfo1.Name);
Console.WriteLine(memberInfo2.Name);
Console.WriteLine(memberInfo3.Name);
Console.Read();
}
public static MemberInfo GetMemberFromExpression(Expression<Action> expression)
{
return ((MethodCallExpression)expression.Body).Method;
}
public static object Method1(int p1, int p2)
{
return p1 + p2;
}
public static void Method2()
{
// No return
}
public static double Method3(string p1, int p2, DateTime p3)
{
return 10d;
}
You'll see that the GetMemberFromExpression will return MethodInfo of any method you pass it, regardless or parameter type and return type.
Ignoring overloads, invoking on instance and name
If you're not concerned about overloads, you could probably use simple reflection instead of building up Expressions. The nameof operator in c# 6 would be a better approach than passing in the name as a string (compile-time checking).
public static MemberInfo GetMemberInfo(Type type, string methodName)
{
return type.GetMethod(methodName);
}
Note, theres no validation checks in this method, just to show the concept.
The above method will work for any instance or static methods. Simply pass the instance type / or static class type and the method name as follows:
MyClass cl = new MyClass();
var methodInfo1 = GetMemberInfo(cl.GetType(), "AMethod");
var methodInfo2 = GetMemberInfo(typeof(MyClass), "AStaticMethod");
Here's MyClass with the methods:
class MyClass
{
public void AMethod(int a, int b)
{
// instance method
}
public static bool AStaticMethod(bool a, bool b)
{
return a & b; // static method
}
}
This way you don't pass any parameters because you're simply investigating the definition and not invoking.
Using Expressions with types rather than values
Here's a third option. This way you have:
Compile-time checking,
No need to pass valued ("fake") parameters,
Only the parameter types required (which ensures overloaded methods will work).
Create a class catering for the Action and Func overloads:
public class Method
{
public static MethodInfo GetInfo<TReturn>(Func<TReturn> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TReturn>(Func<TP1, TReturn> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TP2, TReturn>(Func<TP1, TP2, TReturn> method)
{
return method.Method;
}
//... Continue with some more Func overloads
public static MethodInfo GetInfo(Action method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1>(Action<TP1> method)
{
return method.Method;
}
public static MethodInfo GetInfo<TP1, TP2>(Action<TP1, TP2> method)
{
return method.Method;
}
//... Continue with some more Action overloads
}
Now you can simply get your MethodInfo as follows:
var methodInfo1 = Method.GetInfo<int, int>(cl.AMethod);
var methodInfo2 = Method.GetInfo<bool, bool, bool>(MyClass.AStaticMethod);
Yes you'll have to create a bunch of overloads in the Method class for Action and Func, but that's a once off thing you'll do and .NET does the same with the Action and Func delegates to cater for all the overloads.