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");
}
}
I have created an architecture in my C# code which does exactly what I want, but seems it would be very difficult to maintain in the long-run and am hoping there's a design pattern / better architecture I could be pointed towards.
I have created an object Test which, again, does exactly what I need perfectly which has the following structure:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
private Lazy<object> _test1;
public object Test1 { get { return _test1.Value; } }
private Lazy<object> _test2;
public object Test2 { get { return _test2.Value; } }
public Test()
{
_test1 = new Lazy<object>(() => MethodDictionary["Test1"](this), true);
_test2 = new Lazy<object>(() => MethodDictionary["Test2"](this), true);
}
}
What this allows me to do is, at run-time to assign a dictionary of functions to my Test object and the 2 properties Test1 & Test2 will use the functions loaded into it to return values.
The implementation looking somewhat as follows:
class Program
{
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1.ToString());
Console.WriteLine(x.Test2.ToString());
Console.ReadKey();
}
private static object TestMethod1(Test t)
{ return t.Var1 + t.Var2; }
private static object TestMethod2(Test t)
{ return t.Var1 - t.Var2; }
}
And it works great and has proven very efficient for large sets of Test objects.
My challenge is that if I ever want to add in a new method to my Test class, I need to add in the:
private Lazy<object> _myNewMethod;
public object MyNewMethod { get { return _myNewMethod.Value; } }
Update the constuctor with the key to look for in the dictionary
And, although that is pretty simple, I'd love to have a 1-line add-in (maybe some form of custom object) or have the properties read directly form the dictionary without any need for defining them at all.
Any ideas? ANY help would be great!!!
Thanks!!!
One of the ways in which you could achieve your desired behavior, is to use something that resembles a miniature IoC framework for field injection, tuned to your specific use case.
To make things easier, allow less typing in your concrete classes and make things type-safe, we introduce the LazyField type:
public class LazyField<T>
{
private static readonly Lazy<T> Default = new Lazy<T>();
private readonly Lazy<T> _lazy;
public LazyField() : this(Default) { }
public LazyField(Lazy<T> lazy)
{
_lazy = lazy;
}
public override string ToString()
{
return _lazy.Value.ToString();
}
public static implicit operator T(LazyField<T> instance)
{
return instance._lazy.Value;
}
}
Furthermore, we define an abstract base class, that ensures that these fields will be created at construction time:
public abstract class AbstractLazyFieldHolder
{
protected AbstractLazyFieldHolder()
{
LazyFields.BuildUp(this); // ensures fields are populated.
}
}
Skipping for a moment how this is achieved (explained further below), this allows the following way of defining your Test class:
public class Test : AbstractLazyFieldHolder
{
public double Var1;
public double Var2;
public readonly LazyField<double> Test1;
public readonly LazyField<double> Test2;
}
Note that these fields are immutable, initialized in the constructor. Now, for your usage example, the below snippet shows the "new way" of doing this:
LazyFields.Configure<Test>()
// We can use a type-safe lambda
.SetProvider(x => x.Test1, inst => inst.Var1 + inst.Var2)
// Or the field name.
.SetProvider("Test2", TestMethod2);
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1);
double test2Val = x.Test2; // type-safe conversion
Console.WriteLine(test2Val);
// Output:
// 50
// -10
The class below provides the services that support the configuration and injection of these field value.
public static class LazyFields
{
private static readonly ConcurrentDictionary<Type, IBuildUp> _registry = new ConcurrentDictionary<Type,IBuildUp>();
public interface IConfigureType<T> where T : class
{
IConfigureType<T> SetProvider<FT>(string fieldName, Func<T, FT> provider);
IConfigureType<T> SetProvider<F, FT>(Expression<Func<T, F>> fieldExpression, Func<T, FT> provider) where F : LazyField<FT>;
}
public static void BuildUp(object instance)
{
System.Diagnostics.Debug.Assert(instance != null);
var builder = _registry.GetOrAdd(instance.GetType(), BuildInitializer);
builder.BuildUp(instance);
}
public static IConfigureType<T> Configure<T>() where T : class
{
return (IConfigureType<T>)_registry.GetOrAdd(typeof(T), BuildInitializer);
}
private interface IBuildUp
{
void BuildUp(object instance);
}
private class TypeCfg<T> : IBuildUp, IConfigureType<T> where T : class
{
private readonly List<FieldInfo> _fields;
private readonly Dictionary<string, Action<T>> _initializers;
public TypeCfg()
{
_fields = typeof(T)
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Where(IsLazyField)
.ToList();
_initializers = _fields.ToDictionary(x => x.Name, BuildDefaultSetter);
}
public IConfigureType<T> SetProvider<FT>(string fieldName, Func<T,FT> provider)
{
var pi = _fields.First(x => x.Name == fieldName);
_initializers[fieldName] = BuildSetter<FT>(pi, provider);
return this;
}
public IConfigureType<T> SetProvider<F,FT>(Expression<Func<T,F>> fieldExpression, Func<T,FT> provider)
where F : LazyField<FT>
{
return SetProvider((fieldExpression.Body as MemberExpression).Member.Name, provider);
}
public void BuildUp(object instance)
{
var typedInstance = (T)instance;
foreach (var initializer in _initializers.Values)
initializer(typedInstance);
}
private bool IsLazyField(FieldInfo fi)
{
return fi.FieldType.IsGenericType && fi.FieldType.GetGenericTypeDefinition() == typeof(LazyField<>);
}
private Action<T> BuildDefaultSetter(FieldInfo fi)
{
var itemType = fi.FieldType.GetGenericArguments()[0];
var defValue = Activator.CreateInstance(typeof(LazyField<>).MakeGenericType(itemType));
return (inst) => fi.SetValue(inst, defValue);
}
private Action<T> BuildSetter<FT>(FieldInfo fi, Func<T, FT> provider)
{
return (inst) => fi.SetValue(inst, new LazyField<FT>(new Lazy<FT>(() => provider(inst))));
}
}
private static IBuildUp BuildInitializer(Type targetType)
{
return (IBuildUp)Activator.CreateInstance(typeof(TypeCfg<>).MakeGenericType(targetType));
}
}
Look at library https://github.com/ekonbenefits/impromptu-interface.
With it and using DynamicObject i wrote sample code that shows how to simplify adding new methods:
public class Methods
{
public Methods()
{
MethodDictionary = new Dictionary<string, Func<ITest, object>>();
LazyObjects = new Dictionary<string, Lazy<object>>();
}
public Dictionary<string, Func<ITest, object>> MethodDictionary { get; private set; }
public Dictionary<string, Lazy<object>> LazyObjects { get; private set; }
}
public class Proxy : DynamicObject
{
Methods _methods;
public Proxy()
{
_methods = new Methods();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _methods.LazyObjects[binder.Name].Value;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_methods.MethodDictionary[binder.Name] = (Func<ITest, object>)value;
_methods.LazyObjects[binder.Name] = new Lazy<object>(() => _methods.MethodDictionary[binder.Name](this.ActLike<ITest>()), true);
return true;
}
}
//now you can add new methods by add single method to interface
public interface ITest
{
object Test1 { get; set; }
object Test2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new Proxy().ActLike<ITest>();
x.Test1 = new Func<ITest, object>((y) => "Test1");
x.Test2 = new Func<ITest, object>((y) => "Test2");
Console.WriteLine(x.Test1);
Console.WriteLine(x.Test2);
}
}
I don't know what you are trying to do, but I think you can use a simpler approach like this:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
}
Calling the function is simple:
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(Test.MethodDictionary["Test1"](x).ToString());
Console.WriteLine(Test.MethodDictionary["Test2"](x).ToString());
Console.ReadKey();
}
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.
I'm getting an AmbigiousMatchException for a function calling Type.GetMethod() even though everything looks pretty much correct.
public partial class IBaseEvent
{
private Dictionary<int, Func<object[], object>> funcs = new Dictionary<int,Func<object[],object>>();
private Dictionary<int, object[]> func_args = new Dictionary<int,object[]>();
public void Execute()
{
int exp = 0;
foreach(var func in funcs)
{
exp = func.GetHashCode();
func.Value.DynamicInvoke(func_args[exp]);
}
}
public void AddFunction(Type T, dynamic sFunc, params object[] parameters)
{
funcs.Add(T.GetHashCode(), new Func<object[],object>(T.GetMethod(sFunc)));
func_args.Add(T.GetHashCode(), parameters);
}
}
public class DummyEvent : IBaseEvent
{
private string EventType = "DUMMY_EVENT";
public DummyEvent()
{
object[] parm = new object[3];
parm[0] = Logging.LOG_TYPE.DEBUG;
parm[1] = "Hello World from DummyEvent! TypeCode: {0}";
parm[2] = typeof(DummyEvent).GetType().GUID;
AddFunction(typeof(Logging.LoggingFactory), "WriteToLog", parm);
}
}
Errors on AddFunction(typeof(Logging.LoggingFactory), "WriteToLog", parm);
What am I doing wrong? and how can I correct this?
Based on the error message, I suspect that you may already have a function WriteToLog in LoggingFactory or its inheritance chain.
It seems like you are unnecessarily complicating stuff. Both the function and its argument are known whenever you are adding it to the list. Have you considering using anonymous functions like so. As an example I have wrapped the this object.. the string argument in this example. DynamicInvoke will be considerably slower as well.
Also two different Types can return the same GetHashCode which depending on your particular needs may or may not matter.
public partial class IBaseEvent
{
private Dictionary<int, Action> funcs = new Dictionary<int, Action>();
public void Execute()
{
foreach (var func in funcs.Values)
{
func();
}
}
public void AddFunction(Type t, Action ff)
{
funcs.Add(t.GetHashCode(), ff);
}
}
public class DummyEvent : IBaseEvent
{
private string EventType = "DUMMY_EVENT";
private void DoSomething(string x)
{
Console.WriteLine(x);
}
public DummyEvent()
{
Action temp = () =>
{
DoSomething("Hello World from DummyEvent! TypeCode");
};
AddFunction(typeof(Logging), temp);
}
}
If type is strictly not needed you can further simply it like so
public partial class IBaseEvent
{
public Action MyAction;
public void Execute()
{
MyAction();
}
public void AddFunction(Action ff)
{
MyAction += ff;
}
}