Skip to content

Commit

Permalink
Implement SupportsDeferredBindingAttribute (#1275)
Browse files Browse the repository at this point in the history
  • Loading branch information
liliankasem committed Jan 18, 2023
1 parent 5fd72f7 commit dac0e1b
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,16 @@ public class ExtensionInformationAttribute : Attribute

public bool EnableImplicitRegistration { get; }

public bool SupportsDeferredBinding { get; }

public ExtensionInformationAttribute(string extensionPackage, string extensionVersion)
: this(extensionPackage, extensionVersion, false, false)
: this(extensionPackage, extensionVersion, false)
{
}

public ExtensionInformationAttribute(string extensionPackage, string extensionVersion, bool enableImplicitRegistration)
: this(extensionPackage, extensionVersion, enableImplicitRegistration, false)
{
}

public ExtensionInformationAttribute(string extensionPackage, string extensionVersion, bool enableImplicitRegistration, bool supportsDeferredBinding)
{
ExtensionPackage = extensionPackage;
ExtensionVersion = extensionVersion;
EnableImplicitRegistration = enableImplicitRegistration;
SupportsDeferredBinding = supportsDeferredBinding;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;

namespace Microsoft.Azure.Functions.Worker.Extensions.Abstractions
{
/// <summary>
/// Specifies if a binding attribute supports deferred binding when generating function metadata.
/// This is to be used on input, output or trigger attributes that support deferred binding.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class SupportsDeferredBindingAttribute : Attribute
{
}
}
1 change: 1 addition & 0 deletions sdk/Sdk/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal static class Constants
internal const string FixedDelayRetryAttributeType = "Microsoft.Azure.Functions.Worker.FixedDelayRetryAttribute";
internal const string ExponentialBackoffRetryAttributeType = "Microsoft.Azure.Functions.Worker.ExponentialBackoffRetryAttribute";
internal const string BindingPropertyNameAttributeType = "Microsoft.Azure.Functions.Worker.Extensions.Abstractions.BindingPropertyNameAttribute";
internal const string SupportsDeferredBindingAttributeType = "Microsoft.Azure.Functions.Worker.Extensions.Abstractions.SupportsDeferredBindingAttribute";

// System types
internal const string IEnumerableType = "System.Collections.IEnumerable";
Expand Down
46 changes: 25 additions & 21 deletions sdk/Sdk/FunctionMetadataGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Collections.Generic;

namespace Microsoft.Azure.Functions.Worker.Sdk
{
Expand Down Expand Up @@ -120,7 +118,7 @@ internal IEnumerable<SdkFunctionMetadata> GenerateFunctionMetadata(ModuleDefinit
functions.AddRange(functionsResult);
}

if (!moduleExtensionRegistered && TryAddExtensionInfo(_extensions, module.Assembly, out bool supportsDeferredBinding, usedByFunction: false))
if (!moduleExtensionRegistered && TryAddExtensionInfo(_extensions, module.Assembly, usedByFunction: false))
{
_logger.LogMessage($"Implicitly registered {module.FileName} as an extension.");
}
Expand Down Expand Up @@ -347,7 +345,7 @@ private void AddOutputBindingFromProperty(IList<ExpandoObject> bindingMetadata,
foundOutputAttribute = true;

AddOutputBindingMetadata(bindingMetadata, propertyAttribute, property.PropertyType, property.Name);
AddExtensionInfo(_extensions, propertyAttribute, out bool supportsDeferredBinding);
AddExtensionInfo(_extensions, propertyAttribute);
}
}
}
Expand All @@ -367,7 +365,7 @@ private bool TryAddOutputBindingFromMethod(IList<ExpandoObject> bindingMetadata,
}

AddOutputBindingMetadata(bindingMetadata, methodAttribute, methodAttribute.AttributeType, Constants.ReturnBindingName);
AddExtensionInfo(_extensions, methodAttribute, out bool supportsDeferredBinding);
AddExtensionInfo(_extensions, methodAttribute);

foundBinding = true;
}
Expand All @@ -384,8 +382,8 @@ private void AddInputTriggerBindingsAndExtensions(IList<ExpandoObject> bindingMe
{
if (IsFunctionBindingType(parameterAttribute))
{
AddExtensionInfo(_extensions, parameterAttribute, out bool supportsDeferredBinding);
AddBindingMetadata(bindingMetadata, parameterAttribute, parameter.ParameterType, parameter.Name, supportsDeferredBinding);
AddExtensionInfo(_extensions, parameterAttribute);
AddBindingMetadata(bindingMetadata, parameterAttribute, parameter.ParameterType, parameter.Name);
}
}
}
Expand Down Expand Up @@ -416,10 +414,10 @@ private static void AddOutputBindingMetadata(IList<ExpandoObject> bindingMetadat
AddBindingMetadata(bindingMetadata, attribute, parameterType, parameterName: name);
}

private static void AddBindingMetadata(IList<ExpandoObject> bindingMetadata, CustomAttribute attribute, TypeReference parameterType, string? parameterName, bool supportsReferenceType = false)
private static void AddBindingMetadata(IList<ExpandoObject> bindingMetadata, CustomAttribute attribute, TypeReference parameterType, string? parameterName)
{
string bindingType = GetBindingType(attribute);
ExpandoObject binding = BuildBindingMetadataFromAttribute(attribute, bindingType, parameterType, parameterName, supportsReferenceType);
ExpandoObject binding = BuildBindingMetadataFromAttribute(attribute, bindingType, parameterType, parameterName);
bindingMetadata.Add(binding);
}

Expand Down Expand Up @@ -471,7 +469,7 @@ private static void AddBindingMetadata(IList<ExpandoObject> bindingMetadata, Cus
return bindingNameAliasMap;
}

private static ExpandoObject BuildBindingMetadataFromAttribute(CustomAttribute attribute, string bindingType, TypeReference parameterType, string? parameterName, bool supportsDeferredBinding)
private static ExpandoObject BuildBindingMetadataFromAttribute(CustomAttribute attribute, string bindingType, TypeReference parameterType, string? parameterName)
{
ExpandoObject binding = new ExpandoObject();

Expand All @@ -489,7 +487,7 @@ private static ExpandoObject BuildBindingMetadataFromAttribute(CustomAttribute a

// For extensions that support deferred binding, set the supportsDeferredBinding property so parameters are bound by the worker
// Only use deferred binding for input and trigger bindings, output is out not currently supported
if (supportsDeferredBinding && direction != Constants.OutputBindingDirection)
if (SupportsDeferredBinding(attribute) && direction != Constants.OutputBindingDirection)
{
bindingProperties.Add(Constants.SupportsDeferredBindingProperty, Boolean.TrueString);
}
Expand Down Expand Up @@ -752,16 +750,14 @@ private static void AddHttpOutputBinding(IList<ExpandoObject> bindingMetadata, s
bindingMetadata.Add((ExpandoObject)returnBinding);
}

private static void AddExtensionInfo(IDictionary<string, string> extensions, CustomAttribute attribute, out bool supportsDeferredBinding)
private static void AddExtensionInfo(IDictionary<string, string> extensions, CustomAttribute attribute)
{
AssemblyDefinition extensionAssemblyDefinition = attribute.AttributeType.Resolve().Module.Assembly;
TryAddExtensionInfo(extensions, extensionAssemblyDefinition, out supportsDeferredBinding);
TryAddExtensionInfo(extensions, extensionAssemblyDefinition);
}

private static bool TryAddExtensionInfo(IDictionary<string, string> extensions, AssemblyDefinition extensionAssemblyDefinition, out bool supportsDeferredBinding, bool usedByFunction = true)
private static bool TryAddExtensionInfo(IDictionary<string, string> extensions, AssemblyDefinition extensionAssemblyDefinition, bool usedByFunction = true)
{
supportsDeferredBinding = false;

foreach (var assemblyAttribute in extensionAssemblyDefinition.CustomAttributes)
{
if (string.Equals(assemblyAttribute.AttributeType.FullName, Constants.ExtensionsInformationType, StringComparison.Ordinal))
Expand All @@ -775,11 +771,6 @@ private static bool TryAddExtensionInfo(IDictionary<string, string> extensions,
// EnableImplicitRegistration
implicitlyRegister = (bool)assemblyAttribute.ConstructorArguments[2].Value;
}

if (assemblyAttribute.ConstructorArguments.Count >= 4)
{
supportsDeferredBinding = (bool)assemblyAttribute.ConstructorArguments[3].Value;
}

if (usedByFunction || implicitlyRegister)
{
Expand All @@ -804,6 +795,19 @@ private static string GetBindingDirection(CustomAttribute attribute)
return Constants.InputBindingDirection;
}

private static bool SupportsDeferredBinding(CustomAttribute attribute)
{
var typeDefinition = attribute?.AttributeType?.Resolve();

if (typeDefinition is null)
{
return false;
}

return typeDefinition.CustomAttributes
.Any(a => string.Equals(a.AttributeType.FullName, Constants.SupportsDeferredBindingAttributeType, StringComparison.Ordinal));
}

private static bool IsOutputBindingType(CustomAttribute attribute)
{
return TryGetBaseAttributeType(attribute, Constants.OutputBindingType, out _);
Expand Down

0 comments on commit dac0e1b

Please sign in to comment.