From b32c2489ca299648d93f41b0bfb6963ee3c68298 Mon Sep 17 00:00:00 2001 From: Sam Xu Date: Mon, 7 Aug 2023 15:40:22 -0700 Subject: [PATCH] Fix issue #2712: add overload to set custom uri functions on model scope --- .../PublicAPI/net45/PublicAPI.Shipped.txt | 6 +- .../netcoreapp3.1/PublicAPI.Shipped.txt | 6 +- .../netstandard1.1/PublicAPI.Shipped.txt | 6 +- .../netstandard2.0/PublicAPI.Shipped.txt | 6 +- .../UriParser/Binders/FunctionCallBinder.cs | 16 ++++- .../UriParser/CustomUriFunctions.cs | 67 +++++++++++++++---- .../UriParser/CustomUriFunctionsTests.cs | 22 ++++++ .../Microsoft.OData.PublicApi.net45.bsl | 10 +-- ...crosoft.OData.PublicApi.netstandard1.1.bsl | 6 +- ...crosoft.OData.PublicApi.netstandard2.0.bsl | 10 +-- 10 files changed, 109 insertions(+), 46 deletions(-) diff --git a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Shipped.txt b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Shipped.txt index 94dad90512..1bc3072f61 100644 --- a/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Shipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/net45/PublicAPI.Shipped.txt @@ -2284,9 +2284,9 @@ static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Min -> static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Sum -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.VirtualPropertyCount -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken.Merge(Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token1, Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token2) -> Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken -static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> void -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName) -> bool -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> void +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.Edm.IEdmModel model = null) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> bool static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.Edm.IEdmTypeReference edmTypeReference, Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.RemoveCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> bool diff --git a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Shipped.txt b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Shipped.txt index a4079e2e35..0a83d5d2c3 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Shipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netcoreapp3.1/PublicAPI.Shipped.txt @@ -2291,9 +2291,9 @@ static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Min -> static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Sum -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.VirtualPropertyCount -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken.Merge(Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token1, Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token2) -> Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken -static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> void -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName) -> bool -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> void +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.Edm.IEdmModel model = null) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> bool static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.Edm.IEdmTypeReference edmTypeReference, Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.RemoveCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> bool diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Shipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Shipped.txt index 94dad90512..1bc3072f61 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Shipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netstandard1.1/PublicAPI.Shipped.txt @@ -2284,9 +2284,9 @@ static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Min -> static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Sum -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.VirtualPropertyCount -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken.Merge(Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token1, Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token2) -> Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken -static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> void -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName) -> bool -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> void +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.Edm.IEdmModel model = null) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> bool static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.Edm.IEdmTypeReference edmTypeReference, Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.RemoveCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> bool diff --git a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt index 94dad90512..1bc3072f61 100644 --- a/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt +++ b/src/Microsoft.OData.Core/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt @@ -2284,9 +2284,9 @@ static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Min -> static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.Sum -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition.VirtualPropertyCount -> Microsoft.OData.UriParser.Aggregation.AggregationMethodDefinition static Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken.Merge(Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token1, Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken token2) -> Microsoft.OData.UriParser.Aggregation.EntitySetAggregateToken -static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> void -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName) -> bool -static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.AddCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> void +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.Edm.IEdmModel model = null) -> bool +static Microsoft.OData.UriParser.CustomUriFunctions.RemoveCustomUriFunction(string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, Microsoft.OData.Edm.IEdmModel model = null) -> bool static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.Edm.IEdmTypeReference edmTypeReference, Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.AddCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> void static Microsoft.OData.UriParser.CustomUriLiteralParsers.RemoveCustomUriLiteralParser(Microsoft.OData.UriParser.IUriLiteralParser customUriLiteralParser) -> bool diff --git a/src/Microsoft.OData.Core/UriParser/Binders/FunctionCallBinder.cs b/src/Microsoft.OData.Core/UriParser/Binders/FunctionCallBinder.cs index 8ea1fbde3c..235d67b8fb 100644 --- a/src/Microsoft.OData.Core/UriParser/Binders/FunctionCallBinder.cs +++ b/src/Microsoft.OData.Core/UriParser/Binders/FunctionCallBinder.cs @@ -144,9 +144,11 @@ internal static KeyValuePair MatchSigna /// /// The function call token to get the signatures for. /// Optional flag for whether case insensitive match is enabled. + /// Optional model for whether the custom function is from model scoped or global scoped. In 8.x, it will always from model scoped. /// The signatures which match the supplied function name. [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "need to use lower characters for built-in functions.")] - internal static IList> GetUriFunctionSignatures(string functionCallToken, bool enableCaseInsensitive = false) + internal static IList> GetUriFunctionSignatures(string functionCallToken, + bool enableCaseInsensitive = false, IEdmModel model = null) { IList> customUriFunctionsNameSignatures = null; string builtInUriFunctionName = null; @@ -155,7 +157,15 @@ internal static IList> Get // Try to find the function in the user custom functions bool customFound = CustomUriFunctions.TryGetCustomFunction(functionCallToken, out customUriFunctionsNameSignatures, - enableCaseInsensitive); + enableCaseInsensitive, model); + + // for back-compatibility, we first find custom functions from model scope + // If not found, try to find from global scope + if (!customFound) + { + customFound = CustomUriFunctions.TryGetCustomFunction(functionCallToken, out customUriFunctionsNameSignatures, + enableCaseInsensitive, model: null); + } bool builtInFound = BuiltInUriFunctions.TryGetBuiltInFunction(functionCallToken, enableCaseInsensitive, out builtInUriFunctionName, out builtInUriFunctionsSignatures); @@ -301,7 +311,7 @@ private QueryNode BindAsUriFunction(FunctionCallToken functionCallToken, List> nameSignatures = GetUriFunctionSignatures(functionCallToken.Name, - this.state.Configuration.EnableCaseInsensitiveUriFunctionIdentifier); + this.state.Configuration.EnableCaseInsensitiveUriFunctionIdentifier, this.state.Model); SingleValueNode[] argumentNodeArray = ValidateArgumentsAreSingleValue(functionCallToken.Name, argumentNodes); KeyValuePair nameSignature = MatchSignatureToUriFunction(functionCallToken.Name, argumentNodeArray, nameSignatures); diff --git a/src/Microsoft.OData.Core/UriParser/CustomUriFunctions.cs b/src/Microsoft.OData.Core/UriParser/CustomUriFunctions.cs index 8386eb828d..84e1ebf354 100644 --- a/src/Microsoft.OData.Core/UriParser/CustomUriFunctions.cs +++ b/src/Microsoft.OData.Core/UriParser/CustomUriFunctions.cs @@ -41,11 +41,12 @@ private static readonly Dictionary Cu /// /// The new custom function name /// The new custom function signature + /// The provided model. If it's non-null, the custom Uri functions will be model scoped, otherwise, it's global scoped. /// Arguments are null, or function signature return type is null /// Throws if built-in function name already exists. /// Throws if built-in function signature overload already exists. /// Throws if custom function signature overload already exists - public static void AddCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature) + public static void AddCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature, IEdmModel model = null) { // Parameters validation ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "functionName"); @@ -70,18 +71,21 @@ public static void AddCustomUriFunction(string functionName, FunctionSignatureWi } } - AddCustomFunction(functionName, functionSignature); + AddCustomFunction(functionName, functionSignature, model); } } + /// /// Removes the specific function overload from the custom uri functions. /// /// Custom function name to remove /// The specific signature overload of the function to remove + /// The provided model. If it's non-null, the custom Uri functions will be model scoped, otherwise, it's global scoped. /// 'False' if custom function signature doesn't exist. 'True' if function has been removed successfully /// Arguments are null, or function signature return type is null - public static bool RemoveCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature) + [System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "")] + public static bool RemoveCustomUriFunction(string functionName, FunctionSignatureWithReturnType functionSignature, IEdmModel model = null) { ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "functionName"); ExceptionUtils.CheckArgumentNotNull(functionSignature, "functionSignature"); @@ -90,8 +94,10 @@ public static bool RemoveCustomUriFunction(string functionName, FunctionSignatur lock (Locker) { + Dictionary functionsDict = GetFunctionsDict(model); + FunctionSignatureWithReturnType[] existingCustomFunctionOverloads; - if (!CustomFunctions.TryGetValue(functionName, out existingCustomFunctionOverloads)) + if (!functionsDict.TryGetValue(functionName, out existingCustomFunctionOverloads)) { return false; } @@ -109,31 +115,35 @@ public static bool RemoveCustomUriFunction(string functionName, FunctionSignatur // No overloads have left in this function name. Delete the function name if (customFunctionOverloadsWithoutTheOneToRemove.Length == 0) { - return CustomFunctions.Remove(functionName); + return functionsDict.Remove(functionName); } else { // Requested overload has been removed. // Update the custom functions to the overloads without that one requested to be removed - CustomFunctions[functionName] = customFunctionOverloadsWithoutTheOneToRemove; + functionsDict[functionName] = customFunctionOverloadsWithoutTheOneToRemove; return true; } } } + /// /// Removes all the function overloads from the custom uri functions. /// /// The custom function name + /// The provided model. If it's non-null, the custom Uri functions will be model scoped, otherwise, it's global scoped. /// 'False' if custom function signature doesn't exist. 'True' if function has been removed successfully /// Arguments are null, or function signature return type is null - public static bool RemoveCustomUriFunction(string functionName) + [System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "")] + public static bool RemoveCustomUriFunction(string functionName, IEdmModel model = null) { ExceptionUtils.CheckArgumentStringNotNullOrEmpty(functionName, "functionName"); lock (Locker) { - return CustomFunctions.Remove(functionName); + Dictionary functionsDict = GetFunctionsDict(model); + return functionsDict.Remove(functionName); } } @@ -150,9 +160,10 @@ public static bool RemoveCustomUriFunction(string functionName) /// null if no matches found. /// /// Whether to perform case-insensitive match for function name. + /// The provided model. If it's non-null, the custom Uri functions will be model scoped, otherwise, it's global scoped. /// true if the function was found, or false otherwise. internal static bool TryGetCustomFunction(string functionCallToken, out IList> nameSignatures, - bool enableCaseInsensitive = false) + bool enableCaseInsensitive = false, IEdmModel model = null) { Debug.Assert(functionCallToken != null, "name != null"); @@ -161,7 +172,9 @@ internal static bool TryGetCustomFunction(string functionCallToken, out IList> bufferedKeyValuePairs = new List>(); - foreach (KeyValuePair func in CustomFunctions) + Dictionary functionsDict = GetFunctionsDict(model); + + foreach (KeyValuePair func in functionsDict) { if (func.Key.Equals(functionCallToken, enableCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)) { @@ -183,14 +196,16 @@ IList> bufferedKeyValuePai #region Private Methods - private static void AddCustomFunction(string customFunctionName, FunctionSignatureWithReturnType newCustomFunctionSignature) + private static void AddCustomFunction(string customFunctionName, FunctionSignatureWithReturnType newCustomFunctionSignature, IEdmModel model) { FunctionSignatureWithReturnType[] existingCustomFunctionOverloads; + Dictionary functionsDict = GetFunctionsDict(model); + // In case the function doesn't already exist - if (!CustomFunctions.TryGetValue(customFunctionName, out existingCustomFunctionOverloads)) + if (!functionsDict.TryGetValue(customFunctionName, out existingCustomFunctionOverloads)) { - CustomFunctions.Add(customFunctionName, new FunctionSignatureWithReturnType[] { newCustomFunctionSignature }); + functionsDict.Add(customFunctionName, new FunctionSignatureWithReturnType[] { newCustomFunctionSignature }); } else { @@ -206,7 +221,7 @@ private static void AddCustomFunction(string customFunctionName, FunctionSignatu } // Add the custom function as an overload to the same function name - CustomFunctions[customFunctionName] = + functionsDict[customFunctionName] = existingCustomFunctionOverloads.Concat(new FunctionSignatureWithReturnType[] { newCustomFunctionSignature }).ToArray(); } } @@ -255,6 +270,30 @@ private static void ValidateFunctionWithReturnType(FunctionSignatureWithReturnTy ExceptionUtils.CheckArgumentNotNull(functionSignature.ReturnType, "functionSignatureWithReturnType must contain a return type"); } + private static Dictionary GetFunctionsDict(IEdmModel model) + { + return model == null ? CustomFunctions : GetCustomUriFunctionsContainer(model).CustomFunctions; + } + #endregion + + // The below should be private, set it as internal for unit test only. + internal static CustomUriFunctionsContainer GetCustomUriFunctionsContainer(IEdmModel model) + { + CustomUriFunctionsContainer container = model.GetAnnotationValue(model); + if (container == null) + { + container = new CustomUriFunctionsContainer(); + model.SetAnnotationValue(model, container); + } + + return container; + } + + internal class CustomUriFunctionsContainer + { + public Dictionary CustomFunctions { get; } + = new Dictionary(StringComparer.Ordinal); + } } } diff --git a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/CustomUriFunctionsTests.cs b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/CustomUriFunctionsTests.cs index 1cd421d6a9..706b5d1907 100644 --- a/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/CustomUriFunctionsTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Core.Tests/ScenarioTests/UriParser/CustomUriFunctionsTests.cs @@ -267,6 +267,28 @@ public void AddCustomFunction_CustomFunctionNameExistsButNotFullSignature_Should } } + [Fact] + public void AddCustomFunction_OnModelScope_AddAndRemove() + { + EdmModel model = new EdmModel(); + string customFunctionName = "my.ExistingCustomFunction"; + + // Prepare + FunctionSignatureWithReturnType existingCustomFunctionSignature = + new FunctionSignatureWithReturnType(EdmCoreModel.Instance.GetDouble(false), EdmCoreModel.Instance.GetBoolean(false)); + CustomUriFunctions.AddCustomUriFunction(customFunctionName, existingCustomFunctionSignature, model); + + // Assert + CustomUriFunctions.CustomUriFunctionsContainer container = CustomUriFunctions.GetCustomUriFunctionsContainer(model); + KeyValuePair singleItem = Assert.Single(container.CustomFunctions); + Assert.Equal(customFunctionName, singleItem.Key); + + // Test - removing + CustomUriFunctions.RemoveCustomUriFunction(customFunctionName, model); + container = CustomUriFunctions.GetCustomUriFunctionsContainer(model); + Assert.Empty(container.CustomFunctions); + } + #endregion #region Remove Custom Function diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl index f9924ae521..a9e4941964 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.net45.bsl @@ -6369,9 +6369,9 @@ public abstract class Microsoft.OData.UriParser.SingleValueNode : Microsoft.ODat } public sealed class Microsoft.OData.UriParser.CustomUriFunctions { - public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) - public static bool RemoveCustomUriFunction (string functionName) - public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) + public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) } public sealed class Microsoft.OData.UriParser.CustomUriLiteralPrefixes { @@ -7925,7 +7925,6 @@ public enum Microsoft.OData.Client.SaveChangesOptions : int { BatchWithSingleChangeset = 1 BulkUpdate = 128 ContinueOnError = 2 - DeepInsert = 256 None = 0 PostOnlySetProperties = 8 ReplaceOnUpdate = 4 @@ -8237,7 +8236,6 @@ public class Microsoft.OData.Client.DataServiceContext { public virtual DataServiceQuery`1 CreateQuery (string entitySetName) public virtual DataServiceQuery`1 CreateQuery (string resourcePath, bool isComposable) public virtual DataServiceQuery`1 CreateSingletonQuery (string singletonName) - public virtual Microsoft.OData.Client.DataServiceResponse DeepInsert (T resource) protected System.Type DefaultResolveType (string typeName, string fullNamespace, string languageDependentNamespace) public virtual void DeleteLink (object source, string sourceProperty, object target) public virtual void DeleteObject (object entity) @@ -8304,8 +8302,6 @@ public class Microsoft.OData.Client.DataServiceContext { public virtual System.Threading.Tasks.Task`1[[Microsoft.OData.Client.DataServiceResponse]] SaveChangesAsync (System.Threading.CancellationToken cancellationToken) public virtual System.Threading.Tasks.Task`1[[Microsoft.OData.Client.DataServiceResponse]] SaveChangesAsync (Microsoft.OData.Client.SaveChangesOptions options, System.Threading.CancellationToken cancellationToken) public virtual void SetLink (object source, string sourceProperty, object target) - public virtual void SetRelatedObject (object source, string sourceProperty, object target) - public virtual void SetRelatedObjectLink (object source, string sourceProperty, object target) public virtual void SetSaveStream (object entity, System.IO.Stream stream, bool closeStream, Microsoft.OData.Client.DataServiceRequestArgs args) public virtual void SetSaveStream (object entity, System.IO.Stream stream, bool closeStream, string contentType, string slug) public virtual void SetSaveStream (object entity, string name, System.IO.Stream stream, bool closeStream, Microsoft.OData.Client.DataServiceRequestArgs args) diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl index c30f3b01e8..f06ad235ef 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard1.1.bsl @@ -6369,9 +6369,9 @@ public abstract class Microsoft.OData.UriParser.SingleValueNode : Microsoft.ODat } public sealed class Microsoft.OData.UriParser.CustomUriFunctions { - public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) - public static bool RemoveCustomUriFunction (string functionName) - public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) + public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) } public sealed class Microsoft.OData.UriParser.CustomUriLiteralPrefixes { diff --git a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl index f9924ae521..a9e4941964 100644 --- a/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl +++ b/test/PublicApiTests/BaseLine/Microsoft.OData.PublicApi.netstandard2.0.bsl @@ -6369,9 +6369,9 @@ public abstract class Microsoft.OData.UriParser.SingleValueNode : Microsoft.ODat } public sealed class Microsoft.OData.UriParser.CustomUriFunctions { - public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) - public static bool RemoveCustomUriFunction (string functionName) - public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature) + public static void AddCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, params Microsoft.OData.Edm.IEdmModel model) + public static bool RemoveCustomUriFunction (string functionName, Microsoft.OData.UriParser.FunctionSignatureWithReturnType functionSignature, params Microsoft.OData.Edm.IEdmModel model) } public sealed class Microsoft.OData.UriParser.CustomUriLiteralPrefixes { @@ -7925,7 +7925,6 @@ public enum Microsoft.OData.Client.SaveChangesOptions : int { BatchWithSingleChangeset = 1 BulkUpdate = 128 ContinueOnError = 2 - DeepInsert = 256 None = 0 PostOnlySetProperties = 8 ReplaceOnUpdate = 4 @@ -8237,7 +8236,6 @@ public class Microsoft.OData.Client.DataServiceContext { public virtual DataServiceQuery`1 CreateQuery (string entitySetName) public virtual DataServiceQuery`1 CreateQuery (string resourcePath, bool isComposable) public virtual DataServiceQuery`1 CreateSingletonQuery (string singletonName) - public virtual Microsoft.OData.Client.DataServiceResponse DeepInsert (T resource) protected System.Type DefaultResolveType (string typeName, string fullNamespace, string languageDependentNamespace) public virtual void DeleteLink (object source, string sourceProperty, object target) public virtual void DeleteObject (object entity) @@ -8304,8 +8302,6 @@ public class Microsoft.OData.Client.DataServiceContext { public virtual System.Threading.Tasks.Task`1[[Microsoft.OData.Client.DataServiceResponse]] SaveChangesAsync (System.Threading.CancellationToken cancellationToken) public virtual System.Threading.Tasks.Task`1[[Microsoft.OData.Client.DataServiceResponse]] SaveChangesAsync (Microsoft.OData.Client.SaveChangesOptions options, System.Threading.CancellationToken cancellationToken) public virtual void SetLink (object source, string sourceProperty, object target) - public virtual void SetRelatedObject (object source, string sourceProperty, object target) - public virtual void SetRelatedObjectLink (object source, string sourceProperty, object target) public virtual void SetSaveStream (object entity, System.IO.Stream stream, bool closeStream, Microsoft.OData.Client.DataServiceRequestArgs args) public virtual void SetSaveStream (object entity, System.IO.Stream stream, bool closeStream, string contentType, string slug) public virtual void SetSaveStream (object entity, string name, System.IO.Stream stream, bool closeStream, Microsoft.OData.Client.DataServiceRequestArgs args)