private static Func <TAttribute, IValueProvider> BuildICollectorArgument <TAttribute, TMessage, TMessageSrc>( IConverterManager cm, Func <TAttribute, IAsyncCollector <TMessage> > buildFromAttribute, AttributeCloner <TAttribute> cloner) where TAttribute : Attribute { // Other Func <TMessageSrc, TAttribute, TMessage> convert = cm.GetConverter <TMessageSrc, TMessage, TAttribute>(); if (convert == null) { ThrowMissingConversionError(typeof(TMessageSrc)); } Func <TAttribute, IValueProvider> argumentBuilder = (attrResolved) => { IAsyncCollector <TMessage> raw = buildFromAttribute(attrResolved); IAsyncCollector <TMessageSrc> obj = new TypedAsyncCollectorAdapter <TMessageSrc, TMessage, TAttribute>( raw, convert, attrResolved); ICollector <TMessageSrc> obj2 = new SyncAsyncCollectorAdapter <TMessageSrc>(obj); string invokeString = cloner.GetInvokeString(attrResolved); return(new AsyncCollectorValueProvider <ICollector <TMessageSrc>, TMessage>(obj2, raw, invokeString)); }; return(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 Func <TContext, ValueBindingContext, IValueProvider> BuildICollectorArgument <TContext, TMessageSrc, TMessage>( IConverterManager cm, Func <TContext, ValueBindingContext, IAsyncCollector <TMessage> > builder, string invokeString) { // Other Func <TMessageSrc, TMessage> convert = cm.GetConverter <TMessageSrc, TMessage>(); Func <TContext, ValueBindingContext, IValueProvider> argumentBuilder = (context, valueBindingContext) => { IAsyncCollector <TMessage> raw = builder(context, valueBindingContext); IAsyncCollector <TMessageSrc> obj = new TypedAsyncCollectorAdapter <TMessageSrc, TMessage>(raw, convert); ICollector <TMessageSrc> obj2 = new SyncAsyncCollectorAdapter <TMessageSrc>(obj); return(new AsyncCollectorValueProvider <ICollector <TMessageSrc>, TMessage>(obj2, raw, invokeString)); }; return(argumentBuilder); }
// Get a ValueProvider that's in the right mode. private static IValueProvider CoerceValueProvider(Mode mode, string invokeString, IAsyncCollector <TMessage> collector) { switch (mode) { case Mode.IAsyncCollector: return(new AsyncCollectorValueProvider <IAsyncCollector <TMessage>, TMessage>(collector, collector, invokeString)); case Mode.ICollector: ICollector <TMessage> syncCollector = new SyncAsyncCollectorAdapter <TMessage>(collector); return(new AsyncCollectorValueProvider <ICollector <TMessage>, TMessage>(syncCollector, collector, invokeString)); case Mode.OutArray: return(new OutArrayValueProvider <TMessage>(collector, invokeString)); case Mode.OutSingle: return(new OutValueProvider <TMessage>(collector, invokeString)); default: throw new NotImplementedException($"mode ${mode} not implemented"); } }
public static IBinding BindCollector <TMessage, TContext>( ParameterInfo parameter, IConverterManager converterManager, Func <TContext, ValueBindingContext, IAsyncCollector <TMessage> > builder, string invokeString, Func <string, TContext> invokeStringBinder) { if (builder == null) { throw new ArgumentNullException("builder"); } if (invokeStringBinder == null) { throw new ArgumentNullException("invokeStringBinder"); } if (parameter == null) { throw new ArgumentNullException("parameter"); } Type parameterType = parameter.ParameterType; Func <TContext, ValueBindingContext, IValueProvider> argumentBuilder = null; if (parameterType.IsGenericType) { 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 = (context, valueBindingContext) => { IAsyncCollector <TMessage> raw = builder(context, valueBindingContext); 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, builder, invokeString); } } else if (genericType == typeof(ICollector <>)) { if (elementType == typeof(TMessage)) { // Bind to ICollector<TMessage> This just needs an Sync/Async wrapper argumentBuilder = (context, valueBindingContext) => { IAsyncCollector <TMessage> raw = builder(context, valueBindingContext); 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, builder, invokeString); } } } if (parameter.IsOut) { Type elementType = parameter.ParameterType.GetElementType(); if (elementType.IsArray) { if (elementType == typeof(TMessage[])) { argumentBuilder = (context, valueBindingContext) => { IAsyncCollector <TMessage> raw = builder(context, valueBindingContext); return(new OutArrayValueProvider <TMessage>(raw, invokeString)); }; } else { // out TMessage[] var e2 = elementType.GetElementType(); argumentBuilder = DynamicBuildOutArrayArgument(e2, converterManager, builder, invokeString); } } else { // Single enqueue // out TMessage if (elementType == typeof(TMessage)) { argumentBuilder = (context, valueBindingContext) => { IAsyncCollector <TMessage> raw = builder(context, valueBindingContext); return(new OutValueProvider <TMessage>(raw, invokeString)); }; } else { // use JSon converter // out T argumentBuilder = DynamicInvokeBuildOutArgument(elementType, converterManager, builder, invokeString); } } } if (argumentBuilder != null) { ParameterDescriptor param = new ParameterDescriptor { Name = parameter.Name, DisplayHints = new ParameterDisplayHints { Description = "output" } }; var initialClient = invokeStringBinder(invokeString); return(new AsyncCollectorBinding <TMessage, TContext>(initialClient, argumentBuilder, param, invokeStringBinder)); } string msg = string.Format(CultureInfo.CurrentCulture, "Can't bind to {0}.", parameter); throw new InvalidOperationException(msg); }