I want to write a closure and increment it's value but i'm not able to do it. Here is my code
int i = 0;
Expression<Func<bool>> closurExpression = () =>
{
i++;
return i != 0;
};
but i get multuple errors about A lambda expression with a statement body cannot be converted to an expression tree or An expression tree may not contain an assignment operator etc. Is it possible without using external tools as Mono.Cecil etc?
for the question: why am I asking for it. I want to write a simple wrapper (for a signature Func<T,T> at least that will calculate count of calls. For example:
Wrapper<int> wrapper = () => 5;
for(int i = 0; i < 10; i++)
wrapper();
int calls = wrapper.Calls; // 10;
my first realisation was:
class FunctionWithCounter<T, TResult>
{
private readonly Func<T, TResult> function;
public int Calls { get; set; }
private FunctionWithCounter(Func<T, TResult> function)
{
Calls = 0;
this.function = function;
}
public static implicit operator FunctionWithCounter<T, TResult>(Func<T, TResult> func)
{
return new FunctionWithCounter<T, TResult>(func);
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg);
}
}
}
but after i get that recurcive functions won't work properly. For example for this code
int fact(int n) { return n < 2 ? 1 : n * fact(n - 1); }
Calls count will be 1 for any n. So idea is: get source function, and inject increment of Calls for every call of method increment it. All inner calls of method somefunc should be replaced by our method funcWithInjection, in this case we'll catch recursive functions too. Here is my code, but it doesn't work (except inject, so this code really increments a field value, but I cannot add source's method body to the tail and compile it, you can play with it if you will):
public class FunctionWithCounter<T, TResult> where T : new()
{
private readonly Func<T, TResult> _functionWithInjection;
private int _calls;
public int Calls
{
get
{
return _calls;
}
}
public FunctionWithCounter(Func<T, TResult> function)
{
_calls = 0;
var targetObject = function.Target ?? new object();
var dynMethod = new DynamicMethod(new Guid().ToString(), typeof(TResult), new[] { targetObject.GetType(), typeof(T), typeof(FunctionWithCounter<T, TResult>) }, true);
var ilGenerator = GenerateInjection(dynMethod);
ilGenerator.Emit(OpCodes.Ret);
var resDelegate = dynMethod.CreateDelegate(typeof(Func<T, FunctionWithCounter<T, TResult>, TResult>), targetObject);
var functionWithInjection = (Func<T, FunctionWithCounter<T, TResult>, TResult>)resDelegate;
var targetMethodBody = function.Method.GetMethodBody();
Debug.Assert(targetMethodBody != null, "mbody != null");
//here i need to write method body in the tail of dynamic method.
_functionWithInjection = function;
_functionWithInjection = t =>
{
functionWithInjection(t, this);
return default(TResult);
};
//finally here should be _functionWithInjection = t => functionWithInjection(t, this);
}
private ILGenerator GenerateInjection(DynamicMethod method)
{
var callsFieldInfo = GetType().GetField("_calls", BindingFlags.NonPublic | BindingFlags.Instance);
Debug.Assert(callsFieldInfo != null, "callsFieldInfo != null");
var ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Nop);
ilGenerator.Emit(OpCodes.Ldarg_2);
ilGenerator.Emit(OpCodes.Dup);
ilGenerator.Emit(OpCodes.Ldfld, callsFieldInfo);
ilGenerator.Emit(OpCodes.Ldc_I4_1);
ilGenerator.Emit(OpCodes.Add);
ilGenerator.Emit(OpCodes.Stfld, callsFieldInfo);
return ilGenerator;
}
public static implicit operator FunctionWithCounter<T, TResult>(Func<T, TResult> func)
{
return new FunctionWithCounter<T, TResult>(func);
}
public TResult this[T arg]
{
get
{
return _functionWithInjection(arg);
}
}
}
My second realisation was based on Emit API, but it's too complex and It was unfinished for a long time...
So now this is my 3rd try and i want to use expressions. Шt should look something like this:
public FunctionWithCounter(Expression<Func<T, TResult>> function)
{
Action action = () => _calls++;
Expression<Action> closurExpression = () => action();
var result = Expression.Block(closurExpression, function);
_functionWithInjection = Expression.Lambda<Func<T,TResult>>(result).Compile();
}
sorry for my english, but i really want to realize this idea
Well, you can do sidestep the rules using Interlocked.Increment:
int i = 0;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
... but I would be very cautious about doing so. I wouldn't expect many pieces of code which deal with expression trees to handle this terribly cleanly, given the side-effect involved.
The above does seem to work, in terms of behaving how I'd expect it to:
int i = -2;
Expression<Func<bool>> expression = () => Interlocked.Increment(ref i) != 0;
var del = expression.Compile();
Console.WriteLine(del()); // True
Console.WriteLine(del()); // False
Console.WriteLine(del()); // True
Console.WriteLine(del()); // True
Console.WriteLine(i); // 2
I think that your first approach was cleaner and ok for simple, non-recursive cases.
If you allow your wrapped functions to be aware of recursion, you can take it a little further and make the wrapper an argument to the function itself:
class RecursiveFunctionWithCounter<T, TResult>
{
private readonly Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function;
public int Calls { get; set; }
public RecursiveFunctionWithCounter(Func<T, RecursiveFunctionWithCounter<T, TResult>, TResult> function)
{
Calls = 0;
this.function = function;
}
public TResult this[T arg]
{
get
{
Calls++;
return function(arg, this);
}
}
}
And use it like this:
var rw = new RecursiveFunctionWithCounter<int, int>(
(n, self) => { return n < 2 ? 1 : n * self[n - 1]; }
);
int rr = rw[3]; // rr=6
int rc = rw.Calls; // rc=3
On the other hand, if what you really want to do is instrument some existing methods in your code, consider doing a little Aspect Oriented Programming (with PostSharp for instance, this is an example of an aspect that increments a performance counter on each method call). This way you could just add an attribute like IncrementPerformanceCounterAttribute to your methods and the AOT library will do the rest.
Related
Here is a sample Scala code that I'm trying to rewrite in C#:
trait FuncHolder[T, TResult] {
def Value: Function1[T, TResult]
}
object FuncHolder {
def GetFunctionHolder[T, TResult](func: Function1[T, TResult]) = new FuncHolder[T, TResult] {
override def Value: Function1[T, TResult] = func
}
}
Here is where I started:
public abstract class FuncHolder<T, TResult>
{
public Func<T, TResult> Value { get; }
protected FuncHolder(Func<T, TResult> value)
{
Value = value;
}
}
public static class FuncHolder
{
public static FuncHolder<T, TResult> GetFuncHolder<T, TResult>(Func<T, TResult> func)
{
var ilBody = func.Method.GetMethodBody().GetILAsByteArray();
}
}
But then I stuck because I'm not sure if I could just copy that byte array in il.emit and it will work. So I thought maybe in 2019 there could be some ways in acheiving it without dirty magic, postsharping output binaries or something. I'm looking for a pure solution in terms of BCL and Expressions/DynamicMethods.
The most recent attempt is following:
public abstract class FuncHolder<T, TResult>
{
public abstract TResult GetResult(T value);
}
public static class FuncHolder
{
private static ModuleBuilder _builder = AssemblyBuilder
.DefineDynamicAssembly(new AssemblyName("OmsCodegen"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("MainModule");
/// <summary>
/// Returns a holder that allows safely pass delegates through the network
/// </summary>
/// <param name="func">Func to hold. Note that it must be pure function, closure with external dependencies will fail</param>
public static FuncHolder<T, TResult> GetFuncHolder<T, TResult>(Func<T, TResult> func)
{
var tb = _builder.DefineType($"<{func.Method.MetadataToken}>__FuncHolder", TypeAttributes.Class | TypeAttributes.Sealed);
tb.SetParent(typeof(FuncHolder));
var baseMethod = typeof(FuncHolder<,>).GetMethod("GetResult");
Debug.Assert(baseMethod != null);
var implementation = tb.DefineMethod(baseMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual);
CopyIl(implementation, func.Method);
tb.DefineMethodOverride(implementation, baseMethod);
tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName);
return (FuncHolder<T, TResult>) Activator.CreateInstance(tb.CreateTypeInfo().AsType());
}
private static void CopyIl(MethodBuilder implementation, MethodInfo methodInfo)
{
var ilGenerator = implementation.GetILGenerator();
var methodBody = methodInfo.GetMethodBody();
var il = methodBody?.GetILAsByteArray() ?? throw new InvalidOperationException("Cannot get method body");
foreach (var local in methodBody.LocalVariables)
ilGenerator.DeclareLocal(local.LocalType);
var opCodes = GetOpCodes(il);
for (int i = 0; i < opCodes.Length; ++i)
{
if (!opCodes[i].code.HasValue)
continue;
OpCode opCode = opCodes[i].code.Value;
if (opCode.OperandType == OperandType.InlineBrTarget)
{
ilGenerator.Emit(opCode, BitConverter.ToInt32(il, i + 1));
i += 4;
continue;
}
if (opCode.OperandType == OperandType.ShortInlineBrTarget)
{
ilGenerator.Emit(opCode, il[i + 1]);
++i;
continue;
}
if (opCode.OperandType == OperandType.InlineType)
{
Type tp = methodInfo.Module.ResolveType(BitConverter.ToInt32(il, i + 1), methodInfo.DeclaringType.GetGenericArguments(), methodInfo.GetGenericArguments());
ilGenerator.Emit(opCode, tp);
i += 4;
continue;
}
if (opCode.FlowControl == FlowControl.Call)
{
MethodInfo mi = methodInfo.Module.ResolveMethod(BitConverter.ToInt32(il, i + 1)) as MethodInfo;
if (mi == methodInfo)
ilGenerator.Emit(opCode, implementation);
else
ilGenerator.Emit(opCode, mi);
i += 4;
continue;
}
ilGenerator.Emit(opCode);
}
}
static OpCodeContainer[] GetOpCodes(byte[] data)
{
List<OpCodeContainer> opCodes = new List<OpCodeContainer>();
foreach (byte opCodeByte in data)
opCodes.Add(new OpCodeContainer(opCodeByte));
return opCodes.ToArray();
}
class OpCodeContainer
{
public OpCode? code;
byte data;
public OpCodeContainer(byte opCode)
{
data = opCode;
try
{
code = (OpCode)typeof(OpCodes).GetFields().First(t => ((OpCode)(t.GetValue(null))).Value == opCode).GetValue(null);
}
catch
{
// if it throws an exception then code should remain null
}
}
}
}
Which fails with CLR execution error.
It's not exactly what I wanted but it's the only solution I came with
public abstract class FuncHolder<T, TResult>
{
[JsonIgnore]
public abstract Func<T, TResult> Value { get; }
}
public static class FuncHolder
{
private static Dictionary<int, object> _metadataTokenToMethodDictionary = new Dictionary<int, object>();
private class FuncHolderImplementation<T, TResult> : FuncHolder<T, TResult>
{
public int MetadataToken { get; }
public FuncHolderImplementation(int metadataToken)
{
MetadataToken = metadataToken;
}
public override Func<T, TResult> Value => (Func<T, TResult>)_metadataTokenToMethodDictionary[MetadataToken];
}
public static FuncHolder<T, TResult> GetFuncHolder<T, TResult>(Func<T, TResult> func)
{
if (!_metadataTokenToMethodDictionary.ContainsKey(func.Method.MetadataToken))
{
_metadataTokenToMethodDictionary[func.Method.MetadataToken] = func;
}
return new FuncHolderImplementation<T, TResult>(func.Method.MetadataToken);
}
}
Instead of wrapping a function in the type I merely pass a metadataToken which I then convert back.
Why is this needed may be shown as following:
var holder = FuncHolder.GetFuncHolder<string, int>(s => s.Length);
var settings = new JsonSerializerSettings {TypeNameHandling = TypeNameHandling.All};
var json = JsonConvert.SerializeObject(holder, settings);
var holder2 = JsonConvert.DeserializeObject<FuncHolder<string, int>>(json, settings);
Console.WriteLine(holder2.Value("hello"));
As you can see, this way function callback may be serialized and deserialized back.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I know this topic (memoization) has been discussed quite a bit (like here), but no answer I could find satisfies the DRY principle as much as I would like, so please, read this whole question and the three points I want to address.
I have a simple support class like this:
public class Memoized<T1, TResult>
{
private readonly Func<T1, TResult> _f;
private readonly Dictionary<T1, TResult> _cache = new Dictionary<T1, TResult>();
public Memoized(Func<T1, TResult> f)
{
_f = f;
}
public TResult Invoke(T1 p1)
{
if (p1 == null) throw new ArgumentNullException(nameof(p1));
if (_cache.TryGetValue(p1, out var res)) return res;
return _cache[p1] = _f(p1);
}
public static Func<T1, TResult> Of(Func<T1, TResult> f)
{
var memo = new Memoized<T1, TResult>(f);
return x => memo.Invoke(x);
}
}
Nothing especially fancy, but it allows me to do this:
public class MyClass
{
public Func<int, bool> MemoizedMethod { get; }
private bool UncachedMethod(int v)
{
return v > 0;
}
public MyClass()
{
MemoizedMethod = Memoized<int, bool>.Of(UncachedMethod);
}
}
Now, even if the resulting code is not terribly noisy, I'm trying to figure out if the implementation could be more elegant, because currently I need:
an invokable property that acts as a Method.
a true method that should not be called directly.
a line in the constructor (cannot be an inline initialization) that links the two (with a third repetition of the function signature!).
Any suggestion for a strategy that allows to remove one (or two!) of the above points would be great.
In my struggle for elegance, I finally found what I think is the best syntax I saw anywhere:
private class MemoizedTest
{
private int _counter = 0;
public int Method(int p) => this.Memoized(p, x =>
{
return _counter += x;
});
}
Implementation (one pretty small extension class):
namespace System
{
public static class MemoizerExtension
{
internal static ConditionalWeakTable<object, ConcurrentDictionary<string, object>> _weakCache =
new ConditionalWeakTable<object, ConcurrentDictionary<string, object>>();
public static TResult Memoized<T1, TResult>(
this object context,
T1 arg,
Func<T1, TResult> f,
[CallerMemberName] string? cacheKey = null)
where T1 : notnull
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (cacheKey == null) throw new ArgumentNullException(nameof(cacheKey));
var objCache = _weakCache.GetOrCreateValue(context);
var methodCache = (ConcurrentDictionary<T1, TResult>) objCache
.GetOrAdd(cacheKey, _ => new ConcurrentDictionary<T1, TResult>());
return methodCache.GetOrAdd(arg, f);
}
}
}
Explanation
In the implementation I'm using a ConditionalWeakTable for caching, effectively extending the internal structure of the object invoking the memoization. As an additional key, the CallerMemberName is used, acting as a second key (this allows more memoizations for instance, and optionally more memoizations per method, if passing the cacheKey parameter explicitly).
The third key is the parameter of the invocation.
So, we have 3 runtime dictionary-like searches instead of 1, but a syntax that is a lot cleaner, IMO.
Is it worth it? I dunno, but my desire for elegance is satiated.
If someone else is interested, I'm including the tests for reference:
[TestFixture]
public class MemoizerTest
{
[Test]
public void MemoizationWorksOnFuncs()
{
int counter = 0;
Func<int, int> f = x => counter += x;
Assert.That(this.Memoized(1, f), Is.EqualTo(1));
Assert.That(this.Memoized(2, f), Is.EqualTo(3));
Assert.That(this.Memoized(2, f), Is.EqualTo(3));
Assert.That(this.Memoized(1, f), Is.EqualTo(1));
}
private class MemoizedTest
{
private int _counter = 0;
public int Method(int p)
=> this.Memoized(p, x => { return _counter += x; });
}
[Test]
public void MemoizationWorksOnInstances()
{
var obj1 = new MemoizedTest();
Assert.That(obj1.Method(5), Is.EqualTo(5));
Assert.That(obj1.Method(4), Is.EqualTo(9));
Assert.That(obj1.Method(5), Is.EqualTo(5));
Assert.That(obj1.Method(1), Is.EqualTo(10));
Assert.That(obj1.Method(4), Is.EqualTo(9));
obj1 = new MemoizedTest();
Assert.That(obj1.Method(5), Is.EqualTo(5));
Assert.That(obj1.Method(4), Is.EqualTo(9));
Assert.That(obj1.Method(5), Is.EqualTo(5));
Assert.That(obj1.Method(1), Is.EqualTo(10));
Assert.That(obj1.Method(4), Is.EqualTo(9));
}
[Test]
[Ignore("This test passes only when compiled in Release mode")]
public void WeakMemoizationCacheIsCleared()
{
var obj1 = new MemoizedTest();
var r1 = obj1.Method(5);
MemoizerExtension._weakCache.TryGetValue(obj1, out var cache);
var weakRefToCache = new WeakReference(cache);
cache = null;
GC.Collect(2);
obj1 = null;
GC.Collect();
GC.Collect();
var msg = weakRefToCache.TrackResurrection;
Assert.That(weakRefToCache.IsAlive, Is.False, "The weak reference should be dead.");
Assert.That(r1, Is.EqualTo(5));
}
}
If you capture the dictionary in the lambda, your state will be maintained implicitly.
public class Memoized
{
// Example with a single parameter. That parameter becomes the key to the dictionary.
public static Func<T1, TRet> Of<T1, TRet>(Func<T1, TRet> f)
{
ConcurrentDictionary<T1, TRet> cache = new ConcurrentDictionary<T1, TRet>();
return (arg1) => cache.GetOrAdd(arg1, xarg=>f(xarg));
}
// Example with two parameters. The key is a tuple, and it must be unpacked before calling func.
// Three or more parameters generalize from this
public static Func<T1, T2, TRet> Of<T1, T2, TRet>(Func<T1, T2, TRet> f)
{
ConcurrentDictionary<Tuple<T1,T2>, TRet> cache = new ConcurrentDictionary<Tuple<T1, T2>, TRet>();
return (arg1, arg2) => cache.GetOrAdd(new Tuple<T1,T2>(arg1, arg2),
(xarg)=>f(xarg.Item1, xarg.Item2)
);
}
}
Usage example:
class Test
{
public int Method(String s, String s2)
{
return 99;
}
}
class Program
{
static bool UncachedMethod(int x) { return x > 0; }
static void Main(string[] args)
{
var cached = Memoized.Of<int,bool>(UncachedMethod);
var exampleCall = cached(44);
var exampleCall2 = cached(44);
// Capture a non-static member function
var x = new Test();
var cachedX = Memoized.Of<String, String,int>(x.Method);
var exampleCall3 = cachedX("a","b");
}
}
Doing Add for two elements like T a, T b is simple, Mark has provided a good solution using Expression tree here, which translates into following and is simple to use:
static T Add<T>(T a, T b)
{
// Declare Parameter Expressions
ParameterExpression paramA = Expression.Parameter(typeof(T), "valueA"),
paramB = Expression.Parameter(typeof(T), "valueB");
// add the parameters together
BinaryExpression body = Expression.Add(paramA, paramB);
// Compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// Call it
return add(a, b);
}
Challenge that I have is there's a collection of List<T>, where all elements have to added as shown above. I have tried following, on same lines as above, but it doesn't work:
static T AddAll<T>(List<T> list)
{
var parameterExpressionList = list.Select((x,i) => (Expression)Expression.Parameter(typeof(T), "value"+i));
var body = parameterExpressionList
.Skip(1)
.Aggregate(parameterExpressionList.First(),
(paramA, paramB) => Expression.Add(paramA, paramB));
// Compile it
Func<List<T>, T> addAll = Expression.Lambda<Func<List<T>, T>>(body, parameterExpressionList.Cast<ParameterExpression>()).Compile();
return addAll(list);
}
Run-time error that I get is: Incorrect number of parameters supplied for lambda declaration. Any pointer, how to achieve, please note, I don't need a solution where I cumulatively pick two elements from actual list and call Add<T>(T a, T b) , since that would lead to multiple times compilation of the Expression tree, which is not efficient, as I would have > 100 K data points, any suggestion to make my code work would be great, I am not sure where it is going wrong.
Since you have created a generic function, just use it on the list (I added an optional Adder method to handle non-standard classes):
static T AddAll<T>(IEnumerable<T> src, Func<T, T, T> adder = null) {
// Declare Parameter Expressions
ParameterExpression paramA = Expression.Parameter(typeof(T), "valueA"),
paramB = Expression.Parameter(typeof(T), "valueB");
// add the parameters together
BinaryExpression body;
if (adder == null)
body = Expression.Add(paramA, paramB);
else
body = Expression.Add(paramA, paramB, adder.GetMethodInfo());
// Compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// Call it
return src.Aggregate(default(T), (ans, n) => add(ans, n));
}
You can use the Adder parameter to handle things like strings:
var ans = AddAll(new[] { "a", "b", "c" }, String.Concat);
Since we know the type of T at compile time though, we can just call Sum:
static T AddAll2<T>(IEnumerable<T> src) {
var paramA = Expression.Parameter(typeof(IEnumerable<T>), "valueA");
var method = typeof(Enumerable).GetMethod("Sum", new[] { typeof(IEnumerable<T>) });
if (method != null) {
// Create lambda body
var body = Expression.Call(method, paramA);
// Compile it
Func<IEnumerable<T>, T> sum = Expression.Lambda<Func<IEnumerable<T>, T>>(body, paramA).Compile();
// Call it
return sum(src);
}
else
return default(T);
}
Of course, if you are going to call Sum, you don't need a lambda:
static T AddAll3<T>(IEnumerable<T> src) {
var method = typeof(Enumerable).GetMethod("Sum", new[] { typeof(IEnumerable<T>) });
if (method != null) {
// Call it
return (T)method.Invoke(null, new[] { src });
}
else
return default(T);
}
Just try to get every item from your list and then accumulate they into result.
static T AddAll<T>(List<T> list)
{
if (list.Count == 0)
{
// It's additional small case
return default(T);
}
var listParam = Expression.Parameter(typeof(List<T>));
var propInfo = typeof(List<T>).GetProperty("Item");
var indexes = list.Select((x, i) => Expression.MakeIndex(listParam, propInfo, new[] { Expression.Constant(i) }));
Expression sum = indexes.First();
foreach (var item in indexes.Skip(1))
{
sum = Expression.Add(sum, item);
}
var lambda = Expression.Lambda<Func<List<T>, T>>(sum, listParam).Compile();
return lambda(list);
}
You can pass list directly as argument and just create sum via indexes:
static T AddAll<T>(List<T> list)
{
if (list.Count == 0) return default(T);
if (list.Count == 1) return list[0];
var indexerProperty = typeof(List<T>).GetProperty("Item");
var p = Expression.Parameter(typeof(List<T>));
var exp = Expression.Add(
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(0) }),
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(1) }));
for (var i = 2; i < list.Count; i++)
{
exp = Expression.Add(
exp,
Expression.MakeIndex(p, indexerProperty, new [] { Expression.Constant(i) }));
}
var lambda = Expression.Lambda<Func<List<T>, T>>(exp, p).Compile();
return lambda(list);
}
Store all applicable Enumerable.Sum overloads in a dictionary:
// all methods with signature public static T Enumerable.Sum(IEnumerable<T>) by element type
private static readonly Dictionary<Type, MethodInfo> _sumMethodsByElementType = typeof(Enumerable)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Where(m => m.Name == "Sum" && !m.IsGenericMethod)
.Select(m => new { Method = m, Parameters = m.GetParameters() })
.Where(mp => mp.Parameters.Length == 1)
.Select(mp => new { mp.Method, mp.Parameters[0].ParameterType })
.Where(mp => mp.ParameterType.IsGenericType && mp.ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
.Select(mp => new { mp.Method, ElementType = mp.ParameterType.GetGenericArguments()[0] })
.Where(me => me.Method.ReturnType == me.ElementType)
.ToDictionary(mp => mp.ElementType, mp => mp.Method);
Invoke the corresponding one from inside the generic AddAll (or Sum as I prefer to call it) method:
public static T Sum<T>(IEnumerable<T> summands)
{
MethodInfo sumMethod;
if (!_sumMethodsByElementType.TryGetValue(typeof(T), out sumMethod)) throw new InvalidOperationException($"Cannot sum elements of type {typeof(T)}.");
return (T)sumMethod.Invoke(null, new object[] { summands });
}
Test:
Console.WriteLine(Sum(new[] { 1, 2, 3 }));
Console.WriteLine(Sum(new[] { 1, 2, 3, default(int?) }));
Console.WriteLine(Sum(new[] { 1.1, 2.2, 3.3 }));
Console.WriteLine(Sum(new[] { 1.1, 2.2, 3.3, default(double?) }));
try { Console.WriteLine(Sum(new[] { 'a', 'b', 'c' })); }
catch (InvalidOperationException ex) { Console.WriteLine(ex.Message); }
Output:
6
6
6.6
6.6
Cannot sum elements of type System.Char.
You don't necessarily need to solve every part of the problem with expressions, if you are just interested in the operation itself
Here's an implementation that uses Singleton via the Lazy<> type for the default addition of type T (instead of static methods)
The LinqExpression expression could potentially be reused if you really need expressions (say, in an EF scenario), but there's no equivalent expression for the AddAll operation... though it can potentially be expanded to support a generic expression for AddAll
public abstract class Addition<T>
{
private readonly Lazy<Expression<Func<T, T, T>>> _lazyExpression;
private readonly Lazy<Func<T, T, T>> _lazyFunc;
public Func<T, T, T> Execute
{
get { return _lazyFunc.Value; }
}
public Expression<Func<T, T, T>> LinqExpression
{
get { return _lazyExpression.Value; }
}
protected Addition()
{
_lazyExpression = new Lazy<Expression<Func<T, T, T>>>(InitializeExpression);
_lazyFunc = new Lazy<Func<T, T, T>>(() => LinqExpression.Compile());
}
protected abstract Expression<Func<T, T, T>> InitializeExpression();
}
public sealed class DefaultAddition<T> : Addition<T>
{
private static readonly Lazy<DefaultAddition<T>> _lazyInstance = new Lazy<DefaultAddition<T>>(() => new DefaultAddition<T>());
public static DefaultAddition<T> Instance
{
get {return _lazyInstance.Value; }
}
// Private constructor, you only get an instance via the Instance static property
private DefaultAddition()
{
}
protected override Expression<Func<T, T, T>> InitializeExpression()
{
var paramX = Expression.Parameter(typeof(T), "x");
var paramY = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(paramX, paramY);
return Expression.Lambda<Func<T, T, T>>(body, paramX, paramY);
}
}
public static class Operations
{
public static T Add<T>(T x, T y)
{
return DefaultAddition<T>.Instance.Execute(x, y);
}
public static T AddAll<T>(IEnumerable<T> enumerable)
{
var itemAdd = DefaultAddition<T>.Instance.Execute;
return enumerable.Aggregate(default(T), (result, item) => itemAdd(result, item));
// This might be more efficient than Aggregate, but I didn't benchmark it
/*
var result = default(T);
foreach (var item in enumerable)
{
result = itemAdd(result, item);
}
return result;
*/
}
}
Usage:
// Can mix double with int :)
var doubleAdd = Operations.Add(4.5, 3);
// Can mix decimal with int :)
var listAdd = Operations.AddAll(new[] {3, 6.7m, 0.3m});
// Even empty enumerables
var shortAdd = Operations.AddAll(Enumerable.Empty<short>());
// This will not work for byte. System.Byte should be casted to System.Int32
// Throws "InvalidOperationException: The binary operator Add is not defined for the types 'System.Byte' and 'System.Byte'."
var byteAdd = Operations.AddAll(new byte[] {1, 2, 3});
If your T is of value type like int, long, double etc. then you can simply do this:
//add
//using System.Linq;
var items = new List<int>();
items.Add(1);
items.Add(5);
items.Add(10);
var sum = items.Sum();
(based on an email conversation, now recorded for information sharing) I have two models used at different layers:
public class TestDTO {
public int CustomerID { get; set; }
}
//...
public class Test {
public int CustomerID { get; set; }
}
and a lambda in terms of my DTO layer:
Expression<Func<TestDTO, bool>> fc1 =
(TestDTO c1) => c1.CustomerID <= 100 && c1.CustomerID >= 10;
How can I convert that lambda (in the general case) to talking about the other model:
Expression<Func<Test, bool>> fc2 = {insert magic here, based on fc1}
(obviously, we're after the same test-condition, but using the Test type)
?
To do that, you'll have to rebuild the expression-tree completely; the parameters will need re-mapping, and all member-access that is now talking to different types will need to be reapplied. Fortunately, a lot of this is made easier by the ExpressionVisitor class; for example (doing it all in the general case, not just the Func<T,bool> predicate usage):
class TypeConversionVisitor : ExpressionVisitor
{
private readonly Dictionary<Expression, Expression> parameterMap;
public TypeConversionVisitor(
Dictionary<Expression, Expression> parameterMap)
{
this.parameterMap = parameterMap;
}
protected override Expression VisitParameter(ParameterExpression node)
{
// re-map the parameter
Expression found;
if(!parameterMap.TryGetValue(node, out found))
found = base.VisitParameter(node);
return found;
}
protected override Expression VisitMember(MemberExpression node)
{
// re-perform any member-binding
var expr = Visit(node.Expression);
if (expr.Type != node.Type)
{
MemberInfo newMember = expr.Type.GetMember(node.Member.Name)
.Single();
return Expression.MakeMemberAccess(expr, newMember);
}
return base.VisitMember(node);
}
}
Here, we pass in a dictionary of parameters to re-map, applying that in VisitParameter. We also, in VisitMember, check to see if we've switched type (which can happen if Visit involves a ParameterExpression or another MemberExpression, at any point): if we have, we'll try and find another member of the same name.
Next, we need a general purpose lambda-conversion rewriter method:
// allows extension to other signatures later...
private static Expression<TTo> ConvertImpl<TFrom, TTo>(Expression<TFrom> from)
where TFrom : class
where TTo : class
{
// figure out which types are different in the function-signature
var fromTypes = from.Type.GetGenericArguments();
var toTypes = typeof(TTo).GetGenericArguments();
if (fromTypes.Length != toTypes.Length)
throw new NotSupportedException(
"Incompatible lambda function-type signatures");
Dictionary<Type, Type> typeMap = new Dictionary<Type,Type>();
for (int i = 0; i < fromTypes.Length; i++)
{
if (fromTypes[i] != toTypes[i])
typeMap[fromTypes[i]] = toTypes[i];
}
// re-map all parameters that involve different types
Dictionary<Expression, Expression> parameterMap
= new Dictionary<Expression, Expression>();
ParameterExpression[] newParams =
new ParameterExpression[from.Parameters.Count];
for (int i = 0; i < newParams.Length; i++)
{
Type newType;
if(typeMap.TryGetValue(from.Parameters[i].Type, out newType))
{
parameterMap[from.Parameters[i]] = newParams[i] =
Expression.Parameter(newType, from.Parameters[i].Name);
}
else
{
newParams[i] = from.Parameters[i];
}
}
// rebuild the lambda
var body = new TypeConversionVisitor(parameterMap).Visit(from.Body);
return Expression.Lambda<TTo>(body, newParams);
}
This takes an arbitrary Expression<TFrom>, and a TTo, converting it to an Expression<TTo>, by:
finding which types are different between TFrom / TTo
using that to re-map the parameters
using the expression-visitor we just created
and finally constructing a new lambda expression for the desired signature
Then, putting it all together and exposing our extension method:
public static class Helpers {
public static Expression<Func<TTo, bool>> Convert<TFrom, TTo>(
this Expression<Func<TFrom, bool>> from)
{
return ConvertImpl<Func<TFrom, bool>, Func<TTo, bool>>(from);
}
// insert from above: ConvertImpl
// insert from above: TypeConversionVisitor
}
et voila; a general-purpose lambda conversion routine, with a specific implementation of:
Expression<Func<Test, bool>> fc2 = fc1.Convert<TestDTO, Test>();
You could use AutoMapper (no expression tree):
Mapper.CreateMap<Test, TestDTO>();
...
Func<TestDTO, bool> fc1 =
(TestDTO c1) => c1.CustomerID <= 100 && c1.CustomerID >= 10;
Func<Test, bool> fc2 =
(Test t) => fc1(Mapper.Map<Test, TestDTO>(t));
I am trying to refactor this code into a more elegant version. Can anyone please help.
The issue is where to as sign the first evaluation result for comparision later on?
And I want to eliminate the use of if/switch if possible
Should I remove Operator class and split Eval into And and Or class, but wouldn't be too much differnt I think
public interface IEval<T>
{
Func<T, bool> Expression { get; }
Operator Operator { get; }
string Key { get; }
}
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
var returnResult = true;
var counter = 0;
foreach (var condition in conditions)
{
var tempResult = condition.Expression(o);
if (counter == 0) //don't like this
{
returnResult = tempResult;
counter++;
}
else
{
switch (condition.Operator) //don't like this
{
case Operator.And:
returnResult &= tempResult;
break;
case Operator.Or:
returnResult |= tempResult;
break;
default:
throw new NotImplementedException();
}
}
}
return returnResult;
}
Thanks!
Code Updated:
public interface IEval<T>
{
Func<T, bool> Expression { get; }
bool Eval(bool against, T t);
}
public class AndEval<T> : IEval<T>
{
public Func<T, bool> Expression { get; private set; }
public AndEval(Func<T, bool> expression)
{
Expression = expression;
}
public bool Eval(bool against, T t)
{
return Expression.Invoke(t) & against;
}
}
public class OrEval<T> : IEval<T>
{
public Func<T, bool> Expression { get; private set; }
public OrEval(Func<T, bool> expression)
{
Expression = expression;
}
public bool Eval(bool against, T t)
{
return Expression.Invoke(t) | against;
}
}
public static class EvalExtensions
{
public static bool Validate<T>(this T t, IList<IEval<T>> conditions)
{
var accumulator = conditions.First().Expression(t);
foreach (var condition in conditions.Skip(1))
{
accumulator = condition.Eval(accumulator, t);
}
return accumulator;
}
}
Try this (assuming that conditions is not empty)
var accumulator = conditions.First().Expression(0);
foreach (var condition in conditions.Skip(1))
{
accumulator = condition.Operation.Evaluate(
condition.Expression(0), accumulator);
}
class AddOperation : Operation
{
public override int Evaluate(int a, int b)
{
return a & b;
}
}
You get the idea. You can make it even more compact by defining a method in condition that makes it run Expression() on itself and pass the result as the first argument to Evaluate:
condition.Evaluate(accumulator);
class Condition
{
public int Evaluate(int argument)
{
return Operation.Evaluate(Expression(0), argument);
}
}
(also an unrelated advice: never ever call a variable tempSomething, it is bad karma and creates the impression that you don't know exactly the role of that particular variable for the reader)
One general pattern for eliminating if/switch is to place the logic behind the if in the class you are operating on. I don't know enough about your domain to judge whether that will work here.
To apply that pattern, IEval would be expanded with another method, e.g.
IEval<T>.PerformOperation(T tempResult)
Each concrete implementation of IEval would then implement PerformOperation based on the specific operation it models, rather than using an Enum to indicate the type of operation.
(not sure if tempResult is of type T based on your code).
Then instead of the switch, write
returnResult = condition.PerformOperation(tempResult);
I would go with LINQ methods. Like -
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
return conditions
.Skip(1)
.Aggregate(
conditions.First().Expression(o),
(a, b) => b.Operator == Operators.Or ? (a || b.Expression(o)) : (a && b.Expression(o))
);
}
Or if you don't like ternary operator or need more extensible and nicer approach, you can use Dictionary to store and lookup functions associated with operators.
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
return conditions
.Skip(1)
.Aggregate(
conditions.First().Expression(o),
(a, b) => operators[b.Operator](a, b.Expression(o))
);
}
public static Dictionary<Operator, Func<bool, bool, bool>> operators = new Dictionary<Operator, Func<bool, bool, bool>>()
{
{Operator.And, (a, b) => a && b},
{Operator.Or, (a, b) => a || b}
}
The only thing I can think of is:
Have an if statement with checks that you have at least 2 conditions.
Then, instead of a foreach, use a regular for statement with a counter that starts at the second condition.
If you have zero conditions, return true. depending on your other business logic.
If you have one condition, then take the value.
Regardless, I believe the switch statement for the operation to perform is going to be necessary... Unless you change the code to execute some type of script which is your actual op to perform. Which I think is worse.
The only thing I don't like is that you have a variable called counter that will always be either 0 or 1. I'd make it a bool isFirst instead. If you want to get rid of the switch, you could replace your IEval interface with
public interface IEval<T>{
Func<T, bool> Expression { get; }
Func<bool, bool, bool> Combinator { get; }
string Key { get; }
}
Your Combine method will then be either
public Func<bool, bool, bool> Combinator {
get { return (b1, b2) => b1 | b2; }
}
or
public Func<bool, bool, bool> Combinator {
get { return (b1, b2) => b1 & b2; }
}
depending on the desired operation.
Might be overkill to return a delegate, though, perhaps just add a method bool Combine(bool value1, bool value2)
The following algorithm exhibits short-circuiting (it stops evaluating once the condition is known to be false). It has the same basic design, but it effectively uses an implicit true && ... at the beginning to make things cleaner.
public static bool Validate<T>(this T o, IList<IEval<T>> conditions)
{
bool result = true;
Operator op = Operator.And;
var conditionIter = conditions.GetEnumerator();
while (result && conditionIter.MoveNext())
{
bool tempResult = conditionIter.Current.Expression(o);
switch (op)
{
case Operator.And:
result &= tempResult;
break;
case Operator.Or:
result |= tempResult;
break;
default:
throw new NotImplementedException();
}
op = condition.Operator;
}
return result;
}