protected virtual Delegate TryCreateDelegateInternal(Type delegateType, object target, MethodInfo method) { MethodInfo result; lock (CachedDelegates) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); if (!CachedDelegates.TryGetValue(cacheKey, out result)) { result = TryCreateMethodDelegate(delegateType, method); CachedDelegates[cacheKey] = result; if (result != null) { GenerateDelegateFactoryCode(delegateType, result); } } if (result == null) { return(null); } } #if NET_STANDARD if (target == null) { return(result.CreateDelegate(delegateType)); } return(result.CreateDelegate(delegateType, target)); #else if (target == null) { return(Delegate.CreateDelegate(delegateType, result)); } return(Delegate.CreateDelegate(delegateType, target, result)); #endif }
/// <summary> /// Tries to creates a delegate of the specified type that represents the specified static or instance method, with the specified first argument. /// </summary> /// <returns> /// A delegate of the specified type that represents the specified static method of the specified class. /// </returns> /// <param name="delegateType">The <see cref="T:System.Type" /> of delegate to create. </param> /// <param name="target"> /// The <see cref="T:System.Type" /> representing the class that implements <paramref name="method" /> /// . /// </param> /// <param name="method">The name of the static method that the delegate is to represent. </param> public virtual Delegate TryCreateDelegate(Type delegateType, object target, MethodInfo method) { MethodInfo result; lock (CachedDelegates) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); if (!CachedDelegates.TryGetValue(cacheKey, out result)) { result = TryCreateMethodDelegate(delegateType, method); CachedDelegates[cacheKey] = result; } if (result == null) { return(null); } } #if PCL_WINRT if (target == null) { return(result.CreateDelegate(delegateType)); } return(result.CreateDelegate(delegateType, target)); #else if (target == null) { return(Delegate.CreateDelegate(delegateType, result)); } return(Delegate.CreateDelegate(delegateType, target, result)); #endif }
protected virtual Delegate GetMethodDelegateInternal(Type delegateType, MethodInfo method) { lock (InvokeMethodCacheDelegate) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); Delegate value; if (!InvokeMethodCacheDelegate.TryGetValue(cacheKey, out value)) { GenerateInvokeMethodCode(method, delegateType); MethodInfo delegateMethod = delegateType.GetMethodEx(nameof(Action.Invoke)); if (delegateMethod == null) { throw new ArgumentException(string.Empty, nameof(delegateType)); } var delegateParams = delegateMethod.GetParameters().ToList(); ParameterInfo[] methodParams = method.GetParameters(); var expressions = new List <Expression>(); var parameters = new List <ParameterExpression>(); if (!method.IsStatic) { var thisParam = Expression.Parameter(delegateParams[0].ParameterType, "@this"); parameters.Add(thisParam); expressions.Add(ConvertIfNeed(thisParam, method.DeclaringType, false)); delegateParams.RemoveAt(0); } Should.BeValid("delegateType", delegateParams.Count == methodParams.Length); for (int i = 0; i < methodParams.Length; i++) { ParameterExpression parameter = Expression.Parameter(delegateParams[i].ParameterType, i.ToString()); parameters.Add(parameter); expressions.Add(ConvertIfNeed(parameter, methodParams[i].ParameterType, false)); } Expression callExpression; if (method.IsStatic) { callExpression = Expression.Call(null, method, expressions.ToArrayEx()); } else { Expression @this = expressions[0]; expressions.RemoveAt(0); callExpression = Expression.Call(@this, method, expressions.ToArrayEx()); } if (delegateMethod.ReturnType != typeof(void)) { callExpression = ConvertIfNeed(callExpression, delegateMethod.ReturnType, false); } var lambdaExpression = Expression.Lambda(delegateType, callExpression, parameters); value = lambdaExpression.Compile(); InvokeMethodCacheDelegate[cacheKey] = value; } return(value); } }
/// <summary> /// Gets a delegate to call the specified <see cref="MethodInfo" />. /// </summary> /// <param name="delegateType">The type of delegate.</param> /// <param name="method"> /// The specified <see cref="MethodInfo" /> /// </param> /// <returns> /// An instance of delegate. /// </returns> public virtual Delegate GetMethodDelegate(Type delegateType, MethodInfo method) { Should.NotBeNull(delegateType, "delegateType"); Should.BeOfType <Delegate>(delegateType, "delegateType"); Should.NotBeNull(method, "method"); lock (InvokeMethodCacheDelegate) { var cacheKey = new MethodDelegateCacheKey(method, delegateType); Delegate value; if (!InvokeMethodCacheDelegate.TryGetValue(cacheKey, out value)) { MethodInfo delegateMethod = delegateType.GetMethodEx("Invoke"); var delegateParams = delegateMethod.GetParameters().ToList(); ParameterInfo[] methodParams = method.GetParameters(); var expressions = new List <Expression>(); var parameters = new List <ParameterExpression>(); if (!method.IsStatic) { var thisParam = Expression.Parameter(delegateParams[0].ParameterType, "@this"); parameters.Add(thisParam); expressions.Add(ConvertIfNeed(thisParam, GetDeclaringType(method), false)); delegateParams.RemoveAt(0); } Should.BeValid("delegateType", delegateParams.Count == methodParams.Length); for (int i = 0; i < methodParams.Length; i++) { ParameterExpression parameter = Expression.Parameter(delegateParams[i].ParameterType, i.ToString()); parameters.Add(parameter); expressions.Add(ConvertIfNeed(parameter, methodParams[i].ParameterType, false)); } Expression callExpression; if (method.IsStatic) { callExpression = Expression.Call(null, method, expressions.ToArrayEx()); } else { Expression @this = expressions[0]; expressions.RemoveAt(0); callExpression = Expression.Call(@this, method, expressions.ToArrayEx()); } if (delegateMethod.ReturnType != typeof(void)) { callExpression = ConvertIfNeed(callExpression, delegateMethod.ReturnType, false); } var lambdaExpression = CreateLambdaExpressionByType(delegateType, callExpression, parameters); value = lambdaExpression.Compile(); InvokeMethodCacheDelegate[cacheKey] = value; } return(value); } }
public override Delegate TryCreateDelegate(Type delegateType, object target, MethodInfo method) { Func <object, Delegate> value; lock (DelegatesCache) { var key = new MethodDelegateCacheKey(method, delegateType); if (!DelegatesCache.TryGetValue(key, out value)) { method = TryCreateMethodDelegate(delegateType, method); if (method != null) { Type type = method.DeclaringType; DynamicMethod dynamicMethod = CreateDynamicMethod(type, new[] { typeof(object) }, typeof(Delegate)); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); if (method.IsStatic) { ilGenerator.Emit(OpCodes.Ldnull); } else { ilGenerator.Emit(OpCodes.Ldarg_0); UnboxOrCast(ilGenerator, type); } if (method.IsVirtual) { ilGenerator.Emit(OpCodes.Dup); ilGenerator.Emit(OpCodes.Ldvirtftn, method); } else { ilGenerator.Emit(OpCodes.Ldftn, method); } ilGenerator.Emit(OpCodes.Newobj, delegateType.GetConstructors()[0]); ilGenerator.Emit(OpCodes.Ret); value = (Func <object, Delegate>)dynamicMethod.CreateDelegate(typeof(Func <object, Delegate>)); } DelegatesCache[key] = value; } } if (value == null) { return(null); } return(value(target)); }
protected override Delegate TryCreateDelegateInternal(Type delegateType, object target, MethodInfo method) { Func<object, Delegate> value; lock (DelegatesCache) { var key = new MethodDelegateCacheKey(method, delegateType); if (!DelegatesCache.TryGetValue(key, out value)) { method = TryCreateMethodDelegate(delegateType, method); if (method != null) { GenerateDelegateFactoryCode(delegateType, method); Type type = method.DeclaringType; DynamicMethod dynamicMethod = CreateDynamicMethod(type, new[] { typeof(object) }, typeof(Delegate)); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); if (method.IsStatic) ilGenerator.Emit(OpCodes.Ldnull); else { ilGenerator.Emit(OpCodes.Ldarg_0); UnboxOrCast(ilGenerator, type); } if (method.IsVirtual) { ilGenerator.Emit(OpCodes.Dup); ilGenerator.Emit(OpCodes.Ldvirtftn, method); } else ilGenerator.Emit(OpCodes.Ldftn, method); ilGenerator.Emit(OpCodes.Newobj, delegateType.GetConstructors()[0]); ilGenerator.Emit(OpCodes.Ret); value = (Func<object, Delegate>)dynamicMethod.CreateDelegate(typeof(Func<object, Delegate>)); } DelegatesCache[key] = value; } } if (value == null) return null; return value(target); }