private DelegateMap(Type delegateType, Type thisParameter, SimpleParameterInfo[] methodParameters, Type methodReturn) { if (delegateType == null) { throw new ArgumentNullException(nameof(delegateType)); } DelegateType = delegateType; // delegate info var invokeMethod = GetDelegateInvokeMethod(); var delegateParams = SimpleParameterInfo.FromParameters(invokeMethod.GetParameters()); var delegateReturn = invokeMethod.ReturnType; // map try { var hasThis = thisParameter != null; // Check param count if (delegateParams.Length != methodParameters.Length + (hasThis ? 1 : 0)) { throw new Exception("Invalid parameters count."); } ParametersMap = new ArgMap[delegateParams.Length]; for (var i = 0; i < ParametersMap.Length; i++) { var methodParam = hasThis ? i == 0 ? new SimpleParameterInfo(thisParameter) : methodParameters[i - 1] : methodParameters[i]; ParametersMap[i] = new ArgMap(i, delegateParams[i], methodParam); } RetValMap = new RetValMap(delegateReturn, methodReturn); } catch (Exception ex) { throw InvalidSignatureException(ex); } }
// Method | Delegate // ======================= // Normal | Normal,Ref // Ref | Normal,Ref,Out // Out | Ref, Out public ArgMap(int index, SimpleParameterInfo @delegate, SimpleParameterInfo method) { Delegate = @delegate; Method = method; var methodType = method.Type.RemoveByRef(); var delegateType = @delegate.Type.RemoveByRef(); if (method.IsOut || method.IsByRef) { // check underlying types are assignable if (!delegateType.IsAssignableFrom(methodType)) { throw new ArgumentException("Invalid type for parameter " + index); } if (method.IsOut) { // check that delegate can accept method's out if (!(@delegate.IsOut || @delegate.IsByRef)) { throw new ArgumentException( $"Invalid modifier for parameter {index}. Should be Out or Ref."); } } } else { if (@delegate.IsOut) { throw new ArgumentException($"Invalid modifier for parameter {index}. Should be None or Ref."); } // cast up or down should work if (!delegateType.IsAssignableFrom(methodType) && !methodType.IsAssignableFrom(delegateType)) { throw new ArgumentException("Invalid type for parameter " + index); } } }
public static DelegateMap Constructor(Type delegateType, ConstructorInfo constructor) => new DelegateMap(delegateType, null, SimpleParameterInfo.FromParameters(constructor.GetParameters()), constructor.DeclaringType);
public static DelegateMap Method(Type delegateType, MethodInfo methodInfo) => new DelegateMap(delegateType, GetThisParameter(methodInfo), SimpleParameterInfo.FromParameters(methodInfo.GetParameters()), methodInfo.ReturnType);