public void Initialize(ExtensionConfigContext extensionConfigContext) { _log?.LogInformation("Availability Monitoring Extension is initializing:" + " {{Version=\"{Version}\"}}", this.GetType().Assembly.GetName().Version); Validate.NotNull(extensionConfigContext, nameof(extensionConfigContext)); // A Coded Availablity Test is defined as such by returning a value that is bound by AvailabilityTestResult-Attribute. // A paramater bound by AvailabilityTestInfo-Attribute is optional. // Such parameter can be used to programmatically get information about the current availablity test, or it can be omitted. // FluentBindingRule<T> is marked as Obsolete, yet it is the type returned from AddBindingRule(..) // We could use "var", but one should NEVER use "var" except in Lync expressions // or when the type is clear from the *same* line to an unfamiliar reader. // Neither is the case, so we use the type explicitly and work around the obsolete-warning by disabling it. #pragma warning disable CS0618 FluentBindingRule <AvailabilityTestResultAttribute> testResultRule = extensionConfigContext.AddBindingRule <AvailabilityTestResultAttribute>(); FluentBindingRule <AvailabilityTestInfoAttribute> testInfoRule = extensionConfigContext.AddBindingRule <AvailabilityTestInfoAttribute>(); #pragma warning restore CS0618 // This binding is used to get and process the return value of the function: testResultRule.BindToCollector <AvailabilityTestResultAttribute, AvailabilityTelemetry>(CreateAvailabilityTelemetryAsyncCollector); testResultRule.BindToCollector <AvailabilityTestResultAttribute, bool>(CreateBoolAsyncCollector); extensionConfigContext.AddConverter <string, AvailabilityTelemetry>(Convert.StringToAvailabilityTelemetry); // This is an optional In-parameter that allows user code to get runtime info about the availablity test: testInfoRule.BindToInput <AvailabilityTestInfo>(CreateAvailabilityTestInfo); extensionConfigContext.AddConverter <AvailabilityTestInfo, string>(Convert.AvailabilityTestInfoToString); }
#pragma warning disable CS0618 public static void BindToCollector <TAttribute, TMessage>( this FluentBindingRule <TAttribute> bindingRule, Func <TAttribute, ValueBindingContext, Task <IAsyncCollector <TMessage> > > asyncCollectorFactory) where TAttribute : Attribute #pragma warning restore CS0618 { // We could speed this up 10x - 100x by creating and caching delegates to the methods we accell vie reflection. // However, since this is a temp workaround until the methods are available in the SDK, we will avoid the complexity. #pragma warning disable CS0618 Type fluentBindingRuleType = typeof(FluentBindingRule <TAttribute>); #pragma warning restore CS0618 // First, reflect to invoke the method // public static PatternMatcher New<TSource, TDest>(Func<TSource, ValueBindingContext, Task<TDest>> func) // on the PatternMatcher class: Type patternMatcherType = fluentBindingRuleType.Assembly.GetType(PatternMatcherTypeName); MethodInfo patternMatcherFactoryBound = null; { Type[] genericMethodParamTypes = new Type[] { typeof(TAttribute), typeof(IAsyncCollector <TMessage>) }; Type requiredParamType = typeof(Func <TAttribute, ValueBindingContext, Task <IAsyncCollector <TMessage> > >); foreach (MethodInfo method in patternMatcherType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) { if (method.IsGenericMethod && method.GetParameters().Length == 1 && method.GetGenericArguments().Length == 2) { MethodInfo methodBound = method.MakeGenericMethod(genericMethodParamTypes); if (methodBound.GetParameters()[0].ParameterType.Equals(requiredParamType)) { patternMatcherFactoryBound = methodBound; break; } } } } // Create a PatternMatcher instance that wraps asyncCollectorFactory: object patternMatcherInstance = patternMatcherFactoryBound.Invoke(obj: null, parameters: new object[] { asyncCollectorFactory }); // Next, reflect to invoke // private void BindToCollector<TMessage>(PatternMatcher pm) // in the FluentBindingRule<TAttribute> class: MethodInfo bindToCollectorMethodGeneric = fluentBindingRuleType.GetMethod( FluentBindingRuleBindToCollectorMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, binder: null, new Type[] { patternMatcherType }, NoParameterModifiers); MethodInfo bindToCollectorMethodBound = bindToCollectorMethodGeneric.MakeGenericMethod(new Type[] { typeof(TMessage) }); // Bind asyncCollectorFactory wrapped into the patternMatcherInstance to the binding rule: bindToCollectorMethodBound.Invoke(obj: bindingRule, parameters: new object[] { patternMatcherInstance }); }
#pragma warning disable CS0618 // Type or member is obsolete. FluentBindingRule is "Not ready for public consumption." private void RegisterCommonConverters <T>(FluentBindingRule <T> rule) where T : Attribute #pragma warning restore CS0618 // Type or member is obsolete { // Converter manager already has Stream-->Byte[],String,TextReader rule.AddConverter <BlobBaseClient, Stream>(ConvertToStreamAsync); // Blob type is a property of an existing blob. rule.AddConverter(new StorageBlobConverter <AppendBlobClient>()); rule.AddConverter(new StorageBlobConverter <BlockBlobClient>()); rule.AddConverter(new StorageBlobConverter <PageBlobClient>()); }
/// <summary> /// Initializes the SQL binding rules /// </summary> /// <param name="context"> The config context </param> /// <exception cref="ArgumentNullException"> /// Thrown if context is null /// </exception> public void Initialize(ExtensionConfigContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } ILogger logger = this._loggerFactory.CreateLogger(LogCategories.Bindings); TelemetryInstance.Initialize(this._configuration, logger); #pragma warning disable CS0618 // Fine to use this for our stuff FluentBindingRule <SqlAttribute> inputOutputRule = context.AddBindingRule <SqlAttribute>(); var converter = new SqlConverter(this._configuration); inputOutputRule.BindToInput(converter); inputOutputRule.BindToInput <string>(typeof(SqlGenericsConverter <string>), this._configuration, logger); inputOutputRule.BindToCollector <OpenType>(typeof(SqlAsyncCollectorBuilder <>), this._configuration, logger); inputOutputRule.BindToInput <OpenType>(typeof(SqlGenericsConverter <>), this._configuration, logger); }
public static void BindToCollector <TAttribute, TMessage>(this FluentBindingRule <TAttribute> rule, Func <TAttribute, ValueBindingContext, Task <IAsyncCollector <TMessage> > > buildFromAttribute) where TAttribute : Attribute { // TEMP: temporary workaround code effectively adding a ValueBindingContext collector overload, // until it's added to the SDK Type patternMatcherType = typeof(FluentBindingRule <>).Assembly.GetType("Microsoft.Azure.WebJobs.Host.Bindings.PatternMatcher"); var patternMatcherNewMethodInfo = patternMatcherType.GetMethods()[4]; // TODO: get this method properly via reflection patternMatcherNewMethodInfo = patternMatcherNewMethodInfo.MakeGenericMethod(new Type[] { typeof(TAttribute), typeof(IAsyncCollector <TMessage>) }); var patternMatcherInstance = patternMatcherNewMethodInfo.Invoke(null, new object[] { buildFromAttribute }); MethodInfo bindToCollectorMethod = typeof(FluentBindingRule <TAttribute>).GetMethod( "BindToCollector", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, binder: null, new Type[] { patternMatcherType }, modifiers: null); bindToCollectorMethod = bindToCollectorMethod.MakeGenericMethod(new Type[] { typeof(TMessage) }); bindToCollectorMethod.Invoke(rule, new object[] { patternMatcherInstance }); }
public void Initialize(ExtensionConfigContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } var extensions = context.Config.GetService <IExtensionRegistry>(); // register trigger binding provider var triggerBindingProvider = new EdgeHubTriggerBindingProvider(); extensions.RegisterExtension <ITriggerBindingProvider>(triggerBindingProvider); extensions.RegisterBindingRules <EdgeHubAttribute>(); FluentBindingRule <EdgeHubAttribute> rule = context.AddBindingRule <EdgeHubAttribute>(); rule.BindToCollector <Message>(typeof(EdgeHubCollectorBuilder)); context.AddConverter <Message, string>(this.MessageConverter); context.AddConverter <string, Message>(this.ConvertToMessage); }