private static FuncArgumentBuilder <TAttribute> BuildICollectorArgument <TAttribute, TMessage, TMessageSrc>( IConverterManager cm, Func <TAttribute, IAsyncCollector <TMessage> > buildFromAttribute, AttributeCloner <TAttribute> cloner) where TAttribute : Attribute { // Other var convert = cm.GetConverter <TMessageSrc, TMessage, TAttribute>(); if (convert == null) { ThrowMissingConversionError(typeof(TMessageSrc)); } FuncArgumentBuilder <TAttribute> argumentBuilder = (attrResolved, context) => { IAsyncCollector <TMessage> raw = buildFromAttribute(attrResolved); IAsyncCollector <TMessageSrc> obj = new TypedAsyncCollectorAdapter <TMessageSrc, TMessage, TAttribute>( raw, convert, attrResolved, context); ICollector <TMessageSrc> obj2 = new SyncAsyncCollectorAdapter <TMessageSrc>(obj); string invokeString = cloner.GetInvokeString(attrResolved); return(new AsyncCollectorValueProvider <ICollector <TMessageSrc>, TMessage>(obj2, raw, invokeString)); }; return(argumentBuilder); }
public AsyncCollectorBinding( ParameterDescriptor param, FuncArgumentBuilder <TAttribute> argumentBuilder, AttributeCloner <TAttribute> cloner) : base(cloner, param) { this._argumentBuilder = argumentBuilder; }
// Helper to bind an IAsyncCollector<TMessage> raw object to an IAsyncCollector<TUser> or ICollecter<TUser> and invoke converter manager as needed. private static FuncArgumentBuilder <TAttribute> BindAsyncCollectorToInterface <TAttribute, TMessage>( IConverterManager converterManager, Func <TAttribute, IAsyncCollector <TMessage> > buildFromAttribute, AttributeCloner <TAttribute> cloner, Type parameterType, FuncArgumentBuilder <TAttribute> argumentBuilder) where TAttribute : Attribute { var genericType = parameterType.GetGenericTypeDefinition(); var elementType = parameterType.GetGenericArguments()[0]; if (genericType == typeof(IAsyncCollector <>)) { if (elementType == typeof(TMessage)) { // Bind to IAsyncCollector<TMessage>. This is the "purest" binding, no adaption needed. argumentBuilder = (attrResolved, context) => { IAsyncCollector <TMessage> raw = buildFromAttribute(attrResolved); var invokeString = cloner.GetInvokeString(attrResolved); return(new AsyncCollectorValueProvider <IAsyncCollector <TMessage>, TMessage>(raw, raw, invokeString)); }; } else { // Bind to IAsyncCollector<T> // Get a converter from T to TMessage argumentBuilder = DynamicInvokeBuildIAsyncCollectorArgument(elementType, converterManager, buildFromAttribute, cloner); } } else if (genericType == typeof(ICollector <>)) { if (elementType == typeof(TMessage)) { // Bind to ICollector<TMessage> This just needs an Sync/Async wrapper argumentBuilder = (attrResolved, context) => { IAsyncCollector <TMessage> raw = buildFromAttribute(attrResolved); var invokeString = cloner.GetInvokeString(attrResolved); ICollector <TMessage> obj = new SyncAsyncCollectorAdapter <TMessage>(raw); return(new AsyncCollectorValueProvider <ICollector <TMessage>, TMessage>(obj, raw, invokeString)); }; } else { // Bind to ICollector<T>. // This needs both a conversion from T to TMessage and an Sync/Async wrapper argumentBuilder = DynamicInvokeBuildICollectorArgument(elementType, converterManager, buildFromAttribute, cloner); } } return(argumentBuilder); }
private static FuncArgumentBuilder <TAttribute> BuildOutArrayArgument <TAttribute, TMessage, TMessageSrc>( IConverterManager cm, Func <TAttribute, IAsyncCollector <TMessage> > buildFromAttribute, AttributeCloner <TAttribute> cloner) where TAttribute : Attribute { // Other var convert = cm.GetConverter <TMessageSrc, TMessage, TAttribute>(); FuncArgumentBuilder <TAttribute> argumentBuilder = (attrResolved, context) => { IAsyncCollector <TMessage> raw = buildFromAttribute(attrResolved); IAsyncCollector <TMessageSrc> obj = new TypedAsyncCollectorAdapter <TMessageSrc, TMessage, TAttribute>( raw, convert, attrResolved, context); string invokeString = cloner.GetInvokeString(attrResolved); return(new OutArrayValueProvider <TMessageSrc>(obj, invokeString)); }; return(argumentBuilder); }
internal static IBinding BindCollector <TAttribute, TMessage>( ParameterInfo parameter, INameResolver nameResolver, IConverterManager converterManager, IReadOnlyDictionary <string, Type> bindingDataContract, Func <TAttribute, IAsyncCollector <TMessage> > buildFromAttribute, Func <TAttribute, ParameterInfo, INameResolver, ParameterDescriptor> buildParamDescriptor = null, Func <TAttribute, ParameterInfo, INameResolver, Task <TAttribute> > hook = null) where TAttribute : Attribute { if (parameter == null) { throw new ArgumentNullException("parameter"); } Func <TAttribute, Task <TAttribute> > hookWrapper = null; if (hook != null) { hookWrapper = (attr) => hook(attr, parameter, nameResolver); } TAttribute attributeSource = parameter.GetCustomAttribute <TAttribute>(inherit: false); // ctor will do validation and throw. var cloner = new AttributeCloner <TAttribute>(attributeSource, bindingDataContract, nameResolver, hookWrapper); Type parameterType = parameter.ParameterType; FuncArgumentBuilder <TAttribute> argumentBuilder = null; // C# reflection trivia: If .IsOut = true, then IsGenericType = false. if (parameterType.IsGenericType) { argumentBuilder = BindAsyncCollectorToInterface(converterManager, buildFromAttribute, cloner, parameterType, argumentBuilder); } if (parameter.IsOut) { argumentBuilder = BindAsyncCollectorToOut <TAttribute, TMessage>(parameter, converterManager, buildFromAttribute, cloner); } if (argumentBuilder == null) { // Can't bind it. return(null); } ParameterDescriptor param; if (buildParamDescriptor != null) { param = buildParamDescriptor(attributeSource, parameter, nameResolver); } else { // If no parameter supplied, use a default. param = new ParameterDescriptor { Name = parameter.Name, DisplayHints = new ParameterDisplayHints { Description = "output" } }; } return(new AsyncCollectorBinding <TAttribute, TMessage>(param, argumentBuilder, cloner)); }