public void AddExactConverter <TSource, TDestination>(Func <TSource, TDestination> func) { FuncAsyncConverter converter = (src, attr, context) => Task.FromResult <object>(func((TSource)src)); FuncConverterBuilder builder = (srcType, destType) => converter; this.AddConverter <TSource, TDestination, System.Attribute>(builder); }
/// <summary> /// Register a new converter function that is influenced by the attribute. /// If TSource is object, then this converter is applied to any attempt to convert to TDestination. /// </summary> /// <typeparam name="TSource">Source type.</typeparam> /// <typeparam name="TDestination">Destination type.</typeparam> /// <typeparam name="TAttribute">Attribute on the binding. </typeparam> /// <param name="converterManager"></param> /// <param name="converter">A function to convert from the source to the destination type.</param> public static void AddConverter <TSource, TDestination, TAttribute>(this ConverterManager converterManager, FuncAsyncConverter converter) where TAttribute : Attribute { FuncConverterBuilder builder = (srcType, destType) => converter; converterManager.AddConverter <TSource, TDestination, TAttribute>(builder); }
// Add a 'global' converter for all Attributes. // Passing in the cancellationToken also helps C# overload resolution determine sync. vs. async public void AddExactConverter <TSource, TDestination>(Func <TSource, CancellationToken, Task <TDestination> > func) { FuncAsyncConverter converter = async(src, attr, context) => await func((TSource)src, CancellationToken.None); FuncConverterBuilder builder = (srcType, destType) => converter; this.AddConverter <TSource, TDestination, System.Attribute>(builder); }
/// <summary> /// Register a new converter function that is influenced by the attribute. /// If TSource is object, then this converter is applied to any attempt to convert to TDestination. /// </summary> /// <typeparam name="TSource">Source type.</typeparam> /// <typeparam name="TDestination">Destination type.</typeparam> /// <typeparam name="TAttribute">Attribute on the binding. </typeparam> /// <param name="converterManager"></param> /// <param name="converter">A function to convert from the source to the destination type.</param> public static void AddConverter <TSource, TDestination, TAttribute>(this ConverterManager converterManager, FuncAsyncConverter <TSource, TDestination> converter) where TAttribute : Attribute { FuncAsyncConverter func = (src, attr, context) => Task.FromResult <object>(converter((TSource)src, attr, context)); FuncConverterBuilder builder = (srcType, destType) => func; converterManager.AddConverter <TSource, TDestination, TAttribute>(builder); }
/// <summary> /// Add a builder function that returns a converter. This can use <see cref="Microsoft.Azure.WebJobs.Host.Bindings.OpenType"/> to match against an /// open set of types. The builder can then do one time static type checking and code gen caching before /// returning a converter function that is called on each invocation. /// The types passed to that converter are gauranteed to have matched against the TSource and TDestination parameters. /// </summary> /// <typeparam name="TSource">Source type. Can be a concrete type or a <see cref="OpenType"/></typeparam> /// <typeparam name="TDestination">Destination type. Can be a concrete type or a <see cref="OpenType"/></typeparam> /// <typeparam name="TAttribute">Attribute on the binding. /// If this is <see cref="System.Attribute"/>, then it applies to any attribute. /// Else it applies to the specific TAttribte.</typeparam> /// <param name="converterBuilder">A function that is invoked if-and-only-if there is a compatible type match for the /// source and destination types. It then produce a converter function that can be called many times </param> public void AddConverter <TSource, TDestination, TAttribute>( FuncConverterBuilder converterBuilder) where TAttribute : Attribute { var openTypeSource = OpenType.FromType <TSource>(); var openTypeDest = OpenType.FromType <TDestination>(); AddOpenConverter <TAttribute>(openTypeSource, openTypeDest, converterBuilder); }
public static FuncConverterBuilder GetBuilder <TSource, TDestination>(FuncAsyncConverter <TSource, TDestination> func) { FuncConverterBuilder builder = (srcType, destType) => { // Cast from TDestination --> Object return(async(input, attr, ctx) => (object) await func((TSource)input, attr, ctx)); }; return(builder); }
// Exact types have precedence over open-types // If source nad dest match exactly, then replace. private void AddOpenConverter <TAttribute>( OpenType source, OpenType dest, FuncConverterBuilder converterBuilder) where TAttribute : Attribute { // Replace existing if the keys are exactly the same. foreach (var entry in GetEntries()) { if (entry.Attribute == typeof(TAttribute) && entry.Source.Equals(source) && entry.Dest.Equals(dest)) { entry.Builder = converterBuilder; return; } } { var entry = new Entry { Source = source, Dest = dest, Attribute = typeof(TAttribute), Builder = converterBuilder }; // Exact types are a "better match" than open types, so give them precedence. // Precedence is handled by having 2 separate lists. if (source is OpenType.ExactMatch && dest is OpenType.ExactMatch) { this._exactConverters.Add(entry); } else { this._openConverters.Add(entry); } } }
public void AddConverter <TSource, TDestination, TAttribute>(FuncConverterBuilder converterBuilder) where TAttribute : Attribute { throw new NotSupportedException("Identity converter is read-only"); }