Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public static TDelegate CreateDelegate<TDelegate>(
- MethodInfo method,
- object instance = null,
- CreateOptions options = CreateOptions.None )
- where TDelegate : class
- {
- switch ( options )
- {
- case CreateOptions.None:
- // Ordinary delegate creation, maintaining variance safety.
- return Delegate.CreateDelegate( typeof( TDelegate ), instance, method ) as TDelegate;
- default:
- {
- MethodInfo delegateInfo = MethodInfoFromDelegateType( typeof( TDelegate ) );
- // Create delegate original and converted arguments.
- var delegateTypes = delegateInfo.GetParameters().Select( d => d.ParameterType );
- var methodTypes = method.GetParameters()
- .SkipWhile( p => p.ParameterType == typeof( Closure ) )
- .Select( p => p.ParameterType );
- var delegateArgumentExpressions = CreateDelegateArgumentExpressions( delegateTypes, methodTypes );
- // Create method call.
- List<Expression> arguments = new List<Expression>();
- if ( method.GetParameters().FirstOrDefault().ParameterType == typeof( Closure ) )
- {
- arguments.Add( Expression.Parameter( typeof( Closure ) ) );
- }
- arguments.AddRange( delegateArgumentExpressions.ConvertedArguments );
- Expression methodCall = Expression.Call(
- instance == null ? null : Expression.Constant( instance ),
- method,
- arguments );
- // Convert return type when necessary.
- Expression convertedMethodCall;
- if ( delegateInfo.ReturnType == method.ReturnType )
- {
- convertedMethodCall = methodCall;
- }
- else
- {
- try
- {
- convertedMethodCall = Expression.Convert( methodCall, delegateInfo.ReturnType );
- }
- catch ( InvalidOperationException )
- {
- // Attempt recursive downcasting of the type arguments when it is a delegate. E.g. Func<Action<T>>
- if ( method.ReturnType.IsDelegate() && method.ReturnType.IsGenericType )
- {
- PropertyInfo methodProperty = method.ReturnType.GetProperty( MethodProperty, typeof( MethodInfo ) );
- MemberExpression getDelegateMethod = Expression.Property( methodCall, methodProperty );
- Func<MethodInfo, object, CreateOptions, TDelegate> createDelegateDelegate = CreateDelegate<TDelegate>;
- MethodInfo createDelegateMethod
- = createDelegateDelegate.Method.GetGenericMethodDefinition( delegateInfo.ReturnType );
- MethodCallExpression createDelegate = Expression.Call(
- createDelegateMethod,
- getDelegateMethod, Expression.Constant( null ), Expression.Constant( CreateOptions.Downcasting ) );
- convertedMethodCall = createDelegate;
- }
- else
- {
- throw new InvalidOperationException( "Can't downcast the return type to its desired type." );
- }
- }
- }
- return Expression.Lambda<TDelegate>(
- convertedMethodCall,
- delegateArgumentExpressions.OriginalArguments
- ).Compile();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement