public SubscribeableMethod(MethodInfo method, SubscriptionAttribute subscription, Type payloadType, Type parameterType, bool isEnvelope) { Method = method; Subscription = subscription; PayloadType = payloadType; ParameterType = parameterType; IsEnvelopeType = isEnvelope; }
private SubscribeableMethod GetSubscribeableMethod(MethodInfo method, SubscriptionAttribute subscription) { Type payloadType = subscription.PayloadType.UnwrapEnvelopeType(); // void MyMethod<T>(T) or void MyMethod<T>() or void MyMethod<T>(Envelope<T>) // If the method is generic, we can try to fill in the type parameters with the value from the attribute if (method.IsGenericMethodDefinition) { if (method.GetGenericArguments().Length != 1 || payloadType == null) { _logger.Error($"Cannot subscribe method {method.Name} because method is generic and there is not enough information to construct it"); return(null); } method = method.MakeGenericMethod(payloadType); } Type parameterType = method.GetParameters().FirstOrDefault()?.ParameterType; // void MyMethod() // There is no parameter, so see if we have enough information to construct a trampoline if (parameterType == null) { // We have no type information at all, so we can't do anything if (payloadType == null) { _logger.Error($"Could not determine which channel to use because payload type is not provided and there is no parameter"); return(null); } // This is not a fully-constructed type, so we can't determine a channel for it if (payloadType.IsGenericType && !payloadType.IsConstructedGenericType) { _logger.Error($"Payload type {payloadType.Name} is not fully-constructed and cannot be used to define a channel"); return(null); } // Use the payload type from the attribute to create a trampoline to a method with no parameters return(new SubscribeableMethod(method, subscription, payloadType, null, false)); } // parameterType is the type of the raw parameter, which may include Envelope<> // parameterPayloadType is the type of the payload without Envelope<> bool isEnvelope = parameterType.IsEnvelopeType(); Type parameterPayloadType = parameterType.UnwrapEnvelopeType(); if (payloadType == null) { payloadType = parameterPayloadType; } // void MyMethod<T>(T payload) or void MyMethod<T>(Envelope<T> payload) // This is not a fully-constructed type, so we can't determine a channel for it if (payloadType.IsGenericType && !payloadType.IsConstructedGenericType) { _logger.Error($"Payload type {payloadType.Name} is not fully-constructed and cannot be used"); return(null); } // Check that the type information between parameter and specified payload type are assignable if (!parameterPayloadType.IsAssignableFrom(payloadType)) { _logger.Error($"Cannot subscribe method {method.Name} because specified payload type {payloadType.Name} is not assignable to parameter type {parameterPayloadType.Name}"); return(null); } return(new SubscribeableMethod(method, subscription, payloadType, parameterType, isEnvelope)); }