Skip to content

Commit

Permalink
Binding refactor cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mathewc committed Jun 27, 2016
1 parent b71378d commit 520737f
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 192 deletions.
32 changes: 4 additions & 28 deletions src/WebJobs.Script/Binding/ExtensionBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs.Host.Bindings.Path;
using Microsoft.Azure.WebJobs.Host.Bindings.Runtime;
using Microsoft.Azure.WebJobs.Script.Description;
using Microsoft.Azure.WebJobs.Script.Extensibility;
Expand Down Expand Up @@ -54,11 +53,14 @@ public override async Task BindAsync(BindingContext context)
RuntimeBindingContext runtimeContext = new RuntimeBindingContext(attribute, additionalAttributes);

// TEMP: We'll be doing away with this IBinder code
// So for now we don't support binding parameters for Non C#
if (_binding.DefaultType == typeof(IAsyncCollector<byte[]>))
{
await BindAsyncCollectorAsync<byte[]>(context, runtimeContext);
}
else if (_binding.DefaultType == typeof(IAsyncCollector<JObject>))
{
await BindAsyncCollectorAsync<JObject>(context, runtimeContext);
}
else if (_binding.DefaultType == typeof(Stream))
{
await BindStreamAsync(context, Access, runtimeContext);
Expand All @@ -71,10 +73,6 @@ public override async Task BindAsync(BindingContext context)
context.Value = result;
}
}
else if (_binding.DefaultType == typeof(IAsyncCollector<JObject>))
{
await BindAsyncCollectorAsync<JObject>(context, runtimeContext);
}
}

// TEMP - Since we're still using IBinder for non C#, we have to construct the Attributes
Expand Down Expand Up @@ -128,28 +126,6 @@ private Collection<Attribute> ResolveAttributes(Collection<Attribute> attributes
return resolvedAttributes;
}

// TEMP - This code will go away when the Invoker work is done
private string ResolveAndBind(string value, IReadOnlyDictionary<string, string> bindingData)
{
BindingTemplate template = BindingTemplate.FromString(value);

string boundValue = value;
if (bindingData != null)
{
if (template != null)
{
boundValue = template.Bind(bindingData);
}
}

if (!string.IsNullOrEmpty(value))
{
boundValue = Resolve(boundValue);
}

return boundValue;
}

internal class AttributeBuilderInfo
{
public ConstructorInfo Constructor { get; set; }
Expand Down
29 changes: 6 additions & 23 deletions src/WebJobs.Script/Binding/FunctionBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,6 @@ internal static Collection<FunctionBinding> GetBindings(ScriptHostConfiguration
break;
default:
FunctionBinding binding = null;
if (bindingMetadata.Raw == null)
{
// TEMP: This conversion is only here to keep unit tests passing
bindingMetadata.Raw = JObject.FromObject(bindingMetadata);
}
if (TryParseFunctionBinding(config, bindingMetadata.Raw, out binding))
{
bindings.Add(binding);
Expand All @@ -86,9 +81,6 @@ private static bool TryParseFunctionBinding(ScriptHostConfiguration config, Newt
functionBinding = null;

ScriptBindingContext bindingContext = new ScriptBindingContext(metadata);
string type = bindingContext.Type;
string name = (string)metadata.GetValue("name", StringComparison.OrdinalIgnoreCase);
string direction = (string)metadata.GetValue("direction", StringComparison.OrdinalIgnoreCase);
ScriptBinding scriptBinding = null;
foreach (var provider in config.BindingProviders)
{
Expand All @@ -103,29 +95,20 @@ private static bool TryParseFunctionBinding(ScriptHostConfiguration config, Newt
return false;
}

// TEMP: remove the need for this
BindingMetadata bindingMetadata = new BindingMetadata
{
Name = name,
Type = type,
Direction = (BindingDirection)Enum.Parse(typeof(BindingDirection), direction, true)
};

BindingMetadata bindingMetadata = BindingMetadata.Create(metadata);
functionBinding = new ExtensionBinding(config, scriptBinding, bindingMetadata);

return true;
}

protected string ResolveBindingTemplate(string value, BindingTemplate bindingTemplate, IReadOnlyDictionary<string, string> bindingData)
protected string ResolveAndBind(string value, IReadOnlyDictionary<string, string> bindingData)
{
string boundValue = value;
BindingTemplate template = BindingTemplate.FromString(value);

if (bindingData != null)
string boundValue = value;
if (bindingData != null && template != null)
{
if (bindingTemplate != null)
{
boundValue = bindingTemplate.Bind(bindingData);
}
boundValue = template.Bind(bindingData);
}

if (!string.IsNullOrEmpty(value))
Expand Down
86 changes: 85 additions & 1 deletion src/WebJobs.Script/Description/Binding/BindingMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// Licensed under the MIT License. See License.txt in the project root for license information.

using System;
using System.Globalization;
using System.Linq;
using Microsoft.Azure.WebJobs.Host;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
Expand All @@ -13,6 +16,84 @@ namespace Microsoft.Azure.WebJobs.Script.Description
/// </summary>
public class BindingMetadata
{
/// <summary>
/// Creates an instance from the specified raw metadata.
/// </summary>
/// <param name="raw">The raw binding metadata.</param>
/// <param name="nameResolver">Optional name resolver to use on properties.</param>
/// <returns>The new <see cref="BindingMetadata"/> instance.</returns>
public static BindingMetadata Create(JObject raw, INameResolver nameResolver = null)
{
BindingMetadata bindingMetadata = null;
string bindingDirectionValue = (string)raw["direction"];
string connection = (string)raw["connection"];
string bindingType = (string)raw["type"];
BindingDirection bindingDirection = default(BindingDirection);

if (!string.IsNullOrEmpty(bindingDirectionValue) &&
!Enum.TryParse<BindingDirection>(bindingDirectionValue, true, out bindingDirection))
{
throw new FormatException(string.Format(CultureInfo.InvariantCulture, "'{0}' is not a valid binding direction.", bindingDirectionValue));
}

// TODO: Validate the binding type somehow?

if (!string.IsNullOrEmpty(connection) &&
string.IsNullOrEmpty(Utility.GetAppSettingOrEnvironmentValue(connection)))
{
throw new FormatException("Invalid Connection value specified.");
}

switch (bindingType.ToLowerInvariant())
{
case "httptrigger":
bindingMetadata = raw.ToObject<HttpTriggerBindingMetadata>();
break;
case "http":
bindingMetadata = raw.ToObject<HttpBindingMetadata>();
break;
case "table":
bindingMetadata = raw.ToObject<TableBindingMetadata>();
break;
case "manualtrigger":
bindingMetadata = raw.ToObject<BindingMetadata>();
break;
default:
bindingMetadata = raw.ToObject<BindingMetadata>();
break;
}

bindingMetadata.Type = bindingType;
bindingMetadata.Direction = bindingDirection;
bindingMetadata.Connection = connection;

if (nameResolver != null)
{
nameResolver.ResolveAllProperties(bindingMetadata);

// We want to pass resolved metadata values into
// binding extensions, so we resolve fully here
JObject resolved = new JObject(raw);
foreach (JProperty property in resolved.Properties().ToArray())
{
if (property.Value != null &&
property.Value.Type == JTokenType.String)
{
string val = (string)property.Value;
string newVal = nameResolver.ResolveWholeString(val);
resolved[property.Name] = newVal;
}
}
bindingMetadata.Raw = resolved;
}
else
{
bindingMetadata.Raw = raw;
}

return bindingMetadata;
}

/// <summary>
/// Gets or sets the name of the binding.
/// </summary>
Expand Down Expand Up @@ -51,7 +132,10 @@ public bool IsTrigger
}
}

// TEMP
/// <summary>
/// Gets the raw binding metadata (after name resolution has been applied
/// to all values).
/// </summary>
public JObject Raw { get; set; }
}
}
5 changes: 0 additions & 5 deletions src/WebJobs.Script/Description/FunctionDescriptorProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,6 @@ protected virtual ParameterDescriptor CreateTriggerParameter(BindingMetadata tri
triggerParameter = ParseManualTrigger(triggerMetadata, parameterType ?? typeof(string));
break;
default:
if (triggerMetadata.Raw == null)
{
// TEMP: This conversion is only here to keep unit tests passing
triggerMetadata.Raw = JObject.FromObject(triggerMetadata);
}
TryParseTriggerParameter(triggerMetadata.Raw, out triggerParameter, parameterType);
break;
}
Expand Down
68 changes: 1 addition & 67 deletions src/WebJobs.Script/Host/ScriptHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ private static FunctionMetadata ParseFunctionMetadata(string functionName, IName
{
foreach (JObject binding in bindingArray)
{
BindingMetadata bindingMetadata = ParseBindingMetadata(binding, nameResolver);
BindingMetadata bindingMetadata = BindingMetadata.Create(binding, nameResolver);
functionMetadata.Bindings.Add(bindingMetadata);
if (bindingMetadata.IsTrigger)
{
Expand All @@ -409,72 +409,6 @@ private static FunctionMetadata ParseFunctionMetadata(string functionName, IName
return functionMetadata;
}

private static BindingMetadata ParseBindingMetadata(JObject binding, INameResolver nameResolver)
{
BindingMetadata bindingMetadata = null;
string bindingDirectionValue = (string)binding["direction"];
string connection = (string)binding["connection"];
string bindingType = (string)binding["type"];
BindingDirection bindingDirection = default(BindingDirection);

if (!string.IsNullOrEmpty(bindingDirectionValue) &&
!Enum.TryParse<BindingDirection>(bindingDirectionValue, true, out bindingDirection))
{
throw new FormatException(string.Format(CultureInfo.InvariantCulture, "'{0}' is not a valid binding direction.", bindingDirectionValue));
}

// TODO: Validate the binding type somehow?

if (!string.IsNullOrEmpty(connection) &&
string.IsNullOrEmpty(Utility.GetAppSettingOrEnvironmentValue(connection)))
{
throw new FormatException("Invalid Connection value specified.");
}

switch (bindingType.ToLowerInvariant())
{
case "httptrigger":
bindingMetadata = binding.ToObject<HttpTriggerBindingMetadata>();
break;
case "http":
bindingMetadata = binding.ToObject<HttpBindingMetadata>();
break;
case "table":
bindingMetadata = binding.ToObject<TableBindingMetadata>();
break;
case "manualtrigger":
bindingMetadata = binding.ToObject<BindingMetadata>();
break;
default:
// TEMP - Still require a BindingMetadata until refactoring is complete
bindingMetadata = binding.ToObject<BindingMetadata>();
break;
}

bindingMetadata.Type = bindingType;
bindingMetadata.Direction = bindingDirection;
bindingMetadata.Connection = connection;

nameResolver.ResolveAllProperties(bindingMetadata);

// TEMP - We want to pass resolved metadata values into
// binding extensions
JObject resolved = new JObject(binding);
foreach (JProperty property in resolved.Properties().ToArray())
{
if (property.Value != null &&
property.Value.Type == JTokenType.String)
{
string val = (string)property.Value;
string newVal = nameResolver.ResolveWholeString(val);
resolved[property.Name] = newVal;
}
}
bindingMetadata.Raw = resolved;

return bindingMetadata;
}

private Collection<FunctionDescriptor> ReadFunctions(ScriptHostConfiguration config, IEnumerable<FunctionDescriptorProvider> descriptorProviders)
{
string scriptRootPath = config.RootScriptPath;
Expand Down
Loading

0 comments on commit 520737f

Please sign in to comment.