From 343c45ded7a824cbf4004c2e04fd5ec60488816a Mon Sep 17 00:00:00 2001 From: Andrii Snihyr Date: Thu, 28 Mar 2019 17:28:36 -0700 Subject: [PATCH 1/2] Add CodeGen support for emitting dynamic properties on open types --- src/CodeGen/ODataT4CodeGenerator.tt | 168 +- src/CodeGen/ODataT4CodeGenerator.ttinclude | 10467 ++++++++++--------- 2 files changed, 5369 insertions(+), 5266 deletions(-) diff --git a/src/CodeGen/ODataT4CodeGenerator.tt b/src/CodeGen/ODataT4CodeGenerator.tt index 827915264b..a7589df3a8 100644 --- a/src/CodeGen/ODataT4CodeGenerator.tt +++ b/src/CodeGen/ODataT4CodeGenerator.tt @@ -1,79 +1,89 @@ -<#@ include file="ODataT4CodeGenerator.ttinclude" #> -<#+ -public static class Configuration -{ - // The URI of the metadata document. The value must be set to a valid service document URI or a local file path - // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx" - // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of - // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail. - public const string MetadataDocumentUri = ""; - - // The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false. - public const bool UseDataServiceCollection = true; - - // The namespace of the client code generated. It replaces the original namespace in the metadata document, - // unless the model has several namespaces. - public const string NamespacePrefix = "$rootnamespace$"; - - // The target language of the generated client code. The value must be set to "CSharp" or "VB". - public const string TargetLanguage = "OutputLanguage"; - - // The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path. - // For example - "C:\\temp\\Test.xml" - public const string TempFilePath = ""; - - // This flag indicates whether to enable naming alias. The value must be set to true or false. - public const bool EnableNamingAlias = true; - - // This flag indicates whether to ignore unexpected elements and attributes in the metadata document and generate - // the client code if any. The value must be set to true or false. - public const bool IgnoreUnexpectedElementsAndAttributes = true; -} - -public static class Customization -{ - /// - /// Changes the text to use upper camel case, which upper case for the first character. - /// - /// Text to convert. - /// The converted text in upper camel case - internal static string CustomizeNaming(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return Char.ToUpperInvariant(text[0]).ToString(CultureInfo.InvariantCulture); - } - - return Char.ToUpperInvariant(text[0]) + text.Substring(1); - } - - /// - /// Changes the namespace to use upper camel case, which upper case for the first character of all segments. - /// - /// Namespace to convert. - /// The converted namespace in upper camel case - internal static string CustomizeNamespace(string fullNamespace) - { - if (string.IsNullOrEmpty(fullNamespace)) - { - return fullNamespace; - } - - string[] segs = fullNamespace.Split('.'); - string upperNamespace = string.Empty; - int n = segs.Length; - for (int i = 0; i < n; ++i) - { - upperNamespace += Customization.CustomizeNaming(segs[i]); - upperNamespace += (i == n - 1 ? string.Empty : "."); - } - - return upperNamespace; - } -} -#> \ No newline at end of file +<#@ include file="ODataT4CodeGenerator.ttinclude" #> +<#+ +public static class Configuration +{ + // The URI of the metadata document. The value must be set to a valid service document URI or a local file path + // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx" + // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of + // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail. + public const string MetadataDocumentUri = ""; + + // The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false. + public const bool UseDataServiceCollection = true; + + // The namespace of the client code generated. It replaces the original namespace in the metadata document, + // unless the model has several namespaces. + public const string NamespacePrefix = "$rootnamespace$"; + + // The target language of the generated client code. The value must be set to "CSharp" or "VB". + public const string TargetLanguage = "OutputLanguage"; + + // The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path. + // For example - "C:\\temp\\Test.xml" + public const string TempFilePath = ""; + + // This flag indicates whether to enable naming alias. The value must be set to true or false. + public const bool EnableNamingAlias = true; + + // This flag indicates whether to ignore unexpected elements and attributes in the metadata document and generate + // the client code if any. The value must be set to true or false. + public const bool IgnoreUnexpectedElementsAndAttributes = true; + + // This flag indicates whether to generate an additional Dictionary property + // to store dynamic properties in open types. The value must be set to true or false. + public const bool GenerateDynamicPropertiesCollection = true; + + // This defines the name of Dictionary properties + // that store dynamic properties in open types. This property is only applicable if + // GenerateDynamicPropertiesCollection is set to true. This value must be + // a valid identifier name. + public const string DynamicPropertiesCollectionName = "DynamicProperties"; +} + +public static class Customization +{ + /// + /// Changes the text to use upper camel case, which upper case for the first character. + /// + /// Text to convert. + /// The converted text in upper camel case + internal static string CustomizeNaming(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return Char.ToUpperInvariant(text[0]).ToString(CultureInfo.InvariantCulture); + } + + return Char.ToUpperInvariant(text[0]) + text.Substring(1); + } + + /// + /// Changes the namespace to use upper camel case, which upper case for the first character of all segments. + /// + /// Namespace to convert. + /// The converted namespace in upper camel case + internal static string CustomizeNamespace(string fullNamespace) + { + if (string.IsNullOrEmpty(fullNamespace)) + { + return fullNamespace; + } + + string[] segs = fullNamespace.Split('.'); + string upperNamespace = string.Empty; + int n = segs.Length; + for (int i = 0; i < n; ++i) + { + upperNamespace += Customization.CustomizeNaming(segs[i]); + upperNamespace += (i == n - 1 ? string.Empty : "."); + } + + return upperNamespace; + } +} +#> diff --git a/src/CodeGen/ODataT4CodeGenerator.ttinclude b/src/CodeGen/ODataT4CodeGenerator.ttinclude index 90fe80cd10..67d68d988b 100644 --- a/src/CodeGen/ODataT4CodeGenerator.ttinclude +++ b/src/CodeGen/ODataT4CodeGenerator.ttinclude @@ -1,5187 +1,5280 @@ -<# -/* -OData Client T4 Template ver. #VersionNumber# -Copyright (c) Microsoft Corporation -All rights reserved. -MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#> -<#@ template debug="true" hostSpecific="true" visibility="internal" linePragmas="false"#> -<#@ output extension=".cs" #> -<#@ Assembly Name="System.Core.dll" #> -<#@ Assembly Name="System.IO.dll" #> -<#@ Assembly Name="System.Runtime.dll" #> -<#@ Assembly Name="System.Xml.dll" #> -<#@ Assembly Name="System.Xml.Linq.dll" #> -<#@ Assembly Name="System.Xml.ReaderWriter.dll" #> -<#@ Assembly Name="System.Windows.Forms.dll" #> -<#@ Assembly Name="Microsoft.OData.Client.dll" #> -<#@ Assembly Name="Microsoft.OData.Core.dll" #> -<#@ Assembly Name="Microsoft.OData.Edm.dll" #> -<#@ Assembly Name="Microsoft.Spatial.dll" #> -<#@ Import Namespace="System" #> -<#@ Import Namespace="System.IO" #> -<#@ Import Namespace="System.Diagnostics" #> -<#@ Import Namespace="System.Globalization" #> -<#@ Import Namespace="System.Linq" #> -<#@ Import Namespace="System.Xml"#> -<#@ Import Namespace="System.Xml.Linq" #> -<#@ Import Namespace="System.Collections.Generic" #> -<#@ Import Namespace="Microsoft.OData.Edm.Csdl" #> -<#@ Import Namespace="Microsoft.OData.Edm" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.V1" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.Community.V1" #> -<#@ Import Namespace="System.Text"#> -<#@ Import Namespace="System.Net"#> -<# - CodeGenerationContext context; - if (!string.IsNullOrWhiteSpace(this.Edmx)) - { - context = new CodeGenerationContext(this.Edmx, this.NamespacePrefix) - { - UseDataServiceCollection = this.UseDataServiceCollection, - TargetLanguage = this.TargetLanguage, - EnableNamingAlias = this.EnableNamingAlias, - TempFilePath = this.TempFilePath, - IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes - }; - } - else - { - this.ApplyParametersFromCommandLine(); - if (string.IsNullOrEmpty(metadataDocumentUri)) - { - this.ApplyParametersFromConfigurationClass(); - } - - context = new CodeGenerationContext(new Uri(this.MetadataDocumentUri, UriKind.Absolute), this.NamespacePrefix) - { - UseDataServiceCollection = this.UseDataServiceCollection, - TargetLanguage = this.TargetLanguage, - EnableNamingAlias = this.EnableNamingAlias, - TempFilePath = this.TempFilePath, - IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes - }; - } - - if (this.GetReferencedModelReaderFunc != null) - { - context.GetReferencedModelReaderFunc = this.GetReferencedModelReaderFunc; - } - - ODataClientTemplate template; - switch(this.TargetLanguage) - { - case LanguageOption.CSharp: - template = new ODataClientCSharpTemplate(context); - break; - case LanguageOption.VB: - template = new ODataClientVBTemplate(context); - break; - - default: - throw new NotSupportedException(string.Format("Code gen for the target language '{0}' is not supported.", this.TargetLanguage.ToString())); - } - -#><#=template.TransformText()#><# - foreach (string warning in context.Warnings) - { - this.Warning(warning); - } -#><#+ -/// -/// The string for the edmx content. -/// -public string Edmx -{ - get; - set; -} - -/// -/// The Uri string to the metadata document. -/// -public string MetadataDocumentUri -{ - get - { - return this.metadataDocumentUri; - } - - set - { - value = Uri.UnescapeDataString(value); - Uri uri; - if (!Uri.TryCreate(value, UriKind.Absolute, out uri)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" is not a valid MetadataDocumentUri because is it not a valid absolute Uri. The MetadataDocumentUri must be set to an absolute Uri referencing the $metadata endpoint of an OData service.", value)); - } - - if (uri.Scheme == "http" || uri.Scheme == "https") - { - value = uri.Scheme + "://" + uri.Authority + uri.AbsolutePath; - value = value.TrimEnd('/'); - if (!value.EndsWith("$metadata")) - { - value += "/$metadata"; - } - } - - this.metadataDocumentUri = value; - } -} - -private string metadataDocumentUri; - -/// -/// The Func to get referenced model's XmlReader. Must have value when the this.Edmx xml or this.metadataDocumentUri's model has referneced model. -/// -public Func GetReferencedModelReaderFunc -{ - get; - set; -} - -/// -/// The NamespacePrefix is used as the only namespace for types in the same namespace as the default container, -/// and as a prefix for the namespace from the model for everything else. If this argument is null, the -/// namespaces from the model are used for all types. -/// -public string NamespacePrefix -{ - get - { - return this.namespacePrefix; - } - - set - { - if (string.IsNullOrWhiteSpace(value)) - { - this.namespacePrefix = null; - } - else - { - this.namespacePrefix = value; - } - } -} - -private string namespacePrefix; - -/// -/// true to use DataServiceCollection in the generated code, false otherwise. -/// -public bool UseDataServiceCollection -{ - get; - set; -} - -/// -/// Specifies which specific .Net Framework language the generated code will target. -/// -public LanguageOption TargetLanguage -{ - get; - set; -} - -/// -/// true to use Upper camel case for all class and property names, false otherwise. -/// -public bool EnableNamingAlias -{ - get; - set; -} - -/// -/// The path for the temporary file where the metadata xml document can be stored. -/// -public string TempFilePath -{ - get; - set; -} - -/// -/// true to ignore unknown elements or attributes in metadata, false otherwise. -/// -public bool IgnoreUnexpectedElementsAndAttributes -{ - get; - set; -} - -/// -/// Generate code targeting a specific .Net Framework language. -/// -public enum LanguageOption -{ - /// Generate code for C# language. - CSharp = 0, - - /// Generate code for Visual Basic language. - VB = 1, -} - -/// -/// Set the UseDataServiceCollection property with the given value. -/// -/// The value to set. -public void ValidateAndSetUseDataServiceCollectionFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the UseDataServiceCollection parameter because it is not a valid boolean value.", stringValue)); - } - - this.UseDataServiceCollection = boolValue; -} - -/// -/// Tries to set the TargetLanguage property with the given value. -/// -/// The value to set. -public void ValidateAndSetTargetLanguageFromString(string stringValue) -{ - LanguageOption option; - if (!Enum.TryParse(stringValue, true, out option)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the TargetLanguage parameter because it is not a valid LanguageOption. The supported LanguageOptions are \"CSharp\" and \"VB\".", stringValue)); - } - - this.TargetLanguage = option; -} - -/// -/// Set the EnableNamingAlias property with the given value. -/// -/// The value to set. -public void ValidateAndSetEnableNamingAliasFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the EnableNamingAlias parameter because it is not a valid boolean value.", stringValue)); - } - - this.EnableNamingAlias = boolValue; -} - -/// -/// Set the IgnoreUnexpectedElementsAndAttributes property with the given value. -/// -/// The value to set. -public void ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the IgnoreUnexpectedElementsAndAttributes parameter because it is not a valid boolean value.", stringValue)); - } - - this.IgnoreUnexpectedElementsAndAttributes = boolValue; -} - -/// -/// Reads the parameter values from the Configuration class and applies them. -/// -private void ApplyParametersFromConfigurationClass() -{ - this.MetadataDocumentUri = Configuration.MetadataDocumentUri; - this.NamespacePrefix = Configuration.NamespacePrefix; - this.UseDataServiceCollection = Configuration.UseDataServiceCollection; - this.ValidateAndSetTargetLanguageFromString(Configuration.TargetLanguage); - this.EnableNamingAlias = Configuration.EnableNamingAlias; - this.TempFilePath = Configuration.TempFilePath; - this.IgnoreUnexpectedElementsAndAttributes = Configuration.IgnoreUnexpectedElementsAndAttributes; -} - -/// -/// Reads the parameter values from the command line (TextTransform.exe) and applies them. -/// -private void ApplyParametersFromCommandLine() -{ - if (this.Host == null) - { - return; - } - - string metadataDocumentUri = this.Host.ResolveParameterValue("notempty", "notempty", "MetadataDocumentUri"); - if (!string.IsNullOrEmpty(metadataDocumentUri)) - { - this.MetadataDocumentUri = metadataDocumentUri; - } - - string namespacePrefix = this.Host.ResolveParameterValue("notempty", "notempty", "NamespacePrefix"); - if (!string.IsNullOrEmpty(namespacePrefix)) - { - this.NamespacePrefix = namespacePrefix; - } - - string useDataServiceCollection = this.Host.ResolveParameterValue("notempty", "notempty", "UseDataServiceCollection"); - if (!string.IsNullOrEmpty(useDataServiceCollection)) - { - this.ValidateAndSetUseDataServiceCollectionFromString(useDataServiceCollection); - } - - string targetLanguage = this.Host.ResolveParameterValue("notempty", "notempty", "TargetLanguage"); - if (!string.IsNullOrEmpty(targetLanguage)) - { - this.ValidateAndSetTargetLanguageFromString(targetLanguage); - } - - string enableNamingAlias = this.Host.ResolveParameterValue("notempty", "notempty", "EnableNamingAlias"); - if (!string.IsNullOrEmpty(enableNamingAlias)) - { - this.ValidateAndSetEnableNamingAliasFromString(enableNamingAlias); - } - - string ignoreUnexpectedElementsAndAttributes = this.Host.ResolveParameterValue("notempty", "notempty", "IgnoreUnexpectedElementsAndAttributes"); - if (!string.IsNullOrEmpty(ignoreUnexpectedElementsAndAttributes)) - { - this.ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(ignoreUnexpectedElementsAndAttributes); - } -} - -/// -/// Context object to provide the model and configuration info to the code generator. -/// -public class CodeGenerationContext -{ - /// - /// The namespace of the term to use when building annotations for indicating the conventions used. - /// - private const string ConventionTermNamespace = "Com.Microsoft.OData.Service.Conventions.V1"; - - /// - /// The name of the term to use when building annotations for indicating the conventions used. - /// - private const string ConventionTermName = "UrlConventions"; - - /// - /// The string value for indicating that the key-as-segment convention is being used in annotations and headers. - /// - private const string KeyAsSegmentConventionName = "KeyAsSegment"; - - /// - /// The XElement for the edmx - /// - private readonly XElement edmx; - - /// - /// The namespacePrefix is used as the only namespace in generated code when there's only one schema in edm model, - /// and as a prefix for the namespace from the model with multiple schemas. If this argument is null, the - /// namespaces from the model are used for all types. - /// - private readonly string namespacePrefix; - - /// - /// The EdmModel to generate code for. - /// - private IEdmModel edmModel; - - /// - /// The array of namespaces in the current edm model. - /// - private string[] namespacesInModel; - - /// - /// The array of warnings occured when parsing edm model. - /// - private string[] warnings; - - /// - /// true if the model contains any structural type with inheritance, false otherwise. - /// - private bool? modelHasInheritance; - - /// - /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. - /// Otherwise this is an empty dictionary. - /// - private Dictionary namespaceMap; - - /// - /// Maps the element type of a navigation source to the navigation source. - /// - private Dictionary> elementTypeToNavigationSourceMap; - - /// - /// HashSet contains the pair of Names and Namespaces of EntityContainers using KeyAsSegment url convention - /// - private HashSet keyAsSegmentContainers; - - /// - /// Constructs an instance of . - /// - /// The Uri to the metadata document. The supported scheme are File, http and https. - public CodeGenerationContext(Uri metadataUri, string namespacePrefix) - : this(GetEdmxStringFromMetadataPath(metadataUri), namespacePrefix) - { - } - - /// - /// Constructs an instance of . - /// - /// The string for the edmx. - /// The namespacePrefix is used as the only namespace in generated code - /// when there's only one schema in edm model, and as a prefix for the namespace from the model with multiple - /// schemas. If this argument is null, the namespaces from the model are used for all types. - public CodeGenerationContext(string edmx, string namespacePrefix) - { - this.edmx = XElement.Parse(edmx); - this.namespacePrefix = namespacePrefix; - } - - /// - /// The EdmModel to generate code for. - /// - public XElement Edmx - { - get { return this.edmx; } - } - - /// - /// The EdmModel to generate code for. - /// - public IEdmModel EdmModel - { - get - { - if (this.edmModel == null) - { - Debug.Assert(this.edmx != null, "this.edmx != null"); - - IEnumerable errors; - CsdlReaderSettings edmxReaderSettings = new CsdlReaderSettings() - { - GetReferencedModelReaderFunc = this.GetReferencedModelReaderFuncWrapper, - IgnoreUnexpectedAttributesAndElements = this.IgnoreUnexpectedElementsAndAttributes - }; - if (!CsdlReader.TryParse(this.edmx.CreateReader(ReaderOptions.None), Enumerable.Empty(), edmxReaderSettings, out this.edmModel, out errors)) - { - Debug.Assert(errors != null, "errors != null"); - throw new InvalidOperationException(errors.FirstOrDefault().ErrorMessage); - } - else if (this.IgnoreUnexpectedElementsAndAttributes) - { - if (errors != null && errors.Any()) - { - this.warnings = errors.Select(e => e.ErrorMessage).ToArray(); - } - } - } - - return this.edmModel; - } - } - - /// - /// The func for user code to overwrite and provide referenced model's XmlReader. - /// - public Func GetReferencedModelReaderFunc - { - get { return getReferencedModelReaderFunc; } - set { this.getReferencedModelReaderFunc = value; } - } - - /// - /// Basic setting for XmlReader. - /// - private static readonly XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true }; - - /// - /// The func for user code to overwrite and provide referenced model's XmlReader. - /// - private Func getReferencedModelReaderFunc = uri => XmlReader.Create(GetEdmxStreamFromUri(uri), settings); - - /// - /// The Wrapper func for user code to overwrite and provide referenced model's stream. - /// - public Func GetReferencedModelReaderFuncWrapper - { - get - { - return (uri) => - { - using (XmlReader reader = GetReferencedModelReaderFunc(uri)) - { - if (reader == null) - { - return null; - } - - XElement element = XElement.Load(reader); - if (this.ReferencesMap == null) - { - this.ReferencesMap = new Dictionary(); - } - - this.ReferencesMap.Add(uri, element); - return element.CreateReader(ReaderOptions.None); - } - }; - } - } - - /// - /// Dictionary that stores uri and referenced xml mapping. - /// - public Dictionary ReferencesMap - { - get; - set; - } - - /// - /// The array of namespaces in the current edm model. - /// - public string[] NamespacesInModel - { - get - { - if (this.namespacesInModel == null) - { - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - this.namespacesInModel = GetElementsFromModelTree(this.EdmModel, (m) => m.SchemaElements.Select(e => e.Namespace)).Distinct().ToArray(); - } - - return this.namespacesInModel; - } - } - - /// - /// The array of warnings occured when parsing edm model. - /// - public string[] Warnings - { - get { return this.warnings ?? (this.warnings = new string[] {}); } - } - - /// - /// true if the model contains any structural type with inheritance, false otherwise. - /// - public bool ModelHasInheritance - { - get - { - if (!this.modelHasInheritance.HasValue) - { - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - this.modelHasInheritance = this.EdmModel.SchemaElementsAcrossModels() - .OfType().Any(t => !t.FullTypeName().StartsWith("Org.OData.Authorization.V1") && - !t.FullTypeName().StartsWith("Org.OData.Capabilities.V1") && t.BaseType != null); - } - - return this.modelHasInheritance.Value; - } - } - - /// - /// true if we need to generate the ResolveNameFromType method, false otherwise. - /// - public bool NeedResolveNameFromType - { - get { return this.ModelHasInheritance || this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } - } - - /// - /// true if we need to generate the ResolveTypeFromName method, false otherwise. - /// - public bool NeedResolveTypeFromName - { - get { return this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } - } - - /// - /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. - /// Otherwise this is an empty dictionary. - /// - public Dictionary NamespaceMap - { - get - { - if (this.namespaceMap == null) - { - if (!string.IsNullOrEmpty(this.namespacePrefix)) - { - if (this.NamespacesInModel.Count() == 1) - { - IEdmEntityContainer container = this.EdmModel.EntityContainer; - string containerNamespace = container == null ? null : container.Namespace; - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => ns == containerNamespace ? - this.namespacePrefix : - this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); - } - else - { - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); - } - } - else if (this.EnableNamingAlias) - { - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => Customization.CustomizeNamespace(ns)); - } - else - { - this.namespaceMap = new Dictionary(); - } - } - - return this.namespaceMap; - } - } - - /// - /// true to use DataServiceCollection in the generated code, false otherwise. - /// - public bool UseDataServiceCollection - { - get; - set; - } - - /// - /// Specifies which specific .Net Framework language the generated code will target. - /// - public LanguageOption TargetLanguage - { - get; - set; - } - - /// - /// The path for the temporary file where the metadata xml document can be stored. - /// - public string TempFilePath - { - get; - set; - } - /// - /// true to use Upper camel case for all class and property names, false otherwise. - /// - public bool EnableNamingAlias - { - get; - set; - } - - /// - /// true to ignore unknown elements or attributes in metadata, false otherwise. - /// - public bool IgnoreUnexpectedElementsAndAttributes - { - get; - set; - } - - /// - /// Maps the element type of an entity set to the entity set. - /// - public Dictionary> ElementTypeToNavigationSourceMap - { - get - { - return this.elementTypeToNavigationSourceMap ?? (this.elementTypeToNavigationSourceMap = new Dictionary>(EqualityComparer.Default)); - } - } - - /// - /// true if this EntityContainer need to set the UrlConvention to KeyAsSegment, false otherwise. - /// - public bool UseKeyAsSegmentUrlConvention(IEdmEntityContainer currentContainer) - { - if (this.keyAsSegmentContainers == null) - { - this.keyAsSegmentContainers = new HashSet(); - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - IEnumerable annotations = this.EdmModel.VocabularyAnnotations; - foreach(IEdmVocabularyAnnotation valueAnnotation in annotations) - { - IEdmEntityContainer container = valueAnnotation.Target as IEdmEntityContainer; - IEdmTerm valueTerm = valueAnnotation.Term; - IEdmStringConstantExpression expression = valueAnnotation.Value as IEdmStringConstantExpression; - if (container != null && valueTerm != null && expression != null) - { - if (valueTerm.Namespace == ConventionTermNamespace && - valueTerm.Name == ConventionTermName && - expression.Value == KeyAsSegmentConventionName) - { - this.keyAsSegmentContainers.Add(container.FullName()); - } - } - } - } - - return this.keyAsSegmentContainers.Contains(currentContainer.FullName()); - } - - /// - /// Gets the enumeration of schema elements with the given namespace. - /// - /// The namespace of the schema elements to get. - /// The enumeration of schema elements with the given namespace. - public IEnumerable GetSchemaElements(string ns) - { - Debug.Assert(ns != null, "ns != null"); - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - return GetElementsFromModelTree(this.EdmModel, m => m.SchemaElements.Where(e => e.Namespace == ns)); - } - - /// - /// Gets the namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. - /// - /// The schema element to get the full name for. - /// The fixed name of this schemaElement. - /// The current code generate template. - /// The namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. - public string GetPrefixedFullName(IEdmSchemaElement schemaElement, string schemaElementFixedName, ODataClientTemplate template, bool needGlobalPrefix = true) - { - if (schemaElement == null) - { - return null; - } - - return this.GetPrefixedNamespace(schemaElement.Namespace, template, true, needGlobalPrefix) + "." + schemaElementFixedName; - } - - /// - /// Gets the prefixed namespace for the given . - /// - /// The namespace without the prefix. - /// The current code generate template. - /// The flag indicates whether the namespace need to be fixed now. - /// The flag indicates whether the namespace need to be added by gloabal prefix. - /// The prefixed namespace for the given . - public string GetPrefixedNamespace(string ns, ODataClientTemplate template, bool needFix, bool needGlobalPrefix) - { - if (ns == null) - { - return null; - } - - string prefixedNamespace; - if (!this.NamespaceMap.TryGetValue(ns, out prefixedNamespace)) - { - prefixedNamespace = ns; - } - - if (needFix) - { - string[] segments = prefixedNamespace.Split('.'); - prefixedNamespace = string.Empty; - int n = segments.Length; - for (int i = 0; i < n; ++i) - { - if (template.LanguageKeywords.Contains(segments[i])) - { - prefixedNamespace += string.Format(template.FixPattern, segments[i]); - } - else - { - prefixedNamespace += segments[i]; - } - - prefixedNamespace += (i == n - 1 ? string.Empty : "."); - } - } - - if (needGlobalPrefix) - { - prefixedNamespace = template.GlobalPrefix + prefixedNamespace; - } - - return prefixedNamespace; - } - - /// - /// Reads the edmx string from a file path or a http/https path. - /// - /// The Uri to the metadata document. The supported scheme are File, http and https. - private static string GetEdmxStringFromMetadataPath(Uri metadataUri) - { - string content = null; - using (StreamReader streamReader = new StreamReader(GetEdmxStreamFromUri(metadataUri))) - { - content = streamReader.ReadToEnd(); - } - - return content; - } - - /// - /// Get the metadata stream from a file path or a http/https path. - /// - /// The Uri to the stream. The supported scheme are File, http and https. - private static Stream GetEdmxStreamFromUri(Uri metadataUri) - { - Debug.Assert(metadataUri != null, "metadataUri != null"); - Stream metadataStream = null; - if (metadataUri.Scheme == "file") - { - metadataStream = new FileStream(Uri.UnescapeDataString(metadataUri.AbsolutePath), FileMode.Open, FileAccess.Read); - } - else if (metadataUri.Scheme == "http" || metadataUri.Scheme == "https") - { - try - { - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(metadataUri); - WebResponse webResponse = webRequest.GetResponse(); - metadataStream = webResponse.GetResponseStream(); - } - catch (WebException e) - { - HttpWebResponse webResponse = e.Response as HttpWebResponse; - if (webResponse != null && webResponse.StatusCode == HttpStatusCode.Unauthorized) - { - throw new WebException("Failed to access the metadata document. The OData service requires authentication for accessing it. Please download the metadata, store it into a local file, and set the value of “MetadataDocumentUri” in the .odata.config file to the file path. After that, run custom tool again to generate the OData Client code."); - } - else - { - throw e; - } - } - } - else - { - throw new ArgumentException("Only file, http, https schemes are supported for paths to metadata source locations."); - } - - return metadataStream; - } - - private static IEnumerable GetElementsFromModelTree(IEdmModel mainModel, Func> getElementFromOneModelFunc) - { - List ret = new List(); - if(mainModel is EdmCoreModel || mainModel.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null) - { - return ret; - } - - ret.AddRange(getElementFromOneModelFunc(mainModel)); - foreach (var tmp in mainModel.ReferencedModels) - { - if (tmp is EdmCoreModel || - tmp.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null || - tmp.FindDeclaredTerm(CapabilitiesVocabularyConstants.ChangeTracking) != null || - tmp.FindDeclaredTerm(AlternateKeysVocabularyConstants.AlternateKeys) != null || - tmp.FindDeclaredTerm("Org.OData.Authorization.V1.Authorizations") != null || - tmp.FindDeclaredTerm("Org.OData.Validation.V1.DerivedTypeConstraint") != null || - tmp.FindDeclaredTerm("Org.OData.Community.V1.UrlEscapeFunction") != null) - { - continue; - } - - ret.AddRange(getElementFromOneModelFunc(tmp)); - } - - return ret; - } -} - -/// -/// The template class to generate the OData client code. -/// -public abstract class ODataClientTemplate : TemplateBase -{ - protected const string T4Version = "#VersionNumber#"; - - /// - /// The code generation context. - /// - protected readonly CodeGenerationContext context; - - /// - /// The Dictionary to store identifier mappings when there are duplicate names between properties and Entity/Complex types - /// - protected Dictionary IdentifierMappings = new Dictionary(StringComparer.Ordinal); - - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The code generation context. - public ODataClientTemplate(CodeGenerationContext context) - { - this.context = context; - } - - internal string SingleSuffix - { - get { return "Single"; } - } - - #region Get Language specific keyword names. - internal abstract string GlobalPrefix { get; } - internal abstract string SystemTypeTypeName { get; } - internal abstract string AbstractModifier { get; } - internal abstract string DataServiceActionQueryTypeName { get; } - internal abstract string DataServiceActionQuerySingleOfTStructureTemplate { get; } - internal abstract string DataServiceActionQueryOfTStructureTemplate { get; } - internal abstract string NotifyPropertyChangedModifier { get; } - internal abstract string ClassInheritMarker { get; } - internal abstract string ParameterSeparator { get; } - internal abstract string KeyParameterSeparator { get; } - internal abstract string KeyDictionaryItemSeparator { get; } - internal abstract string SystemNullableStructureTemplate { get; } - internal abstract string ICollectionOfTStructureTemplate { get; } - internal abstract string DataServiceCollectionStructureTemplate { get; } - internal abstract string DataServiceQueryStructureTemplate { get; } - internal abstract string DataServiceQuerySingleStructureTemplate { get; } - internal abstract string ObservableCollectionStructureTemplate { get; } - internal abstract string ObjectModelCollectionStructureTemplate { get; } - internal abstract string DataServiceCollectionConstructorParameters { get; } - internal abstract string NewModifier { get; } - internal abstract string GeoTypeInitializePattern { get; } - internal abstract string Int32TypeName { get; } - internal abstract string StringTypeName { get; } - internal abstract string BinaryTypeName { get; } - internal abstract string DecimalTypeName { get; } - internal abstract string Int16TypeName { get; } - internal abstract string SingleTypeName { get; } - internal abstract string BooleanTypeName { get; } - internal abstract string DoubleTypeName { get; } - internal abstract string GuidTypeName { get; } - internal abstract string ByteTypeName { get; } - internal abstract string Int64TypeName { get; } - internal abstract string SByteTypeName { get; } - internal abstract string DataServiceStreamLinkTypeName { get; } - internal abstract string GeographyTypeName { get; } - internal abstract string GeographyPointTypeName { get; } - internal abstract string GeographyLineStringTypeName { get; } - internal abstract string GeographyPolygonTypeName { get; } - internal abstract string GeographyCollectionTypeName { get; } - internal abstract string GeographyMultiPolygonTypeName { get; } - internal abstract string GeographyMultiLineStringTypeName { get; } - internal abstract string GeographyMultiPointTypeName { get; } - internal abstract string GeometryTypeName { get; } - internal abstract string GeometryPointTypeName { get; } - internal abstract string GeometryLineStringTypeName { get; } - internal abstract string GeometryPolygonTypeName { get; } - internal abstract string GeometryCollectionTypeName { get; } - internal abstract string GeometryMultiPolygonTypeName { get; } - internal abstract string GeometryMultiLineStringTypeName { get; } - internal abstract string GeometryMultiPointTypeName { get; } - internal abstract string DateTypeName { get; } - internal abstract string DateTimeOffsetTypeName { get; } - internal abstract string DurationTypeName { get; } - internal abstract string TimeOfDayTypeName { get; } - internal abstract string XmlConvertClassName { get; } - internal abstract string EnumTypeName { get; } - internal abstract HashSet LanguageKeywords { get; } - internal abstract string FixPattern { get; } - internal abstract string EnumUnderlyingTypeMarker { get; } - internal abstract string ConstantExpressionConstructorWithType { get; } - internal abstract string TypeofFormatter { get; } - internal abstract string UriOperationParameterConstructor { get; } - internal abstract string UriEntityOperationParameterConstructor { get; } - internal abstract string BodyOperationParameterConstructor { get; } - internal abstract string BaseEntityType { get; } - internal abstract string OverloadsModifier { get; } - internal abstract string ODataVersion { get; } - internal abstract string ParameterDeclarationTemplate { get; } - internal abstract string DictionaryItemConstructor { get; } - #endregion Get Language specific keyword names. - - #region Language specific write methods. - internal abstract void WriteFileHeader(); - internal abstract void WriteNamespaceStart(string fullNamespace); - internal abstract void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName); - internal abstract void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName); - internal abstract void WriteKeyAsSegmentUrlConvention(); - internal abstract void WriteInitializeResolveName(); - internal abstract void WriteInitializeResolveType(); - internal abstract void WriteClassEndForEntityContainerConstructor(); - internal abstract void WriteMethodStartForResolveTypeFromName(); - internal abstract void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace); - internal abstract void WriteMethodEndForResolveTypeFromName(); - internal abstract void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace); - internal abstract void WriteResolveType(string fullNamespace, string languageDependentNamespace); - internal abstract void WriteMethodEndForResolveNameFromType(bool modelHasInheritance); - internal abstract void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext = true); - internal abstract void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext = true); - internal abstract void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName); - internal abstract void WriteGeneratedEdmModel(string escapedEdmxString); - internal abstract void WriteClassEndForEntityContainer(); - internal abstract void WriteSummaryCommentForStructuredType(string typeName); - internal abstract void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString); - internal abstract void WriteEntityTypeAttribute(); - internal abstract void WriteEntitySetAttribute(string entitySetName); - internal abstract void WriteEntityHasStreamAttribute(); - internal abstract void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName); - internal abstract void WriteSummaryCommentForStaticCreateMethod(string typeName); - internal abstract void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName); - internal abstract void WriteDeclarationStartForStaticCreateMethod(string typeName,string fixedTypeName ); - internal abstract void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater); - internal abstract void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName); - internal abstract void WriteParameterNullCheckForStaticCreateMethod(string parameterName); - internal abstract void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName); - internal abstract void WriteMethodEndForStaticCreateMethod(string instanceName); - internal abstract void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged); - internal abstract void WriteINotifyPropertyChangedImplementation(); - internal abstract void WriteClassEndForStructuredType(); - internal abstract void WriteNamespaceEnd(); - internal abstract void WriteEnumFlags(); - internal abstract void WriteSummaryCommentForEnumType(string enumName); - internal abstract void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType); - internal abstract void WriteMemberForEnumType(string member, string originalMemberName, bool last); - internal abstract void WriteEnumEnd(); - internal abstract void WritePropertyRootNamespace(string containerName, string fullNamespace); - internal abstract void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues); - internal abstract void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues); - internal abstract void WriteConstructorForSingleType(string singleTypeName, string baseTypeName); - internal abstract void WriteExtensionMethodsStart(); - internal abstract void WriteExtensionMethodsEnd(); - internal abstract void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems); - internal abstract void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName); - internal abstract void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues); - #endregion Language specific write methods. - - internal HashSet ClrReferenceTypes { get { - if (clrReferenceTypes == null) - { - clrReferenceTypes = new HashSet() - { - EdmPrimitiveTypeKind.String, EdmPrimitiveTypeKind.Binary, EdmPrimitiveTypeKind.Geography, EdmPrimitiveTypeKind.Stream, - EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeographyPolygon, - EdmPrimitiveTypeKind.GeographyCollection, EdmPrimitiveTypeKind.GeographyMultiPolygon, EdmPrimitiveTypeKind.GeographyMultiLineString, - EdmPrimitiveTypeKind.GeographyMultiPoint, EdmPrimitiveTypeKind.Geometry, EdmPrimitiveTypeKind.GeometryPoint, - EdmPrimitiveTypeKind.GeometryLineString, EdmPrimitiveTypeKind.GeometryPolygon, EdmPrimitiveTypeKind.GeometryCollection, - EdmPrimitiveTypeKind.GeometryMultiPolygon, EdmPrimitiveTypeKind.GeometryMultiLineString, EdmPrimitiveTypeKind.GeometryMultiPoint - }; - } - return clrReferenceTypes; - } } - private HashSet clrReferenceTypes; - - /// - /// Generates code for the OData client. - /// - /// The generated code for the OData client. - public override string TransformText() - { - this.WriteFileHeader(); - this.WriteNamespaces(); - return this.GenerationEnvironment.ToString(); - } - - internal void WriteNamespaces() - { - foreach(string fullNamespace in context.NamespacesInModel) - { - this.WriteNamespace(fullNamespace); - } - } - - internal void WriteNamespace(string fullNamespace) - { - this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false)); - - IEdmSchemaElement[] schemaElements = this.context.GetSchemaElements(fullNamespace).ToArray(); - if (schemaElements.OfType().Any()) { - IEdmEntityContainer container = schemaElements.OfType().Single(); - this.WriteEntityContainer(container, fullNamespace); - } - - Dictionary> boundOperationsMap = new Dictionary>(); - foreach (IEdmOperation operation in schemaElements.OfType()) - { - if (operation.IsBound) - { - IEdmType edmType = operation.Parameters.First().Type.Definition; - IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType; - if (edmStructuredType != null) - { - List operationList; - if (!boundOperationsMap.TryGetValue(edmStructuredType, out operationList)) - { - operationList = new List(); - } - - operationList.Add(operation); - boundOperationsMap[edmStructuredType] = operationList; - } - } - } - - Dictionary> structuredBaseTypeMap = new Dictionary>(); - foreach(IEdmSchemaType type in schemaElements.OfType()) - { - IEdmEnumType enumType = type as IEdmEnumType; - if (enumType != null) - { - this.WriteEnumType(enumType); - } - else - { - IEdmComplexType complexType = type as IEdmComplexType; - if (complexType != null) - { - this.WriteComplexType(complexType, boundOperationsMap); - } - else - { - IEdmEntityType entityType = type as IEdmEntityType; - this.WriteEntityType(entityType, boundOperationsMap); - } - - IEdmStructuredType structuredType = type as IEdmStructuredType; - if (structuredType.BaseType != null) - { - List derivedTypes; - if (!structuredBaseTypeMap.TryGetValue(structuredType.BaseType, out derivedTypes)) - { - structuredBaseTypeMap[structuredType.BaseType] = new List(); - } - - structuredBaseTypeMap[structuredType.BaseType].Add(structuredType); - } - } - } - - if (schemaElements.OfType().Any() || - schemaElements.OfType().Any(o => o.IsBound)) - { - this.WriteExtensionMethodsStart(); - foreach (IEdmEntityType type in schemaElements.OfType()) - { - string entityTypeName = type.Name; - entityTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; - string entityTypeFullName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName), this); - string returnTypeName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName + this.SingleSuffix), this); - - var keyProperties = type.Key(); - if(keyProperties != null && keyProperties.Any()) - { - List keyParameters = new List(); - List keyDictionaryItems = new List(); - List keyNames = new List(); - foreach (IEdmProperty key in keyProperties) - { - string typeName = Utils.GetClrTypeName(key.Type, this.context.UseDataServiceCollection, this, this.context); - string keyName = Utils.CamelCase(key.Name); - keyNames.Add(keyName); - keyParameters.Add(string.Format(this.ParameterDeclarationTemplate, typeName, this.GetFixedName(keyName))); - keyDictionaryItems.Add(string.Format(this.DictionaryItemConstructor, "\"" + key.Name + "\"", this.GetFixedName(keyName))); - } - - string keyParametersString = string.Join(this.KeyParameterSeparator, keyParameters); - string keyDictionaryItemsString = string.Join(this.KeyDictionaryItemSeparator, keyDictionaryItems); - this.WriteByKeyMethods(entityTypeFullName, returnTypeName, keyNames, keyParametersString, keyDictionaryItemsString); - } - - IEdmEntityType current = (IEdmEntityType)type.BaseType; - while (current != null) - { - string baseTypeName = current.Name; - baseTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(baseTypeName) : baseTypeName; - baseTypeName = context.GetPrefixedFullName(current, GetFixedName(baseTypeName), this); - this.WriteCastToMethods(baseTypeName, entityTypeName, entityTypeFullName, returnTypeName); - current = (IEdmEntityType)current.BaseType; - } - } - - HashSet boundOperations = new HashSet(StringComparer.Ordinal); - foreach (IEdmFunction function in schemaElements.OfType()) - { - if (function.IsBound) - { - IEdmTypeReference edmTypeReference = function.Parameters.First().Type; - string functionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(function.Name) : function.Name; - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); - string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); - string fixedFunctionName = GetFixedName(functionName); - string func = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); - - if (!boundOperations.Contains(func)) - { - boundOperations.Add(func); - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - - IEdmStructuredType structuredType; - if (edmTypeReference.IsCollection()) - { - IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; - structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; - } - else - { - structuredType = (IEdmStructuredType)edmTypeReference.Definition; - } - - List derivedTypes; - if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) - { - foreach (IEdmStructuredType type in derivedTypes) - { - IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); - List currentParameters = function.Parameters.Select(p => p.Type).ToList(); - currentParameters[0] = derivedTypeReference; - - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); - string currentFunc = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(currentFunc)) - { - boundOperations.Add(currentFunc); - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - } - } - } - } - - foreach (IEdmAction action in schemaElements.OfType()) - { - if (action.IsBound) - { - IEdmTypeReference edmTypeReference = action.Parameters.First().Type; - string actionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(action.Name) : action.Name; - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); - string returnTypeName; - if (action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); - if (action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string fixedActionName = GetFixedName(actionName); - string ac = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(ac)) - { - boundOperations.Add(ac); - this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); - } - - IEdmStructuredType structuredType; - if (edmTypeReference.IsCollection()) - { - IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; - structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; - } - else - { - structuredType = (IEdmStructuredType)edmTypeReference.Definition; - } - - List derivedTypes; - if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) - { - foreach (IEdmStructuredType type in derivedTypes) - { - IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); - List currentParameters = action.Parameters.Select(p => p.Type).ToList(); - currentParameters[0] = derivedTypeReference; - - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); - string currentAc = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(currentAc)) - { - boundOperations.Add(currentAc); - this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); - } - } - } - } - } - - this.WriteExtensionMethodsEnd(); - } - - this.WriteNamespaceEnd(); - } - - internal bool HasBoundOperations(IEnumerable operations) - { - foreach (IEdmOperation opeartion in operations) - { - if (opeartion.IsBound) - { - return true; - } - } - - return false; - } - - internal void WriteEntityContainer(IEdmEntityContainer container, string fullNamespace) - { - string camelCaseContainerName = container.Name; - if (this.context.EnableNamingAlias) - { - camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); - } - - this.WriteClassStartForEntityContainer(container.Name, camelCaseContainerName, GetFixedName(camelCaseContainerName)); - this.WriteEntityContainerConstructor(container); - - if (this.context.NeedResolveNameFromType) - { - this.WritePropertyRootNamespace(GetFixedName(camelCaseContainerName), this.context.GetPrefixedNamespace(fullNamespace, this, false, false)); - } - - this.WriteResolveTypeFromName(); - this.WriteResolveNameFromType(camelCaseContainerName, fullNamespace); - - foreach (IEdmEntitySet entitySet in container.EntitySets()) - { - IEdmEntityType entitySetElementType = entitySet.EntityType(); - string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); - - string camelCaseEntitySetName = entitySet.Name; - if (this.context.EnableNamingAlias) - { - camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); - } - - this.WriteContextEntitySetProperty(camelCaseEntitySetName, GetFixedName(camelCaseEntitySetName), entitySet.Name, GetFixedName(entitySetElementTypeName)); - List edmNavigationSourceList = null; - if (!this.context.ElementTypeToNavigationSourceMap.TryGetValue(entitySet.EntityType(), out edmNavigationSourceList)) - { - edmNavigationSourceList = new List(); - this.context.ElementTypeToNavigationSourceMap.Add(entitySet.EntityType(), edmNavigationSourceList); - } - - edmNavigationSourceList.Add(entitySet); - } - - foreach (IEdmEntitySet entitySet in container.EntitySets()) - { - IEdmEntityType entitySetElementType = entitySet.EntityType(); - - string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); - - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(/*IsLanguageCaseSensitive*/true); - string parameterName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(entitySetElementType.Name)); - - string camelCaseEntitySetName = entitySet.Name; - if (this.context.EnableNamingAlias) - { - camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); - } - - this.WriteContextAddToEntitySetMethod(camelCaseEntitySetName, entitySet.Name, GetFixedName(entitySetElementTypeName), parameterName); - } - - foreach (IEdmSingleton singleton in container.Singletons()) - { - IEdmEntityType singletonElementType = singleton.EntityType(); - string singletonElementTypeName = GetElementTypeName(singletonElementType, container); - string camelCaseSingletonName = singleton.Name; - if (this.context.EnableNamingAlias) - { - camelCaseSingletonName = Customization.CustomizeNaming(camelCaseSingletonName); - } - - this.WriteContextSingletonProperty(camelCaseSingletonName, GetFixedName(camelCaseSingletonName), singleton.Name, singletonElementTypeName + "Single"); - - List edmNavigationSourceList = null; - if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(singleton.EntityType(), out edmNavigationSourceList)) - { - edmNavigationSourceList.Add(singleton); - } - } - - this.WriteGeneratedEdmModel(Utils.SerializeToString(this.context.Edmx).Replace("\"", "\"\"")); - - bool hasOperationImport = container.OperationImports().OfType().Any(); - foreach (IEdmFunctionImport functionImport in container.OperationImports().OfType()) - { - string parameterString, parameterTypes, parameterExpressionString, parameterValues; - bool useEntityReference; - this.GetParameterStrings(false, false, functionImport.Function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = GetSourceOrReturnTypeName(functionImport.Function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(functionImport.Function.ReturnType, true); - string fixedContainerName = this.GetFixedName(functionImport.Container.Name); - bool isCollectionResult = functionImport.Function.ReturnType.IsCollection(); - string functionImportName = functionImport.Name; - if (this.context.EnableNamingAlias) - { - functionImportName = Customization.CustomizeNaming(functionImportName); - fixedContainerName = Customization.CustomizeNaming(fixedContainerName); - } - - if (functionImport.Function.ReturnType.IsCollection()) - { - this.WriteFunctionImportReturnCollectionResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, parameterString, parameterValues, functionImport.Function.IsComposable, useEntityReference); - } - else - { - this.WriteFunctionImportReturnSingleResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, parameterValues, functionImport.Function.IsComposable, functionImport.Function.ReturnType.IsEntity(), useEntityReference); - } - } - - foreach (IEdmActionImport actionImport in container.OperationImports().OfType()) - { - string parameterString, parameterTypes, parameterExpressionString, parameterValues; - bool useEntityReference; - this.GetParameterStrings(false, true, actionImport.Action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = null; - string fixedContainerName = this.GetFixedName(actionImport.Container.Name); - - if (actionImport.Action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(actionImport.Action.ReturnType); - if (actionImport.Action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string actionImportName = actionImport.Name; - if (this.context.EnableNamingAlias) - { - actionImportName = Customization.CustomizeNaming(actionImportName); - fixedContainerName = Customization.CustomizeNaming(fixedContainerName); - } - - this.WriteActionImport(this.GetFixedName(actionImportName), actionImport.Name, returnTypeName, parameterString, parameterValues); - } - - this.WriteClassEndForEntityContainer(); - } - - internal void WriteEntityContainerConstructor(IEdmEntityContainer container) - { - string camelCaseContainerName = container.Name; - if (this.context.EnableNamingAlias) - { - camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); - } - - this.WriteMethodStartForEntityContainerConstructor(camelCaseContainerName, GetFixedName(camelCaseContainerName)); - - if (this.context.UseKeyAsSegmentUrlConvention(container)) - { - this.WriteKeyAsSegmentUrlConvention(); - } - - if (this.context.NeedResolveNameFromType) - { - this.WriteInitializeResolveName(); - } - - if (this.context.NeedResolveTypeFromName) - { - this.WriteInitializeResolveType(); - } - - this.WriteClassEndForEntityContainerConstructor(); - } - - internal void WriteResolveTypeFromName() - { - if (!this.context.NeedResolveTypeFromName) - { - return; - } - - this.WriteMethodStartForResolveTypeFromName(); - - // NOTE: since multiple namespaces can have the same prefix and match the namespace - // prefix condition, it's important that the prefix check is done is prefix-length - // order, starting with the longest prefix. - IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key); - - string typeName = this.SystemTypeTypeName + " "; - foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) - { - this.WriteResolveNamespace(typeName, namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); - typeName = string.Empty; - } - - this.WriteMethodEndForResolveTypeFromName(); - } - - internal void WriteResolveNameFromType(string containerName, string fullNamespace) - { - if (!this.context.NeedResolveNameFromType) - { - return; - } - - this.WriteMethodStartForResolveNameFromType(GetFixedName(containerName), fullNamespace); - - // NOTE: in this case order also matters, but the length of the CLR - // namespace is what needs to be considered. - IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key); - - foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) - { - this.WriteResolveType(namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); - } - - this.WriteMethodEndForResolveNameFromType(this.context.ModelHasInheritance); - } - - internal void WritePropertiesForSingleType(IEnumerable properties) - { - foreach (IEdmProperty property in properties.Where(i => i.PropertyKind == EdmPropertyKind.Navigation)) - { - string propertyType; - string propertyName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name; - if (property.Type is Microsoft.OData.Edm.EdmCollectionTypeReference) - { - propertyType = GetSourceOrReturnTypeName(property.Type); - WriteContextEntitySetProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); - } - else - { - propertyType = Utils.GetClrTypeName(property.Type, true, this, this.context, true, isEntitySingleType : true); - WriteContextSingletonProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); - } - } - } - - internal void WriteEntityType(IEdmEntityType entityType, Dictionary> boundOperationsMap) - { - string entityTypeName = ((IEdmSchemaElement)entityType).Name; - entityTypeName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; - this.WriteSummaryCommentForStructuredType(entityTypeName + this.SingleSuffix); - this.WriteStructurdTypeDeclaration(entityType, - this.ClassInheritMarker + string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName)), - this.SingleSuffix); - string singleTypeName = (this.context.EnableNamingAlias ? - Customization.CustomizeNaming(((IEdmSchemaElement)entityType).Name) : ((IEdmSchemaElement)entityType).Name) + this.SingleSuffix; - this.WriteConstructorForSingleType(GetFixedName(singleTypeName), string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName))); - IEdmEntityType current = entityType; - while (current != null) - { - this.WritePropertiesForSingleType(current.DeclaredProperties); - current = (IEdmEntityType)current.BaseType; - } - - this.WriteClassEndForStructuredType(); - - this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityType.Name) : entityType.Name); - - if (entityType.Key().Any()) - { - IEnumerable keyProperties = entityType.Key().Select(k => k.Name); - this.WriteKeyPropertiesCommentAndAttribute( - this.context.EnableNamingAlias ? keyProperties.Select(k => Customization.CustomizeNaming(k)) : keyProperties, - string.Join("\", \"", keyProperties)); - } - else - { - this.WriteEntityTypeAttribute(); - } - - if (this.context.UseDataServiceCollection) - { - List navigationSourceList; - if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(entityType, out navigationSourceList)) - { - if(navigationSourceList.Count == 1) - { - this.WriteEntitySetAttribute(navigationSourceList[0].Name); - } - } - } - - if (entityType.HasStream) - { - this.WriteEntityHasStreamAttribute(); - } - - this.WriteStructurdTypeDeclaration(entityType, this.BaseEntityType); - this.SetPropertyIdentifierMappingsIfNameConflicts(entityType.Name, entityType); - this.WriteTypeStaticCreateMethod(entityType.Name, entityType); - this.WritePropertiesForStructuredType(entityType.DeclaredProperties); - - if (entityType.BaseType == null && this.context.UseDataServiceCollection) - { - this.WriteINotifyPropertyChangedImplementation(); - } - - this.WriteBoundOperations(entityType, boundOperationsMap); - - this.WriteClassEndForStructuredType(); - } - - internal void WriteComplexType(IEdmComplexType complexType, Dictionary> boundOperationsMap) - { - this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(complexType.Name) : complexType.Name); - this.WriteStructurdTypeDeclaration(complexType, string.Empty); - this.SetPropertyIdentifierMappingsIfNameConflicts(complexType.Name, complexType); - this.WriteTypeStaticCreateMethod(complexType.Name, complexType); - this.WritePropertiesForStructuredType(complexType.DeclaredProperties); - - if (complexType.BaseType == null && this.context.UseDataServiceCollection) - { - this.WriteINotifyPropertyChangedImplementation(); - } - - this.WriteClassEndForStructuredType(); - } - - internal void WriteBoundOperations(IEdmStructuredType structuredType, Dictionary> boundOperationsMap) - { - List operations; - if (boundOperationsMap.TryGetValue(structuredType, out operations)) - { - foreach (IEdmFunction function in operations.OfType()) - { - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, function, boundOperationsMap); - this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); - string functionName = function.Name; - if (this.context.EnableNamingAlias) - { - functionName = Customization.CustomizeNaming(functionName); - } - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionInEntityTypeReturnCollectionResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionInEntityTypeReturnSingleResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - - foreach (IEdmAction action in operations.OfType()) - { - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, action, boundOperationsMap); - this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName; - if (action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); - if (action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string actionName = action.Name; - if (this.context.EnableNamingAlias) - { - actionName = Customization.CustomizeNaming(actionName); - } - - this.WriteBoundActionInEntityType(hideBaseMethod, GetFixedName(actionName), action.Name, returnTypeName, parameterString, action.Namespace, parameterValues); - } - } - } - - internal bool CheckMethodsInBaseClass(IEdmStructuredType structuredType, IEdmOperation operation, Dictionary> boundOperationsMap) - { - if (structuredType != null) - { - List operations; - if (boundOperationsMap.TryGetValue(structuredType, out operations)) - { - foreach (IEdmOperation op in operations) - { - if (this.context.TargetLanguage == LanguageOption.VB) - { - if (operation.Name == op.Name) - { - return true; - } - } - - List targetParameter = operation.Parameters.ToList(); - List checkParameter = op.Parameters.ToList(); - if (operation.Name == op.Name && targetParameter.Count == checkParameter.Count) - { - bool areSame = true; - for (int i = 1; i < targetParameter.Count; ++i) - { - var targetParameterType = targetParameter[i].Type; - var checkParameterType = checkParameter[i].Type; - if (!targetParameterType.Definition.Equals(checkParameterType.Definition) - || targetParameterType.IsNullable != checkParameterType.IsNullable) - { - areSame = false; - break; - } - } - - if (areSame) - { - return true; - } - } - } - } - - return CheckMethodsInBaseClass(structuredType.BaseType, operation, boundOperationsMap); - } - - return false; - } - - internal void WriteEnumType(IEdmEnumType enumType) - { - this.WriteSummaryCommentForEnumType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(enumType.Name) : enumType.Name); - if (enumType.IsFlags) - { - this.WriteEnumFlags(); - } - - string underlyingType = string.Empty; - if (enumType.UnderlyingType != null && enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32) - { - underlyingType = Utils.GetClrTypeName(enumType.UnderlyingType, this); - underlyingType = this.EnumUnderlyingTypeMarker + underlyingType; - } - - this.WriteEnumDeclaration(this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(enumType.Name)) : GetFixedName(enumType.Name), enumType.Name, underlyingType); - this.WriteMembersForEnumType(enumType.Members); - this.WriteEnumEnd(); - } - - internal void WriteStructurdTypeDeclaration(IEdmStructuredType structuredType, string baseEntityType, string typeNameSuffix = null) - { - string abstractModifier = structuredType.IsAbstract && typeNameSuffix == null ? this.AbstractModifier : string.Empty; - string baseTypeName = baseEntityType; - - if (typeNameSuffix == null) - { - if (structuredType.BaseType == null) - { - if (this.context.UseDataServiceCollection) - { - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - baseTypeName += string.IsNullOrEmpty(baseTypeName) ? this.ClassInheritMarker : ", "; - } - - baseTypeName += this.NotifyPropertyChangedModifier; - } - } - else - { - IEdmSchemaElement baseType = (IEdmSchemaElement)structuredType.BaseType; - string baseTypeFixedName = this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(baseType.Name)) : GetFixedName(baseType.Name); - baseTypeName = ((IEdmSchemaElement)structuredType).Namespace == baseType.Namespace ? baseTypeFixedName : this.context.GetPrefixedFullName(baseType, baseTypeFixedName, this); - baseTypeName = this.ClassInheritMarker + baseTypeName; - } - } - - string structuredTypeName = this.context.EnableNamingAlias ? - Customization.CustomizeNaming(((IEdmSchemaElement)structuredType).Name) : ((IEdmSchemaElement)structuredType).Name; - this.WriteClassStartForStructuredType(abstractModifier, GetFixedName(structuredTypeName + typeNameSuffix), ((IEdmSchemaElement)structuredType).Name + typeNameSuffix, baseTypeName); - } - - internal string GetSourceOrReturnTypeName(IEdmTypeReference typeReference, bool isEntitySingleType = false) - { - IEdmCollectionType edmCollectionType = typeReference.Definition as IEdmCollectionType; - bool addNullableTemplate = true; - if (edmCollectionType != null) - { - typeReference = edmCollectionType.ElementType; - addNullableTemplate = false; - } - - return Utils.GetClrTypeName(typeReference, this.context.UseDataServiceCollection, this, this.context, addNullableTemplate, isEntitySingleType:isEntitySingleType); - } - - internal void GetParameterStrings(bool isBound, bool isAction, IEdmOperationParameter[] parameters, out string parameterString, out string parameterTypes, out string parameterExpressionString, out string parameterValues, out bool useEntityReference) - { - parameterString = string.Empty; - parameterExpressionString = string.Empty; - parameterTypes = string.Empty; - parameterValues = string.Empty; - useEntityReference = false; - - int n = parameters.Count(); - for (int i = isBound ? 1 : 0; i < n; ++i) - { - IEdmOperationParameter param = parameters[i]; - if (i == (isBound ? 1 : 0)) - { - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - parameterExpressionString += "\r\n "; - } - else - { - parameterExpressionString += "\r\n "; - } - } - - string typeName = Utils.GetClrTypeName(param.Type, this.context.UseDataServiceCollection, this, this.context, true, true, true); - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - parameterString += typeName; - parameterString += (" " + GetFixedName(param.Name)); - } - else if (this.context.TargetLanguage == LanguageOption.VB) - { - parameterString += GetFixedName(param.Name); - parameterString += (this.EnumUnderlyingTypeMarker + typeName); - } - - parameterString += i == n - 1 ? string.Empty : ", "; - parameterTypes += string.Format(this.TypeofFormatter, typeName) + ", "; - parameterExpressionString += this.GetParameterExpressionString(param, typeName) + ", "; - - if (i != (isBound ? 1 : 0)) - { - parameterValues += ",\r\n "; - } - - if (isAction) - { - parameterValues += string.Format(this.BodyOperationParameterConstructor, param.Name, GetFixedName(param.Name)); - } - else if (param.Type.IsEntity() || (param.Type.IsCollection() && param.Type.AsCollection().ElementType().IsEntity())) - { - useEntityReference = true; - parameterValues += string.Format(this.UriEntityOperationParameterConstructor, param.Name, GetFixedName(param.Name),"useEntityReference"); - } - else - { - parameterValues += string.Format(this.UriOperationParameterConstructor, param.Name, GetFixedName(param.Name)); - } - } - } - - internal string GetParameterExpressionString(IEdmOperationParameter param, string typeName) - { - string clrTypeName; - IEdmType edmType = param.Type.Definition; - IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; - if (edmPrimitiveType != null) - { - clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, this); - if (param.Type.IsNullable && !this.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind)) - { - clrTypeName += "?"; - } - - return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), clrTypeName); - } - - return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), typeName); - } - - // This is to solve duplicate names between property and type - internal void SetPropertyIdentifierMappingsIfNameConflicts(string typeName, IEdmStructuredType structuredType) - { - if (this.context.EnableNamingAlias) - { - typeName = Customization.CustomizeNaming(typeName); - } - - // PropertyName in VB is case-insensitive. - bool isLanguageCaseSensitive = this.context.TargetLanguage == LanguageOption.CSharp; - - // In VB, it is allowed that a type has a property whose name is same with the type's name - bool allowPropertyNameSameWithTypeName = this.context.TargetLanguage == LanguageOption.VB; - - Func customizePropertyName = (name) => { return this.context.EnableNamingAlias ? Customization.CustomizeNaming(name) : name; }; - - var propertyGroups = structuredType.Properties() - .GroupBy(p => isLanguageCaseSensitive ? customizePropertyName(p.Name) : customizePropertyName(p.Name).ToUpperInvariant()); - - // If the group contains more than one property, or the property in the group has the same name with the type (only for C#), we need to rename the property - var propertyToBeRenamedGroups = propertyGroups.Where(g => g.Count() > 1 || !allowPropertyNameSameWithTypeName && g.Key == typeName); - - var knownIdentifiers = propertyGroups.Select(g => customizePropertyName(g.First().Name)).ToList(); - if(!allowPropertyNameSameWithTypeName && !knownIdentifiers.Contains(typeName)) - { - knownIdentifiers.Add(typeName); - } - UniqueIdentifierService uniqueIdentifierService = - new UniqueIdentifierService(knownIdentifiers, isLanguageCaseSensitive); - - IdentifierMappings.Clear(); - foreach (IGrouping g in propertyToBeRenamedGroups) - { - bool hasPropertyNameSameWithCustomizedPropertyName = false; - int itemCount = g.Count(); - for (int i = 0; i < itemCount; i++) - { - var property = g.ElementAt(i); - var customizedPropertyName = customizePropertyName(property.Name); - - if(this.context.EnableNamingAlias && customizedPropertyName == property.Name) - { - hasPropertyNameSameWithCustomizedPropertyName = true; - } - - if(isLanguageCaseSensitive) - { - // If a property name is same as its customized property name, then we don't rename it. - // Or we don't rename the last property in the group - if(customizedPropertyName != typeName - && (customizedPropertyName == property.Name - || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1))) - { - continue; - } - } - else - { - // When EnableNamingAlias = true, If a property name is same as its customized property name, then we don't rename it. - // Or we don't rename the last property in the group. - if((this.context.EnableNamingAlias && customizedPropertyName == property.Name) - || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1)) - { - continue; - } - } - var renamedPropertyName = uniqueIdentifierService.GetUniqueIdentifier(customizedPropertyName); - IdentifierMappings.Add(property.Name, renamedPropertyName); - } - } - } - - internal void WriteTypeStaticCreateMethod(string typeName, IEdmStructuredType structuredType) - { - Debug.Assert(structuredType != null, "structuredType != null"); - if (structuredType.IsAbstract) - { - return; - } - - Func hasDefault = p => p.PropertyKind == EdmPropertyKind.Structural && ((IEdmStructuralProperty)p).DefaultValueString != null; - - if (this.context.EnableNamingAlias) - { - typeName = Customization.CustomizeNaming(typeName); - } - - IEnumerable parameters = structuredType.Properties() - .Where(p => !p.Type.IsNullable && !p.Type.IsCollection() && !hasDefault(p)); - if (!parameters.Any()) - { - return; - } - - this.WriteSummaryCommentForStaticCreateMethod(typeName); - - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( /*IsLanguageCaseSensitive*/true); - string instanceName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(typeName)); - KeyValuePair[] propertyToParameterNamePairs = parameters - .Select(p => - new KeyValuePair(p, - uniqueIdentifierService.GetUniqueParameterName( - IdentifierMappings.ContainsKey(p.Name) ? IdentifierMappings[p.Name] : p.Name))) - .ToArray(); - - foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) - { - string propertyName = propertyToParameterNamePair.Key.Name; - propertyName = IdentifierMappings.ContainsKey(propertyName) ? - IdentifierMappings[propertyName] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(propertyName) : propertyName); - this.WriteParameterCommentForStaticCreateMethod(propertyToParameterNamePair.Value, propertyName); - } - - propertyToParameterNamePairs = propertyToParameterNamePairs - .Select(p => p = new KeyValuePair(p.Key, GetFixedName(p.Value))) - .ToArray(); - - this.WriteDeclarationStartForStaticCreateMethod(typeName, GetFixedName(typeName)); - this.WriteStaticCreateMethodParameters(propertyToParameterNamePairs); - this.WriteDeclarationEndForStaticCreateMethod(GetFixedName(typeName), instanceName); - - foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) - { - IEdmProperty property = propertyToParameterNamePair.Key; - string parameterName = propertyToParameterNamePair.Value; - - Debug.Assert(!property.Type.IsCollection(), "!property.Type.IsCollection()"); - Debug.Assert(!property.Type.IsNullable, "!property.Type.IsNullable"); - - // The static create method only sets non-nullable properties. We should add the null check if the type of the property is not a clr ValueType. - // For now we add the null check if the property type is non-primitive. We should add the null check for non-ValueType primitives in the future. - if (!property.Type.IsPrimitive() && !property.Type.IsEnum()) - { - this.WriteParameterNullCheckForStaticCreateMethod(parameterName); - } - - var uniqIdentifier = IdentifierMappings.ContainsKey(property.Name) ? - IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); - this.WritePropertyValueAssignmentForStaticCreateMethod(instanceName, - GetFixedName(uniqIdentifier), - parameterName); - } - - this.WriteMethodEndForStaticCreateMethod(instanceName); - } - - internal void WriteStaticCreateMethodParameters(KeyValuePair[] propertyToParameterPairs) - { - if (propertyToParameterPairs.Length == 0) - { - return; - } - - // If the number of parameters are greater than 5, we put them in separate lines. - string parameterSeparator = propertyToParameterPairs.Length > 5 ? this.ParameterSeparator : ", "; - for (int idx = 0; idx < propertyToParameterPairs.Length; idx++) - { - KeyValuePair propertyToParameterPair = propertyToParameterPairs[idx]; - - string parameterType = Utils.GetClrTypeName(propertyToParameterPair.Key.Type, this.context.UseDataServiceCollection, this, this.context); - string parameterName = propertyToParameterPair.Value; - if (idx == propertyToParameterPairs.Length - 1) - { - // No separator after the last parameter. - parameterSeparator = string.Empty; - } - - this.WriteParameterForStaticCreateMethod(parameterType, GetFixedName(parameterName), parameterSeparator); - } - } - - internal void WritePropertiesForStructuredType(IEnumerable properties) - { - bool useDataServiceCollection = this.context.UseDataServiceCollection; - - var propertyInfos = properties.Select(property => - { - string propertyName = IdentifierMappings.ContainsKey(property.Name) ? - IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); - - return new - { - PropertyType = Utils.GetClrTypeName(property.Type, useDataServiceCollection, this, this.context), - PropertyVanillaName = property.Name, - PropertyName = propertyName, - FixedPropertyName = GetFixedName(propertyName), - PrivatePropertyName = "_" + propertyName, - PropertyInitializationValue = Utils.GetPropertyInitializationValue(property, useDataServiceCollection, this, this.context) - }; - }).ToList(); - - // Private name should not confict with field name - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(propertyInfos.Select(_ => _.FixedPropertyName), - this.context.TargetLanguage == LanguageOption.CSharp); - - foreach (var propertyInfo in propertyInfos) - { - string privatePropertyName = uniqueIdentifierService.GetUniqueIdentifier("_" + propertyInfo.PropertyName); - - this.WritePropertyForStructuredType( - propertyInfo.PropertyType, - propertyInfo.PropertyVanillaName, - propertyInfo.PropertyName, - propertyInfo.FixedPropertyName, - privatePropertyName, - propertyInfo.PropertyInitializationValue, - useDataServiceCollection); - } - } - - internal void WriteMembersForEnumType(IEnumerable members) - { - int n = members.Count(); - for (int idx = 0; idx < n; ++idx) - { - IEdmEnumMember member = members.ElementAt(idx); - string value = string.Empty; - if (member.Value != null) - { - IEdmEnumMemberValue integerValue = member.Value as IEdmEnumMemberValue; - if (integerValue != null) - { - value = " = " + integerValue.Value.ToString(CultureInfo.InvariantCulture); - } - } - - string memberName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(member.Name) : member.Name; - this.WriteMemberForEnumType(GetFixedName(memberName) + value, member.Name, idx == n - 1); - } - } - - internal string GetFixedName(string originalName) - { - string fixedName = originalName; - - if (this.LanguageKeywords.Contains(fixedName)) - { - fixedName = string.Format(this.FixPattern, fixedName); - } - - return fixedName; - } - - internal string GetElementTypeName(IEdmEntityType elementType, IEdmEntityContainer container) - { - string elementTypeName = elementType.Name; - - if (this.context.EnableNamingAlias) - { - elementTypeName = Customization.CustomizeNaming(elementTypeName); - } - - if (elementType.Namespace != container.Namespace) - { - elementTypeName = this.context.GetPrefixedFullName(elementType, GetFixedName(elementTypeName), this); - } - - return elementTypeName; - } -} - -/// -/// Base class for text transformation -/// -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] -public abstract class TemplateBase -{ - #region Fields - private global::System.Text.StringBuilder generationEnvironmentField; - private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; - private global::System.Collections.Generic.List indentLengthsField; - private string currentIndentField = ""; - private bool endsWithNewline; - private global::System.Collections.Generic.IDictionary sessionField; - #endregion - #region Properties - /// - /// The string builder that generation-time code is using to assemble generated output - /// - protected System.Text.StringBuilder GenerationEnvironment - { - get - { - if ((this.generationEnvironmentField == null)) - { - this.generationEnvironmentField = new global::System.Text.StringBuilder(); - } - return this.generationEnvironmentField; - } - set - { - this.generationEnvironmentField = value; - } - } - /// - /// The error collection for the generation process - /// - public System.CodeDom.Compiler.CompilerErrorCollection Errors - { - get - { - if ((this.errorsField == null)) - { - this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); - } - return this.errorsField; - } - } - /// - /// A list of the lengths of each indent that was added with PushIndent - /// - private System.Collections.Generic.List indentLengths - { - get - { - if ((this.indentLengthsField == null)) - { - this.indentLengthsField = new global::System.Collections.Generic.List(); - } - return this.indentLengthsField; - } - } - /// - /// Gets the current indent we use when adding lines to the output - /// - public string CurrentIndent - { - get - { - return this.currentIndentField; - } - } - /// - /// Current transformation session - /// - public virtual global::System.Collections.Generic.IDictionary Session - { - get - { - return this.sessionField; - } - set - { - this.sessionField = value; - } - } - #endregion - - /// - /// Create the template output - /// - public abstract string TransformText(); - - #region Transform-time helpers - /// - /// Write text directly into the generated output - /// - public void Write(string textToAppend) - { - if (string.IsNullOrEmpty(textToAppend)) - { - return; - } - // If we're starting off, or if the previous text ended with a newline, - // we have to append the current indent first. - if (((this.GenerationEnvironment.Length == 0) - || this.endsWithNewline)) - { - this.GenerationEnvironment.Append(this.currentIndentField); - this.endsWithNewline = false; - } - // Check if the current text ends with a newline - if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) - { - this.endsWithNewline = true; - } - // This is an optimization. If the current indent is "", then we don't have to do any - // of the more complex stuff further down. - if ((this.currentIndentField.Length == 0)) - { - this.GenerationEnvironment.Append(textToAppend); - return; - } - // Everywhere there is a newline in the text, add an indent after it - textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); - // If the text ends with a newline, then we should strip off the indent added at the very end - // because the appropriate indent will be added when the next time Write() is called - if (this.endsWithNewline) - { - this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); - } - else - { - this.GenerationEnvironment.Append(textToAppend); - } - } - /// - /// Write text directly into the generated output - /// - public void WriteLine(string textToAppend) - { - this.Write(textToAppend); - this.GenerationEnvironment.AppendLine(); - this.endsWithNewline = true; - } - /// - /// Write formatted text directly into the generated output - /// - public void Write(string format, params object[] args) - { - this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); - } - /// - /// Write formatted text directly into the generated output - /// - public void WriteLine(string format, params object[] args) - { - this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); - } - /// - /// Raise an error - /// - public void Error(string message) - { - System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); - error.ErrorText = message; - this.Errors.Add(error); - } - /// - /// Raise a warning - /// - public void Warning(string message) - { - System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); - error.ErrorText = message; - error.IsWarning = true; - this.Errors.Add(error); - } - /// - /// Increase the indent - /// - public void PushIndent(string indent) - { - if ((indent == null)) - { - throw new global::System.ArgumentNullException("indent"); - } - this.currentIndentField = (this.currentIndentField + indent); - this.indentLengths.Add(indent.Length); - } - /// - /// Remove the last indent that was added with PushIndent - /// - public string PopIndent() - { - string returnValue = ""; - if ((this.indentLengths.Count > 0)) - { - int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; - this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); - if ((indentLength > 0)) - { - returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); - this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); - } - } - return returnValue; - } - /// - /// Remove any indentation - /// - public void ClearIndent() - { - this.indentLengths.Clear(); - this.currentIndentField = ""; - } - #endregion - #region ToString Helpers - /// - /// Utility class to produce culture-oriented representation of an object as a string. - /// - public class ToStringInstanceHelper - { - private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; - /// - /// Gets or sets format provider to be used by ToStringWithCulture method. - /// - public System.IFormatProvider FormatProvider - { - get - { - return this.formatProviderField ; - } - set - { - if ((value != null)) - { - this.formatProviderField = value; - } - } - } - /// - /// This is called from the compile/run appdomain to convert objects within an expression block to a string - /// - public string ToStringWithCulture(object objectToConvert) - { - if ((objectToConvert == null)) - { - throw new global::System.ArgumentNullException("objectToConvert"); - } - System.Type t = objectToConvert.GetType(); - System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { - typeof(System.IFormatProvider)}); - if ((method == null)) - { - return objectToConvert.ToString(); - } - else - { - return ((string)(method.Invoke(objectToConvert, new object[] { - this.formatProviderField }))); - } - } - } - private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); - /// - /// Helper to produce culture-oriented representation of an object as a string - /// - public ToStringInstanceHelper ToStringHelper - { - get - { - return this.toStringHelperField; - } - } - #endregion -} - -/// -/// Service making names within a scope unique. Initialize a new instance for every scope. -/// -internal sealed class UniqueIdentifierService -{ - // This is the list of keywords we check against when creating parameter names from propert. - // If a name matches this keyword we prefix it. - private static readonly string[] Keywords = new string[] {"class", "event"}; - - /// - /// Hash set to detect identifier collision. - /// - private readonly HashSet knownIdentifiers; - - /// - /// Constructs a . - /// - /// true if the language we are generating the code for is case sensitive, false otherwise. - internal UniqueIdentifierService(bool caseSensitive) - { - this.knownIdentifiers = new HashSet(caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); - } - - /// - /// Constructs a . - /// - /// identifiers used to detect collision. - /// true if the language we are generating the code for is case sensitive, false otherwise. - internal UniqueIdentifierService(IEnumerable identifiers, bool caseSensitive) - { - this.knownIdentifiers = new HashSet(identifiers ?? Enumerable.Empty(), caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); - } - - /// - /// Given an identifier, makes it unique within the scope by adding - /// a suffix (1, 2, 3, ...), and returns the adjusted identifier. - /// - /// Identifier. Must not be null or empty. - /// Identifier adjusted to be unique within the scope. - internal string GetUniqueIdentifier(string identifier) - { - Debug.Assert(!string.IsNullOrEmpty(identifier), "identifier is null or empty"); - - // find a unique name by adding suffix as necessary - int numberOfConflicts = 0; - string uniqueIdentifier = identifier; - while (this.knownIdentifiers.Contains(uniqueIdentifier)) - { - ++numberOfConflicts; - uniqueIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture); - } - - // remember the identifier in this scope - Debug.Assert(!this.knownIdentifiers.Contains(uniqueIdentifier), "we just made it unique"); - this.knownIdentifiers.Add(uniqueIdentifier); - - return uniqueIdentifier; - } - - /// - /// Fix up the given parameter name and make it unique. - /// - /// Parameter name. - /// Fixed parameter name. - internal string GetUniqueParameterName(string name) - { - name = Utils.CamelCase(name); - - // FxCop consider 'iD' as violation, we will change any property that is 'id'(case insensitive) to 'ID' - if (StringComparer.OrdinalIgnoreCase.Equals(name, "id")) - { - name = "ID"; - } - - return this.GetUniqueIdentifier(name); - } -} - -/// -/// Utility class. -/// -internal static class Utils -{ - /// - /// Serializes the xml element to a string. - /// - /// The xml element to serialize. - /// The string representation of the xml. - internal static string SerializeToString(XElement xml) - { - // because comment nodes can contain special characters that are hard to embed in VisualBasic, remove them here - xml.DescendantNodes().OfType().Remove(); - - var stringBuilder = new StringBuilder(); - using (var writer = XmlWriter.Create( - stringBuilder, - new XmlWriterSettings - { - OmitXmlDeclaration = true, - NewLineHandling = NewLineHandling.Replace, - Indent = true, - })) - { - xml.WriteTo(writer); - } - - return stringBuilder.ToString(); - } - - /// - /// Changes the text to use camel case, which lower case for the first character. - /// - /// Text to convert. - /// The converted text in camel case - internal static string CamelCase(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); - } - - return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant() + text.Substring(1); - } - - /// - /// Changes the text to use pascal case, which upper case for the first character. - /// - /// Text to convert. - /// The converted text in pascal case - internal static string PascalCase(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant(); - } - - return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant() + text.Substring(1); - } - - /// - /// Gets the clr type name from the give type reference. - /// - /// The type reference in question. - /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, - /// false to use Collection for collections. - /// ODataClientTemplate instance that call this method. - /// CodeGenerationContext instance in the clientTemplate. - /// This flag indicates whether to return the type name in nullable format - /// The flag indicates whether the namespace need to be added by global prefix - /// This flag indicates whether the edmTypeReference is for an operation parameter - /// The clr type name of the type reference. - internal static string GetClrTypeName(IEdmTypeReference edmTypeReference, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context, bool addNullableTemplate = true, bool needGlobalPrefix = true, bool isOperationParameter = false, bool isEntitySingleType = false) - { - string clrTypeName; - IEdmType edmType = edmTypeReference.Definition; - IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; - if (edmPrimitiveType != null) - { - clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, clientTemplate); - if (edmTypeReference.IsNullable && !clientTemplate.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind) && addNullableTemplate) - { - clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); - } - } - else - { - IEdmComplexType edmComplexType = edmType as IEdmComplexType; - if (edmComplexType != null) - { - clrTypeName = context.GetPrefixedFullName(edmComplexType, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmComplexType.Name)) : clientTemplate.GetFixedName(edmComplexType.Name), clientTemplate); - } - else - { - IEdmEnumType edmEnumType = edmType as IEdmEnumType; - if (edmEnumType != null) - { - clrTypeName = context.GetPrefixedFullName(edmEnumType, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEnumType.Name)) : clientTemplate.GetFixedName(edmEnumType.Name), clientTemplate, needGlobalPrefix); - if (edmTypeReference.IsNullable && addNullableTemplate) - { - clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); - } - } - else - { - IEdmEntityType edmEntityType = edmType as IEdmEntityType; - if (edmEntityType != null) - { - clrTypeName = context.GetPrefixedFullName(edmEntityType, - context.EnableNamingAlias - ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEntityType.Name) + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)) - : clientTemplate.GetFixedName(edmEntityType.Name + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)), - clientTemplate); - } - else - { - IEdmCollectionType edmCollectionType = (IEdmCollectionType)edmType; - IEdmTypeReference elementTypeReference = edmCollectionType.ElementType; - IEdmPrimitiveType primitiveElementType = elementTypeReference.Definition as IEdmPrimitiveType; - if (primitiveElementType != null) - { - clrTypeName = Utils.GetClrTypeName(primitiveElementType, clientTemplate); - } - else - { - IEdmSchemaElement schemaElement = (IEdmSchemaElement)elementTypeReference.Definition; - clrTypeName = context.GetPrefixedFullName(schemaElement, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(schemaElement.Name)) : clientTemplate.GetFixedName(schemaElement.Name), clientTemplate); - } - - string collectionTypeName = isOperationParameter - ? clientTemplate.ICollectionOfTStructureTemplate - : (useDataServiceCollection - ? (elementTypeReference.TypeKind() == EdmTypeKind.Entity - ? clientTemplate.DataServiceCollectionStructureTemplate - : clientTemplate.ObservableCollectionStructureTemplate) - : clientTemplate.ObjectModelCollectionStructureTemplate); - - clrTypeName = string.Format(collectionTypeName, clrTypeName); - } - } - } - } - - return clrTypeName; - } - - /// - /// Gets the value expression to initualize the property with. - /// - /// The property in question. - /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, - /// false to use Collection for collections. - /// ODataClientTemplate instance that call this method. - /// CodeGenerationContext instance in the clientTemplate. - /// The value expression to initualize the property with. - internal static string GetPropertyInitializationValue(IEdmProperty property, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context) - { - IEdmTypeReference edmTypeReference = property.Type; - IEdmCollectionTypeReference edmCollectionTypeReference = edmTypeReference as IEdmCollectionTypeReference; - if (edmCollectionTypeReference == null) - { - IEdmStructuralProperty structuredProperty = property as IEdmStructuralProperty; - if (structuredProperty != null) - { - if (!string.IsNullOrEmpty(structuredProperty.DefaultValueString)) - { - string valueClrType = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - string defaultValue = structuredProperty.DefaultValueString; - bool isCSharpTemplate = clientTemplate is ODataClientCSharpTemplate; - if (edmTypeReference.Definition.TypeKind == EdmTypeKind.Enum) - { - var enumValues = defaultValue.Split(','); - string fullenumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - string enumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context, false, false); - List customizedEnumValues = new List(); - foreach(var enumValue in enumValues) - { - string currentEnumValue = enumValue.Trim(); - int indexFirst = currentEnumValue.IndexOf('\'') + 1; - int indexLast = currentEnumValue.LastIndexOf('\''); - if (indexFirst > 0 && indexLast > indexFirst) - { - currentEnumValue = currentEnumValue.Substring(indexFirst, indexLast - indexFirst); - } - - var customizedEnumValue = context.EnableNamingAlias ? Customization.CustomizeNaming(currentEnumValue) : currentEnumValue; - if (isCSharpTemplate) - { - currentEnumValue = "(" + fullenumTypeName + ")" + clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + customizedEnumValue + "\")"; - } - else - { - currentEnumValue = clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + currentEnumValue + "\")"; - } - customizedEnumValues.Add(currentEnumValue); - } - if (isCSharpTemplate) - { - return string.Join(" | ", customizedEnumValues); - } - else - { - return string.Join(" Or ", customizedEnumValues); - } - } - - if (valueClrType.Equals(clientTemplate.StringTypeName)) - { - defaultValue = "\"" + defaultValue + "\""; - } - else if (valueClrType.Equals(clientTemplate.BinaryTypeName)) - { - defaultValue = "System.Text.Encoding.UTF8.GetBytes(\"" + defaultValue + "\")"; - } - else if (valueClrType.Equals(clientTemplate.SingleTypeName)) - { - if (isCSharpTemplate) - { - defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "f"; - } - else - { - defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "F"; - } - } - else if (valueClrType.Equals(clientTemplate.DecimalTypeName)) - { - if (isCSharpTemplate) - { - // decimal in C# must be initialized with 'm' at the end, like Decimal dec = 3.00m - defaultValue = defaultValue.EndsWith("m", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "m"; - } - else - { - // decimal in VB must be initialized with 'D' at the end, like Decimal dec = 3.00D - defaultValue = defaultValue.ToLower().Replace("m", "D"); - defaultValue = defaultValue.EndsWith("D", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "D"; - } - } - else if (valueClrType.Equals(clientTemplate.GuidTypeName) - | valueClrType.Equals(clientTemplate.DateTimeOffsetTypeName) - | valueClrType.Equals(clientTemplate.DateTypeName) - | valueClrType.Equals(clientTemplate.TimeOfDayTypeName)) - { - defaultValue = valueClrType + ".Parse(\"" + defaultValue + "\")"; - } - else if (valueClrType.Equals(clientTemplate.DurationTypeName)) - { - defaultValue = clientTemplate.XmlConvertClassName + ".ToTimeSpan(\"" + defaultValue + "\")"; - } - else if (valueClrType.Contains("Microsoft.Spatial")) - { - defaultValue = string.Format(clientTemplate.GeoTypeInitializePattern, valueClrType, defaultValue); - } - - return defaultValue; - } - else - { - // doesn't have a default value - return null; - } - } - else - { - // only structured property has default value - return null; - } - } - else - { - string constructorParameters; - if (edmCollectionTypeReference.ElementType().IsEntity() && useDataServiceCollection) - { - constructorParameters = clientTemplate.DataServiceCollectionConstructorParameters; - } - else - { - constructorParameters = "()"; - } - - string clrTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - return clientTemplate.NewModifier + clrTypeName + constructorParameters; - } - } - - /// - /// Gets the clr type name from the give Edm primitive type. - /// - /// The Edm primitive type in question. - /// ODataClientTemplate instance that call this method. - /// The clr type name of the Edm primitive type. - internal static string GetClrTypeName(IEdmPrimitiveType edmPrimitiveType, ODataClientTemplate clientTemplate) - { - EdmPrimitiveTypeKind kind = edmPrimitiveType.PrimitiveKind; - - string type="UNKNOWN"; - if (kind==EdmPrimitiveTypeKind.Int32) - { - type= clientTemplate.Int32TypeName; - } - else if (kind== EdmPrimitiveTypeKind.String) - { - type= clientTemplate.StringTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Binary) - { - type= clientTemplate.BinaryTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Decimal) - { - type= clientTemplate.DecimalTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Int16) - { - type= clientTemplate.Int16TypeName; - } - else if(kind==EdmPrimitiveTypeKind.Single) - { - type= clientTemplate.SingleTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Boolean) - { - type= clientTemplate.BooleanTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Double) - { - type= clientTemplate.DoubleTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Guid) - { - type= clientTemplate.GuidTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Byte) - { - type= clientTemplate.ByteTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Int64) - { - type= clientTemplate.Int64TypeName; - } - else if (kind== EdmPrimitiveTypeKind.SByte) - { - type= clientTemplate.SByteTypeName; - } - else if (kind == EdmPrimitiveTypeKind.Stream) - { - type= clientTemplate.DataServiceStreamLinkTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Geography) - { - type= clientTemplate.GeographyTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyPoint) - { - type= clientTemplate.GeographyPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyLineString) - { - type= clientTemplate.GeographyLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyPolygon) - { - type= clientTemplate.GeographyPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyCollection) - { - type= clientTemplate.GeographyCollectionTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiPolygon) - { - type= clientTemplate.GeographyMultiPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiLineString) - { - type= clientTemplate.GeographyMultiLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiPoint) - { - type= clientTemplate.GeographyMultiPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Geometry) - { - type= clientTemplate.GeometryTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryPoint) - { - type= clientTemplate.GeometryPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryLineString) - { - type= clientTemplate.GeometryLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryPolygon) - { - type= clientTemplate.GeometryPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryCollection) - { - type= clientTemplate.GeometryCollectionTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiPolygon) - { - type= clientTemplate.GeometryMultiPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiLineString) - { - type= clientTemplate.GeometryMultiLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiPoint) - { - type= clientTemplate.GeometryMultiPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.DateTimeOffset) - { - type= clientTemplate.DateTimeOffsetTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Duration) - { - type= clientTemplate.DurationTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Date) - { - type= clientTemplate.DateTypeName; - } - else if (kind== EdmPrimitiveTypeKind.TimeOfDay) - { - type= clientTemplate.TimeOfDayTypeName; - } - else - { - throw new Exception("Type "+kind.ToString()+" is unrecognized"); - } - - return type; - } -} - -public sealed class ODataClientCSharpTemplate : ODataClientTemplate -{ - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The code generation context. - public ODataClientCSharpTemplate(CodeGenerationContext context) - : base(context) - { - } - - internal override string GlobalPrefix { get {return "global::"; } } - internal override string SystemTypeTypeName { get { return "global::System.Type"; } } - internal override string AbstractModifier { get { return " abstract"; } } - internal override string DataServiceActionQueryTypeName { get { return "global::Microsoft.OData.Client.DataServiceActionQuery"; } } - internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuerySingle<{0}>"; } } - internal override string DataServiceActionQueryOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuery<{0}>"; } } - internal override string NotifyPropertyChangedModifier { get { return "global::System.ComponentModel.INotifyPropertyChanged"; } } - internal override string ClassInheritMarker { get { return " : "; } } - internal override string ParameterSeparator { get { return ", \r\n "; } } - internal override string KeyParameterSeparator { get { return ", \r\n "; } } - internal override string KeyDictionaryItemSeparator { get { return ", \r\n "; } } - internal override string SystemNullableStructureTemplate { get { return "global::System.Nullable<{0}>"; } } - internal override string ICollectionOfTStructureTemplate { get { return "global::System.Collections.Generic.ICollection<{0}>"; } } - internal override string DataServiceCollectionStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceCollection<{0}>"; } } - internal override string DataServiceQueryStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuery<{0}>"; } } - internal override string DataServiceQuerySingleStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuerySingle<{0}>"; } } - internal override string ObservableCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.ObservableCollection<{0}>"; } } - internal override string ObjectModelCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.Collection<{0}>"; } } - internal override string DataServiceCollectionConstructorParameters { get { return "(null, global::Microsoft.OData.Client.TrackingMode.None)"; } } - internal override string NewModifier { get { return "new "; } } - internal override string GeoTypeInitializePattern { get { return "global::Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(false).Read<{0}>(new global::System.IO.StringReader(\"{1}\"))"; } } - internal override string Int32TypeName { get { return "int"; } } - internal override string StringTypeName { get { return "string"; } } - internal override string BinaryTypeName { get { return "byte[]"; } } - internal override string DecimalTypeName { get { return "decimal"; } } - internal override string Int16TypeName { get { return "short"; } } - internal override string SingleTypeName { get { return "float"; } } - internal override string BooleanTypeName { get { return "bool"; } } - internal override string DoubleTypeName { get { return "double"; } } - internal override string GuidTypeName { get { return "global::System.Guid"; } } - internal override string ByteTypeName { get { return "byte"; } } - internal override string Int64TypeName { get { return "long"; } } - internal override string SByteTypeName { get { return "sbyte"; } } - internal override string DataServiceStreamLinkTypeName { get { return "global::Microsoft.OData.Client.DataServiceStreamLink"; } } - internal override string GeographyTypeName { get { return "global::Microsoft.Spatial.Geography"; } } - internal override string GeographyPointTypeName { get { return "global::Microsoft.Spatial.GeographyPoint"; } } - internal override string GeographyLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyLineString"; } } - internal override string GeographyPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyPolygon"; } } - internal override string GeographyCollectionTypeName { get { return "global::Microsoft.Spatial.GeographyCollection"; } } - internal override string GeographyMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPolygon"; } } - internal override string GeographyMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyMultiLineString"; } } - internal override string GeographyMultiPointTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPoint"; } } - internal override string GeometryTypeName { get { return "global::Microsoft.Spatial.Geometry"; } } - internal override string GeometryPointTypeName { get { return "global::Microsoft.Spatial.GeometryPoint"; } } - internal override string GeometryLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryLineString"; } } - internal override string GeometryPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryPolygon"; } } - internal override string GeometryCollectionTypeName { get { return "global::Microsoft.Spatial.GeometryCollection"; } } - internal override string GeometryMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPolygon"; } } - internal override string GeometryMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryMultiLineString"; } } - internal override string GeometryMultiPointTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPoint"; } } - internal override string DateTypeName { get { return "global::Microsoft.OData.Edm.Date"; } } - internal override string DateTimeOffsetTypeName { get { return "global::System.DateTimeOffset"; } } - internal override string DurationTypeName { get { return "global::System.TimeSpan"; } } - internal override string TimeOfDayTypeName { get { return "global::Microsoft.OData.Edm.TimeOfDay"; } } - internal override string XmlConvertClassName { get { return "global::System.Xml.XmlConvert"; } } - internal override string EnumTypeName { get { return "global::System.Enum"; } } - internal override string FixPattern { get { return "@{0}"; } } - internal override string EnumUnderlyingTypeMarker { get { return " : "; } } - internal override string ConstantExpressionConstructorWithType { get { return "global::System.Linq.Expressions.Expression.Constant({0}, typeof({1}))"; } } - internal override string TypeofFormatter { get { return "typeof({0})"; } } - internal override string UriOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } - internal override string UriEntityOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } - internal override string BodyOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } - internal override string BaseEntityType { get { return " : global::Microsoft.OData.Client.BaseEntityType"; } } - internal override string OverloadsModifier { get { return "new "; } } - internal override string ODataVersion { get { return "global::Microsoft.OData.ODataVersion.V4"; } } - internal override string ParameterDeclarationTemplate { get { return "{0} {1}"; } } - internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } - internal override HashSet LanguageKeywords { get { - if (CSharpKeywords == null) - { - CSharpKeywords = new HashSet(StringComparer.Ordinal) - { - "abstract", "as", "base", "byte", "bool", "break", "case", "catch", "char", "checked", "class", "const", "continue", - "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "for", - "foreach", "finally", "fixed", "float", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", - "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", - "readonly", "ref", "return", "sbyte", "sealed", "string", "short", "sizeof", "stackalloc", "static", "struct", "switch", - "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "volatile", - "void", "while" - }; - } - return CSharpKeywords; - } } - private HashSet CSharpKeywords; - - internal override void WriteFileHeader() - { -#>//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:<#= Environment.Version #> -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -// Generation date: <#= DateTime.Now.ToString(global::System.Globalization.CultureInfo.CurrentCulture) #> -<#+ - } - - internal override void WriteNamespaceStart(string fullNamespace) - { -#> -namespace <#= fullNamespace #> -{ -<#+ - } - - internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) - { -#> - /// - /// There are no comments for <#= containerName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalContainerName #>")] -<#+ - } -#> - public partial class <#= fixedContainerName #> : global::Microsoft.OData.Client.DataServiceContext - { -<#+ - } - - internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) - { -#> - /// - /// Initialize a new <#= containerName #> object. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public <#= fixedContainerName #>(global::System.Uri serviceRoot) : - base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4) - { -<#+ - } - - internal override void WriteKeyAsSegmentUrlConvention() - { -#> - this.UrlKeyDelimiter = global::Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash; -<#+ - } - - internal override void WriteInitializeResolveName() - { -#> - this.ResolveName = new global::System.Func(this.ResolveNameFromType); -<#+ - } - - internal override void WriteInitializeResolveType() - { -#> - this.ResolveType = new global::System.Func(this.ResolveTypeFromName); -<#+ - } - - internal override void WriteClassEndForEntityContainerConstructor() - { -#> - this.OnContextCreated(); - this.Format.LoadServiceModel = GeneratedEdmModel.GetInstance; - this.Format.UseJson(); - } - partial void OnContextCreated(); -<#+ - } - - internal override void WriteMethodStartForResolveTypeFromName() - { -#> - /// - /// Since the namespace configured for this service reference - /// in Visual Studio is different from the one indicated in the - /// server schema, use type-mappers to map between the two. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected global::System.Type ResolveTypeFromName(string typeName) - { -<#+ - } - - internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) - { -#> - <#= typeName #>resolvedType = this.DefaultResolveType(typeName, "<#= fullNamespace #>", "<#= languageDependentNamespace #>"); - if ((resolvedType != null)) - { - return resolvedType; - } -<#+ - } - - internal override void WriteMethodEndForResolveTypeFromName() - { -#> - return null; - } -<#+ - } - - internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) - { - - } - - internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) - { -#> - /// - /// Since the namespace configured for this service reference - /// in Visual Studio is different from the one indicated in the - /// server schema, use type-mappers to map between the two. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected string ResolveNameFromType(global::System.Type clientType) - { -<#+ - if (this.context.EnableNamingAlias) - { -#> - global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true)); -<#+ - } - } - - internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) - { -#> - if (clientType.Namespace.Equals("<#= languageDependentNamespace #>", global::System.StringComparison.Ordinal)) - { -<#+ - if (this.context.EnableNamingAlias) - { -#> - if (originalNameAttribute != null) - { - return string.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName); - } -<#+ - } -#> - return string.Concat("<#= fullNamespace #>.", clientType.Name); - } -<#+ - } - - internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) - { - if (this.context.EnableNamingAlias && modelHasInheritance) - { -#> - if (originalNameAttribute != null) - { - return clientType.Namespace + "." + originalNameAttribute.OriginalName; - } -<#+ - } -#> - return <#= modelHasInheritance ? "clientType.FullName" : "null" #>; - } -<#+ - } - - internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) - { -#> - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path) - : base(context, path) {} - - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path, bool isComposable) - : base(context, path, isComposable) {} - - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(<#= baseTypeName #> query) - : base(query) {} - -<#+ - } - - internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) - { -#> - /// - /// There are no comments for <#= entitySetName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEntitySetName #>")] -<#+ - } -#> - public global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> <#= entitySetFixedName #> - { - get - { -<#+ - if (!inContext) - { -#> - if (!this.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } -<#+ - } -#> - if ((this._<#= entitySetName #> == null)) - { - this._<#= entitySetName #> = <#= inContext ? "base" : "Context" #>.CreateQuery<<#= entitySetElementTypeName #>>(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>); - } - return this._<#= entitySetName #>; - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> _<#= entitySetName #>; -<#+ - } - - internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) - { -#> - /// - /// There are no comments for <#= singletonName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalSingletonName #>")] -<#+ - } -#> - public <#= singletonElementTypeName #> <#= singletonFixedName #> - { - get - { -<#+ - if (!inContext) - { -#> - if (!this.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } -<#+ - } -#> - if ((this._<#= singletonName #> == null)) - { - this._<#= singletonName #> = new <#= singletonElementTypeName #>(<#= inContext ? "this" : "this.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>); - } - return this._<#= singletonName #>; - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private <#= singletonElementTypeName #> _<#= singletonName #>; -<#+ - } - - internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) - { -#> - /// - /// There are no comments for <#= entitySetName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public void AddTo<#= entitySetName #>(<#= typeName #> <#= parameterName #>) - { - base.AddObject("<#= originalEntitySetName #>", <#= parameterName #>); - } -<#+ - } - - internal override void WriteGeneratedEdmModel(string escapedEdmxString) - { - - string path = this.context.TempFilePath; - - if (!String.IsNullOrEmpty(path)) - { - using (StreamWriter writer = new StreamWriter(path, true)) - { - writer.WriteLine(escapedEdmxString); - } - } - - bool useTempFile = !String.IsNullOrEmpty(path) && System.IO.File.Exists(path); -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private abstract class GeneratedEdmModel - { -<#+ - if (this.context.ReferencesMap != null) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Collections.Generic.Dictionary ReferencesMap = new global::System.Collections.Generic.Dictionary() - { -<#+ - foreach(var reference in this.context.ReferencesMap) - { -#> - {@"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", @"<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"") #>"}, -<#+ - } -#> - }; -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString(); -<#+ - if (useTempFile) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private const string filePath = @"<#= path #>"; -<#+ - } - else - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private const string Edmx = @"<#= escapedEdmxString #>"; -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public static global::Microsoft.OData.Edm.IEdmModel GetInstance() - { - return ParsedModel; - } -<#+ - if (this.context.ReferencesMap != null) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader getReferencedModelFromMap(global::System.Uri uri) - { - string referencedEdmx; - if (ReferencesMap.TryGetValue(uri.OriginalString, out referencedEdmx)) - { - return CreateXmlReader(referencedEdmx); - } - - return null; - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() - { -<#+ - if (useTempFile) - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(); -<#+ - } - else - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); -<#+ - } -#> - try - { - return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, getReferencedModelFromMap); - } - finally - { - ((global::System.IDisposable)(reader)).Dispose(); - } - } -<#+ - } - else - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() - { -<#+ - if (useTempFile) - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(); -<#+ - } - else - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); -<#+ - } -#> - try - { - global::System.Collections.Generic.IEnumerable errors; - global::Microsoft.OData.Edm.IEdmModel edmModel; - - if (!global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, <#= this.context.IgnoreUnexpectedElementsAndAttributes ? "true" : "false" #>, out edmModel, out errors)) - { - global::System.Text.StringBuilder errorMessages = new System.Text.StringBuilder(); - foreach (var error in errors) - { - errorMessages.Append(error.ErrorMessage); - errorMessages.Append("; "); - } - throw new global::System.InvalidOperationException(errorMessages.ToString()); - } - - return edmModel; - } - finally - { - ((global::System.IDisposable)(reader)).Dispose(); - } - } -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse) - { - return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse)); - } -<#+ - if (useTempFile) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader CreateXmlReader() - { - return global::System.Xml.XmlReader.Create(new global::System.IO.StreamReader(filePath)); - } -<#+ - } -#> - } -<#+ - } - - internal override void WriteClassEndForEntityContainer() - { -#> - } -<#+ - } - - internal override void WriteSummaryCommentForStructuredType(string typeName) - { -#> - /// - /// There are no comments for <#= typeName #> in the schema. - /// -<#+ - } - - internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) - { -#> - /// -<#+ - foreach (string key in keyProperties) - { -#> - /// <#= key #> -<#+ - } -#> - /// - [global::Microsoft.OData.Client.Key("<#= keyString #>")] -<#+ - } - - internal override void WriteEntityTypeAttribute() - { -#> - [global::Microsoft.OData.Client.EntityType()] -<#+ - } - - internal override void WriteEntitySetAttribute(string entitySetName) - { -#> - [global::Microsoft.OData.Client.EntitySet("<#= entitySetName #>")] -<#+ - } - - internal override void WriteEntityHasStreamAttribute() - { -#> - [global::Microsoft.OData.Client.HasStream()] -<#+ - } - - internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalTypeName #>")] -<#+ - } -#> - public<#= abstractModifier #> partial class <#= typeName #><#= baseTypeName #> - { -<#+ - } - - internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) - { -#> - /// - /// Create a new <#= typeName #> object. - /// -<#+ - } - - internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) - { -#> - /// Initial value of <#= propertyName #>. -<#+ - } - - internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public static <#= fixedTypeName #> Create<#= typeName #>(<#+ - } - - internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) - { -#><#= parameterTypeName #> <#= parameterName #><#= parameterSeparater #><#+ - } - - internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) - { - #>) - { - <#= typeName #> <#= instanceName #> = new <#= typeName #>(); -<#+ - } - - internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) - { -#> - if ((<#= parameterName #> == null)) - { - throw new global::System.ArgumentNullException("<#= parameterName #>"); - } -<#+ - } - - internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) - { -#> - <#= instanceName #>.<#= propertyName #> = <#= parameterName #>; -<#+ - } - - internal override void WriteMethodEndForStaticCreateMethod(string instanceName) - { -#> - return <#= instanceName #>; - } -<#+ - } - - internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) - { -#> - /// - /// There are no comments for Property <#= propertyName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalPropertyName #>")] -<#+ - } -#> - public <#= propertyType #> <#= fixedPropertyName #> - { - get - { - return this.<#= privatePropertyName #>; - } - set - { - this.On<#= propertyName #>Changing(value); - this.<#= privatePropertyName #> = value; - this.On<#= propertyName #>Changed(); -<#+ - if (writeOnPropertyChanged) - { -#> - this.OnPropertyChanged("<#= originalPropertyName #>"); -<#+ - } -#> - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private <#= propertyType #> <#= privatePropertyName #><#= propertyInitializationValue != null ? " = " + propertyInitializationValue : string.Empty #>; - partial void On<#= propertyName #>Changing(<#= propertyType #> value); - partial void On<#= propertyName #>Changed(); -<#+ - } - - internal override void WriteINotifyPropertyChangedImplementation() - { -#> - /// - /// This event is raised when the value of the property is changed - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - /// - /// The value of the property is changed - /// - /// property name - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected virtual void OnPropertyChanged(string property) - { - if ((this.PropertyChanged != null)) - { - this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property)); - } - } -<#+ - } - - internal override void WriteClassEndForStructuredType() - { -#> - } -<#+ - } - - internal override void WriteEnumFlags() - { -#> - [global::System.Flags] -<#+ - } - - internal override void WriteSummaryCommentForEnumType(string enumName) - { -#> - /// - /// There are no comments for <#= enumName #> in the schema. - /// -<#+ - } - - internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEnumName #>")] -<#+ - } -#> - public enum <#= enumName #><#= underlyingType #> - { -<#+ - } - - internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalMemberName #>")] -<#+ - } -#> - <#= member #><#= last ? string.Empty : "," #> -<#+ - } - - internal override void WriteEnumEnd() - { -#> - } -<#+ - } - - internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - return this.CreateFunctionQuery<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.CreateFunctionQuerySingle<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - global::System.Uri requestUri; - Context.TryGetUri(this, out requestUri); - return this.Context.CreateFunctionQuery<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>); - } -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - global::System.Uri requestUri; - Context.TryGetUri(this, out requestUri); - - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.Context.CreateFunctionQuerySingle<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public <#= returnTypeName #> <#= actionName #>(<#= parameters #>) - { - return new <#= returnTypeName #>(this, this.BaseUri.OriginalString.Trim('/') + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= returnTypeName #> <#= actionName #>(<#= parameters #>) - { - global::Microsoft.OData.Client.EntityDescriptor resource = Context.EntityTracker.TryGetEntityDescriptor(this); - if (resource == null) - { - throw new global::System.Exception("cannot find entity"); - } - - return new <#= returnTypeName #>(this.Context, resource.EditLink.OriginalString.Trim('/') + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteExtensionMethodsStart() - { -#> - /// - /// Class containing all extension methods - /// - public static class ExtensionMethods - { -<#+ - } - - internal override void WriteExtensionMethodsEnd() - { -#> - } -<#+ - } - - internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) - { -#> - /// - /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - /// - /// source entity set - /// dictionary with the names and values of keys - public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, global::System.Collections.Generic.Dictionary keys) - { - return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); - } - /// - /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - /// - /// source entity set -<#+ - foreach (var key in keys) - { -#> - /// The value of <#= key #> -<#+ - } -#> - public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, - <#= keyParameters #>) - { - global::System.Collections.Generic.Dictionary keys = new global::System.Collections.Generic.Dictionary - { - <#= keyDictionaryItems #> - }; - return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); - } -<#+ - } - - internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) - { -#> - /// - /// Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> - /// - /// source entity - public static <#= returnTypeName #> CastTo<#= derivedTypeName #>(this global::Microsoft.OData.Client.DataServiceQuerySingle<<#= baseTypeName #>> source) - { - global::Microsoft.OData.Client.DataServiceQuerySingle<<#= derivedTypeFullName #>> query = source.CastTo<<#= derivedTypeFullName #>>(); - return new <#= returnTypeName #>(source.Context, query.GetPath(null)); - } -<#+ - } - - internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public static <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public static global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = true" : string.Empty #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return source.CreateFunctionQuery<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public static <#= returnTypeName #> <#= actionName #>(this <#= boundSourceType #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return new <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteNamespaceEnd() - { -#> -} -<#+ - } -} - -public sealed class ODataClientVBTemplate : ODataClientTemplate -{ - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The cotion context. - public ODataClientVBTemplate(CodeGenerationContext context) - : base(context) - { - } - - internal override string GlobalPrefix { get { return string.Empty; } } - internal override string SystemTypeTypeName { get { return "Global.System.Type"; } } - internal override string AbstractModifier { get { return " MustInherit"; } } - internal override string DataServiceActionQueryTypeName { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery"; } } - internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuerySingle(Of {0})"; } } - internal override string DataServiceActionQueryOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery(Of {0})"; } } - internal override string NotifyPropertyChangedModifier { get { return "\r\n Implements Global.System.ComponentModel.INotifyPropertyChanged"; } } - internal override string ClassInheritMarker { get { return "\r\n Inherits "; } } - internal override string ParameterSeparator { get { return ", _\r\n "; } } - internal override string KeyParameterSeparator { get { return ", _\r\n "; } } - internal override string KeyDictionaryItemSeparator { get { return ", _\r\n "; } } - internal override string SystemNullableStructureTemplate { get { return "Global.System.Nullable(Of {0})"; } } - internal override string ICollectionOfTStructureTemplate { get { return "Global.System.Collections.Generic.ICollection(Of {0})"; } } - internal override string DataServiceCollectionStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceCollection(Of {0})"; } } - internal override string DataServiceQueryStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuery(Of {0})"; } } - internal override string DataServiceQuerySingleStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuerySingle(Of {0})"; } } - internal override string ObservableCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.ObservableCollection(Of {0})"; } } - internal override string ObjectModelCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.Collection(Of {0})"; } } - internal override string DataServiceCollectionConstructorParameters { get { return "(Nothing, Global.Microsoft.OData.Client.TrackingMode.None)"; } } - internal override string NewModifier { get { return "New "; } } - internal override string GeoTypeInitializePattern { get { return "Global.Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(False).Read(Of {0})(New Global.System.IO.StringReader(\"{1}\"))"; } } - internal override string Int32TypeName { get { return "Integer"; } } - internal override string StringTypeName { get { return "String"; } } - internal override string BinaryTypeName { get { return "Byte()"; } } - internal override string DecimalTypeName { get { return "Decimal"; } } - internal override string Int16TypeName { get { return "Short"; } } - internal override string SingleTypeName { get { return "Single"; } } - internal override string BooleanTypeName { get { return "Boolean"; } } - internal override string DoubleTypeName { get { return "Double"; } } - internal override string GuidTypeName { get { return "Global.System.Guid"; } } - internal override string ByteTypeName { get { return "Byte"; } } - internal override string Int64TypeName { get { return "Long"; } } - internal override string SByteTypeName { get { return "SByte"; } } - internal override string DataServiceStreamLinkTypeName { get { return "Global.Microsoft.OData.Client.DataServiceStreamLink"; } } - internal override string GeographyTypeName { get { return "Global.Microsoft.Spatial.Geography"; } } - internal override string GeographyPointTypeName { get { return "Global.Microsoft.Spatial.GeographyPoint"; } } - internal override string GeographyLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyLineString"; } } - internal override string GeographyPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyPolygon"; } } - internal override string GeographyCollectionTypeName { get { return "Global.Microsoft.Spatial.GeographyCollection"; } } - internal override string GeographyMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPolygon"; } } - internal override string GeographyMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiLineString"; } } - internal override string GeographyMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPoint"; } } - internal override string GeometryTypeName { get { return "Global.Microsoft.Spatial.Geometry"; } } - internal override string GeometryPointTypeName { get { return "Global.Microsoft.Spatial.GeometryPoint"; } } - internal override string GeometryLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryLineString"; } } - internal override string GeometryPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryPolygon"; } } - internal override string GeometryCollectionTypeName { get { return "Global.Microsoft.Spatial.GeometryCollection"; } } - internal override string GeometryMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPolygon"; } } - internal override string GeometryMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiLineString"; } } - internal override string GeometryMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPoint"; } } - internal override string DateTypeName { get { return "Global.Microsoft.OData.Edm.Date"; } } - internal override string DateTimeOffsetTypeName { get { return "Global.System.DateTimeOffset"; } } - internal override string DurationTypeName { get { return "Global.System.TimeSpan"; } } - internal override string TimeOfDayTypeName { get { return "Global.Microsoft.OData.Edm.TimeOfDay"; } } - internal override string XmlConvertClassName { get { return "Global.System.Xml.XmlConvert"; } } - internal override string EnumTypeName { get { return "Global.System.Enum"; } } - internal override string FixPattern { get { return "[{0}]"; } } - internal override string EnumUnderlyingTypeMarker { get { return " As "; } } - internal override string ConstantExpressionConstructorWithType { get { return "Global.System.Linq.Expressions.Expression.Constant({0}, GetType({1}))"; } } - internal override string TypeofFormatter { get { return "GetType({0})"; } } - internal override string UriOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } - internal override string UriEntityOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } - internal override string BodyOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } - internal override string BaseEntityType { get { return "\r\n Inherits Global.Microsoft.OData.Client.BaseEntityType"; } } - internal override string OverloadsModifier { get { return "Overloads "; } } - internal override string ODataVersion { get { return "Global.Microsoft.OData.ODataVersion.V4"; } } - internal override string ParameterDeclarationTemplate { get { return "{1} As {0}"; } } - internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } - internal override HashSet LanguageKeywords { get { - if (VBKeywords == null) - { - VBKeywords = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte", "ByVal", - "Call", "Case", "Catch", "CBool", "", "CByte", "CChar", "CDate", "CDbl", "CDec", "Char", - "CInt", "Class", "CLng", "CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", - "CType", "CUInt", "CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", - "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", - "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", - "GetXMLNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In", "Inherits", - "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like", "Long", "Loop", "Me", - "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", "Namespace", "Narrowing", "New", "Next", - "Not", "Nothing", "NotInheritable", "NotOverridable", "Object", "Of", "On", "Operator", "Option", "Optional", - "Or", "OrElse", "Out", "Overloads", "Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", - "Protected", "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "SByte", - "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", - "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast", "TypeOf", - "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While", "Widening", "With", - "WithEvents", "WriteOnly", "Xor" - }; - } - return VBKeywords; - } } - private HashSet VBKeywords; - - internal override void WriteFileHeader() - { -#>'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:<#= Environment.Version #> -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict Off -Option Explicit On - - -'Generation date: <#= DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture) #> -<#+ - } - - internal override void WriteNamespaceStart(string fullNamespace) - { -#> -Namespace <#= fullNamespace #> -<#+ - } - - internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) - { -#> - ''' - '''There are no comments for <#= containerName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Partial Public Class <#= fixedContainerName #> - Inherits Global.Microsoft.OData.Client.DataServiceContext -<#+ - } - - internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) - { -#> - ''' - '''Initialize a new <#= containerName #> object. - ''' - ")> _ - Public Sub New(ByVal serviceRoot As Global.System.Uri) - MyBase.New(serviceRoot, Global.Microsoft.OData.Client.ODataProtocolVersion.V4) -<#+ - } - - internal override void WriteKeyAsSegmentUrlConvention() - { -#> - Me.UrlKeyDelimiter = Global.Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash -<#+ - } - - internal override void WriteInitializeResolveName() - { -#> - Me.ResolveName = AddressOf Me.ResolveNameFromType -<#+ - } - - internal override void WriteInitializeResolveType() - { -#> - Me.ResolveType = AddressOf Me.ResolveTypeFromName -<#+ - } - - internal override void WriteClassEndForEntityContainerConstructor() - { -#> - Me.OnContextCreated - Me.Format.LoadServiceModel = AddressOf GeneratedEdmModel.GetInstance - Me.Format.UseJson() - End Sub - Partial Private Sub OnContextCreated() - End Sub -<#+ - } - - internal override void WriteMethodStartForResolveTypeFromName() - { -#> - ''' - '''Since the namespace configured for this service reference - '''in Visual Studio is different from the one indicated in the - '''server schema, use type-mappers to map between the two. - ''' - ")> _ - Protected Function ResolveTypeFromName(ByVal typeName As String) As Global.System.Type -<#+ - } - - internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) - { - if (!string.IsNullOrEmpty(typeName)) - { -#> - Dim resolvedType As <#= typeName #>= Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) -<#+ - } - else - { -#> - resolvedType = Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) -<#+ - } -#> - If (Not (resolvedType) Is Nothing) Then - Return resolvedType - End If -<#+ - } - - internal override void WriteMethodEndForResolveTypeFromName() - { -#> - Return Nothing - End Function -<#+ - } - - internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) - { -#> - ")> _ - Private Shared ROOTNAMESPACE As String = GetType(<#= containerName #>).Namespace.Remove(GetType(<#= containerName #>).Namespace.LastIndexOf("<#= fullNamespace #>")) -<#+ - } - - internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) - { -#> - ''' - '''Since the namespace configured for this service reference - '''in Visual Studio is different from the one indicated in the - '''server schema, use type-mappers to map between the two. - ''' - ")> _ - Protected Function ResolveNameFromType(ByVal clientType As Global.System.Type) As String -<#+ - if (this.context.EnableNamingAlias) - { -#> - Dim originalNameAttribute As Global.Microsoft.OData.Client.OriginalNameAttribute = - CType(Global.System.Linq.Enumerable.SingleOrDefault(Global.Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, GetType(Global.Microsoft.OData.Client.OriginalNameAttribute), true)), Global.Microsoft.OData.Client.OriginalNameAttribute) -<#+ - } - } - - internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) - { -#> - If clientType.Namespace.Equals(String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>"), Global.System.StringComparison.OrdinalIgnoreCase) Then -<#+ - if (this.context.EnableNamingAlias) - { -#> - If (Not (originalNameAttribute) Is Nothing) Then - Return String.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName) - End If -<#+ - } -#> - Return String.Concat("<#= fullNamespace #>.", clientType.Name) - End If -<#+ - } - - internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) - { - if (this.context.EnableNamingAlias && modelHasInheritance) - { -#> - If (Not (originalNameAttribute) Is Nothing) Then - Dim fullName As String = clientType.FullName.Substring(ROOTNAMESPACE.Length) - Return fullName.Remove(fullName.LastIndexOf(clientType.Name)) + originalNameAttribute.OriginalName - End If -<#+ - } -#> - Return <#= modelHasInheritance ? "clientType.FullName.Substring(ROOTNAMESPACE.Length)" : "Nothing" #> - End Function -<#+ - } - - internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) - { -#> - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String) - MyBase.New(context, path) - End Sub - - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String, ByVal isComposable As Boolean) - MyBase.New(context, path, isComposable) - End Sub - - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal query As <#= baseTypeName #>) - MyBase.New(query) - End Sub -<#+ - } - - internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) - { -#> - ''' - '''There are no comments for <#= entitySetName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public ReadOnly Property <#= entitySetFixedName #>() As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) - Get -<#+ - if (!inContext) - { -#> - If Not Me.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If -<#+ - } -#> - If (Me._<#= entitySetName #> Is Nothing) Then - Me._<#= entitySetName #> = <#= inContext ? "MyBase" : "Context"#>.CreateQuery(Of <#= entitySetElementTypeName #>)(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>) - End If - Return Me._<#= entitySetName #> - End Get - End Property - ")> _ - Private _<#= entitySetName #> As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) -<#+ - } - - internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) - { -#> - ''' - '''There are no comments for <#= singletonName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public ReadOnly Property <#= singletonFixedName #>() As <#= singletonElementTypeName #> - Get -<#+ - if (!inContext) - { -#> - If Not Me.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If -<#+ - } -#> - If (Me._<#= singletonName #> Is Nothing) Then - Me._<#= singletonName #> = New <#= singletonElementTypeName #>(<#= inContext ? "Me" : "Me.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>) - End If - Return Me._<#= singletonName #> - End Get - End Property - ")> _ - Private _<#= singletonName #> As <#= singletonElementTypeName #> -<#+ - } - - internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) - { -#> - ''' - '''There are no comments for <#= entitySetName #> in the schema. - ''' - ")> _ - Public Sub AddTo<#= entitySetName #>(ByVal <#= parameterName #> As <#= typeName #>) - MyBase.AddObject("<#= originalEntitySetName #>", <#= parameterName #>) - End Sub -<#+ - } - - internal override void WriteGeneratedEdmModel(string escapedEdmxString) - { - escapedEdmxString = escapedEdmxString.Replace("\r\n", "\" & _\r\n \""); -#> - ")> _ - Private MustInherit Class GeneratedEdmModel -<#+ - if (this.context.ReferencesMap != null) - { -#> - ")> _ - Private Shared ReferencesMap As Global.System.Collections.Generic.Dictionary(Of String, String) = New Global.System.Collections.Generic.Dictionary(Of String, String) From - { -<#+ - int count = this.context.ReferencesMap.Count(); - foreach(var reference in this.context.ReferencesMap) - { -#> - {"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", "<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"").Replace("\r\n", "\" & _\r\n \"") #>"}<#= (--count>0?",":"")#> -<#+ - } -#> - } -<#+ - } -#> - ")> _ - Private Shared ParsedModel As Global.Microsoft.OData.Edm.IEdmModel = LoadModelFromString - ")> _ - Private Const Edmx As String = "<#= escapedEdmxString #>" - ")> _ - Public Shared Function GetInstance() As Global.Microsoft.OData.Edm.IEdmModel - Return ParsedModel - End Function -<#+ - if (this.context.ReferencesMap != null) - { -#> - ")> _ - Private Shared Function getReferencedModelFromMap(ByVal uri As Global.System.Uri) As Global.System.Xml.XmlReader - Dim referencedEdmx As String = Nothing - If (ReferencesMap.TryGetValue(uri.OriginalString, referencedEdmx)) Then - Return CreateXmlReader(referencedEdmx) - End If - Return Nothing - End Function - ")> _ - Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel - Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) - Try - Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, AddressOf getReferencedModelFromMap) - Finally - CType(reader,Global.System.IDisposable).Dispose - End Try - End Function -<#+ - } - else - { -#> - ")> _ - Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel - Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) - Try - Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader) - Finally - CType(reader,Global.System.IDisposable).Dispose - End Try - End Function -<#+ - } -#> - ")> _ - Private Shared Function CreateXmlReader(ByVal edmxToParse As String) As Global.System.Xml.XmlReader - Return Global.System.Xml.XmlReader.Create(New Global.System.IO.StringReader(edmxToParse)) - End Function - End Class -<#+ - } - - internal override void WriteClassEndForEntityContainer() - { -#> - End Class -<#+ - } - - internal override void WriteSummaryCommentForStructuredType(string typeName) - { -#> - ''' - '''There are no comments for <#= typeName #> in the schema. - ''' -<#+ - } - - internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) - { -#> - ''' -<#+ - foreach (string key in keyProperties) - { -#> - '''<#= key #> -<#+ - } -#> - ''' - ")> _ -<#+ - } - - internal override void WriteEntityTypeAttribute() - { -#> - _ -<#+ - } - - internal override void WriteEntitySetAttribute(string entitySetName) - { -#> - ")> _ -<#+ - } - - internal override void WriteEntityHasStreamAttribute() - { -#> - _ -<#+ - } - - internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Partial Public<#= abstractModifier #> Class <#= typeName #><#= baseTypeName #> -<#+ - } - - internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) - { -#> - ''' - '''Create a new <#= typeName #> object. - ''' -<#+ - } - - internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) - { -#> - '''Initial value of <#= propertyName #>. -<#+ - } - - internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) - { -#> - ")> _ - Public Shared Function Create<#= typeName #>(<#+ - - } - - internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) - { -#>ByVal <#= parameterName #> As <#= parameterTypeName #><#= parameterSeparater #><#+ - } - - internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) - { - #>) As <#= typeName #> - Dim <#= instanceName #> As <#= typeName #> = New <#= typeName #>() -<#+ - } - - internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) - { -#> - If (<#= parameterName #> Is Nothing) Then - Throw New Global.System.ArgumentNullException("<#= parameterName #>") - End If -<#+ - } - - internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) - { -#> - <#= instanceName #>.<#= propertyName #> = <#= parameterName #> -<#+ - } - - internal override void WriteMethodEndForStaticCreateMethod(string instanceName) - { -#> - Return <#= instanceName #> - End Function -<#+ - } - - internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) - { -#> - ''' - '''There are no comments for Property <#= propertyName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) - { -#> - ")> _ -<#+ - } -#> - Public Property <#= fixedPropertyName #>() As <#= propertyType #> - Get - Return Me.<#= privatePropertyName #> - End Get - Set - Me.On<#= propertyName #>Changing(value) - Me.<#= privatePropertyName #> = value - Me.On<#= propertyName #>Changed -<#+ - if (writeOnPropertyChanged) - { -#> - Me.OnPropertyChanged("<#= originalPropertyName #>") -<#+ - } -#> - End Set - End Property - ")> _ -<#+ - string constructorString = string.Empty; - if (!string.IsNullOrEmpty(propertyInitializationValue)) - { - constructorString = " = " + propertyInitializationValue; - } -#> - Private <#= privatePropertyName #> As <#= propertyType #><#= constructorString #> - Partial Private Sub On<#= propertyName #>Changing(ByVal value As <#= propertyType #>) - End Sub - Partial Private Sub On<#= propertyName #>Changed() - End Sub -<#+ - } - - internal override void WriteINotifyPropertyChangedImplementation() - { -#> - ''' - ''' This event is raised when the value of the property is changed - ''' - ")> _ - Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements Global.System.ComponentModel.INotifyPropertyChanged.PropertyChanged - ''' - ''' The value of the property is changed - ''' - ''' property name - ")> _ - Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) - If (Not (Me.PropertyChangedEvent) Is Nothing) Then - RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property])) - End If - End Sub -<#+ - } - - internal override void WriteClassEndForStructuredType() - { -#> - End Class -<#+ - } - - internal override void WriteEnumFlags() - { -#> - -<#+ - } - - internal override void WriteSummaryCommentForEnumType(string enumName) - { -#> - ''' - '''There are no comments for <#= enumName #> in the schema. - ''' -<#+ - } - - internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Enum <#= enumName #><#= underlyingType #> -<#+ - } - - internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - <#= member #> -<#+ - } - - internal override void WriteEnumEnd() - { -#> - End Enum -<#+ - } - - internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - Return Me.CreateFunctionQuery(Of <#= returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #> <#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - Dim requestUri As Global.System.Uri = Nothing - Context.TryGetUri(Me, requestUri) - Return Me.Context.CreateFunctionQuery(Of <#= returnTypeName #>)("", String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))) + "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - Dim requestUri As Global.System.Uri = Nothing - Context.TryGetUri(Me, requestUri) - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.Context.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)(String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))), "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> - Return New <#= returnTypeName #>(Me, Me.BaseUri.OriginalString.Trim("/"C) + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> - Dim resource As Global.Microsoft.OData.Client.EntityDescriptor = Context.EntityTracker.TryGetEntityDescriptor(Me) - If resource Is Nothing Then - Throw New Global.System.Exception("cannot find entity") - End If - - Return New <#= returnTypeName #>(Me.Context, resource.EditLink.OriginalString.Trim("/"C) + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteExtensionMethodsStart() - { -#> - ''' - ''' Class containing all extension methods - ''' - Public Module ExtensionMethods -<#+ - } - - internal override void WriteExtensionMethodsEnd() - { -#> - End Module -<#+ - } - - internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) - { -#> - ''' - ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - ''' - ''' source entity set - ''' dictionary with the names and values of keys - - Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), ByVal keys As Global.System.Collections.Generic.Dictionary(Of String, Object)) As <#= returnTypeName #> - Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) - End Function - ''' - ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - ''' - ''' source entity set -<#+ - foreach (var key in keys) - { -#> - ''' The value of <#= key #> -<#+ - } -#> - - Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), - <#= keyParameters #>) As <#= returnTypeName #> - Dim keys As Global.System.Collections.Generic.Dictionary(Of String, Object) = New Global.System.Collections.Generic.Dictionary(Of String, Object)() From - { - <#= keyDictionaryItems #> - } - Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) - End Function -<#+ - } - - internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) - { -#> - ''' - ''' Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> - ''' - ''' source entity - - Public Function CastTo<#= derivedTypeName #>(ByVal source As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= baseTypeName #>)) As <#= returnTypeName #> - Dim query As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= derivedTypeFullName #>) = source.CastTo(Of <#= derivedTypeFullName #>)() - Return New <#= returnTypeName #>(source.Context, query.GetPath(Nothing)) - End Function -<#+ - } - - internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - - Return source.CreateFunctionQuery(Of <#= returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= actionName #>(ByVal source As <#= boundSourceType #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) As <#= returnTypeName #> - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - Return New <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteNamespaceEnd() - { -#> -End Namespace -<#+ - } -} -#> +<# +/* +OData Client T4 Template ver. #VersionNumber# +Copyright (c) Microsoft Corporation +All rights reserved. +MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#> +<#@ template debug="true" hostSpecific="true" visibility="internal" linePragmas="false"#> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.IO.dll" #> +<#@ Assembly Name="System.Runtime.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ Assembly Name="System.Xml.Linq.dll" #> +<#@ Assembly Name="System.Xml.ReaderWriter.dll" #> +<#@ Assembly Name="System.Windows.Forms.dll" #> +<#@ Assembly Name="Microsoft.OData.Client.dll" #> +<#@ Assembly Name="Microsoft.OData.Core.dll" #> +<#@ Assembly Name="Microsoft.OData.Edm.dll" #> +<#@ Assembly Name="Microsoft.Spatial.dll" #> +<#@ Import Namespace="System" #> +<#@ Import Namespace="System.IO" #> +<#@ Import Namespace="System.Diagnostics" #> +<#@ Import Namespace="System.Globalization" #> +<#@ Import Namespace="System.Linq" #> +<#@ Import Namespace="System.Xml"#> +<#@ Import Namespace="System.Xml.Linq" #> +<#@ Import Namespace="System.Collections.Generic" #> +<#@ Import Namespace="Microsoft.OData.Edm.Csdl" #> +<#@ Import Namespace="Microsoft.OData.Edm" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.V1" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.Community.V1" #> +<#@ Import Namespace="System.Text"#> +<#@ Import Namespace="System.Net"#> +<# + CodeGenerationContext context; + if (!string.IsNullOrWhiteSpace(this.Edmx)) + { + context = new CodeGenerationContext(this.Edmx, this.NamespacePrefix) + { + UseDataServiceCollection = this.UseDataServiceCollection, + TargetLanguage = this.TargetLanguage, + EnableNamingAlias = this.EnableNamingAlias, + TempFilePath = this.TempFilePath, + IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, + GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, + DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName + }; + } + else + { + this.ApplyParametersFromCommandLine(); + if (string.IsNullOrEmpty(metadataDocumentUri)) + { + this.ApplyParametersFromConfigurationClass(); + } + + context = new CodeGenerationContext(new Uri(this.MetadataDocumentUri, UriKind.Absolute), this.NamespacePrefix) + { + UseDataServiceCollection = this.UseDataServiceCollection, + TargetLanguage = this.TargetLanguage, + EnableNamingAlias = this.EnableNamingAlias, + TempFilePath = this.TempFilePath, + IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, + GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, + DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName + }; + } + + if (this.GetReferencedModelReaderFunc != null) + { + context.GetReferencedModelReaderFunc = this.GetReferencedModelReaderFunc; + } + + ODataClientTemplate template; + switch(this.TargetLanguage) + { + case LanguageOption.CSharp: + template = new ODataClientCSharpTemplate(context); + break; + case LanguageOption.VB: + template = new ODataClientVBTemplate(context); + break; + + default: + throw new NotSupportedException(string.Format("Code gen for the target language '{0}' is not supported.", this.TargetLanguage.ToString())); + } + +#><#=template.TransformText()#><# + foreach (string warning in context.Warnings) + { + this.Warning(warning); + } +#><#+ +/// +/// The string for the edmx content. +/// +public string Edmx +{ + get; + set; +} + +/// +/// The Uri string to the metadata document. +/// +public string MetadataDocumentUri +{ + get + { + return this.metadataDocumentUri; + } + + set + { + value = Uri.UnescapeDataString(value); + Uri uri; + if (!Uri.TryCreate(value, UriKind.Absolute, out uri)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" is not a valid MetadataDocumentUri because is it not a valid absolute Uri. The MetadataDocumentUri must be set to an absolute Uri referencing the $metadata endpoint of an OData service.", value)); + } + + if (uri.Scheme == "http" || uri.Scheme == "https") + { + value = uri.Scheme + "://" + uri.Authority + uri.AbsolutePath; + value = value.TrimEnd('/'); + if (!value.EndsWith("$metadata")) + { + value += "/$metadata"; + } + } + + this.metadataDocumentUri = value; + } +} + +private string metadataDocumentUri; + +/// +/// The Func to get referenced model's XmlReader. Must have value when the this.Edmx xml or this.metadataDocumentUri's model has referneced model. +/// +public Func GetReferencedModelReaderFunc +{ + get; + set; +} + +/// +/// The NamespacePrefix is used as the only namespace for types in the same namespace as the default container, +/// and as a prefix for the namespace from the model for everything else. If this argument is null, the +/// namespaces from the model are used for all types. +/// +public string NamespacePrefix +{ + get + { + return this.namespacePrefix; + } + + set + { + if (string.IsNullOrWhiteSpace(value)) + { + this.namespacePrefix = null; + } + else + { + this.namespacePrefix = value; + } + } +} + +private string namespacePrefix; + +/// +/// true to use DataServiceCollection in the generated code, false otherwise. +/// +public bool UseDataServiceCollection +{ + get; + set; +} + +/// +/// Specifies which specific .Net Framework language the generated code will target. +/// +public LanguageOption TargetLanguage +{ + get; + set; +} + +/// +/// true to use Upper camel case for all class and property names, false otherwise. +/// +public bool EnableNamingAlias +{ + get; + set; +} + +/// +/// The path for the temporary file where the metadata xml document can be stored. +/// +public string TempFilePath +{ + get; + set; +} + +/// +/// true to ignore unknown elements or attributes in metadata, false otherwise. +/// +public bool IgnoreUnexpectedElementsAndAttributes +{ + get; + set; +} + + /// + /// true to generate open type property dirctionary, false otherwise. + /// + public bool GenerateDynamicPropertiesCollection + { + get; + set; + } + + /// + /// Name of the OpenType dictionary property + /// + public string DynamicPropertiesCollectionName + { + get; + set; + } + +/// +/// Generate code targeting a specific .Net Framework language. +/// +public enum LanguageOption +{ + /// Generate code for C# language. + CSharp = 0, + + /// Generate code for Visual Basic language. + VB = 1, +} + +/// +/// Set the UseDataServiceCollection property with the given value. +/// +/// The value to set. +public void ValidateAndSetUseDataServiceCollectionFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the UseDataServiceCollection parameter because it is not a valid boolean value.", stringValue)); + } + + this.UseDataServiceCollection = boolValue; +} + +/// +/// Tries to set the TargetLanguage property with the given value. +/// +/// The value to set. +public void ValidateAndSetTargetLanguageFromString(string stringValue) +{ + LanguageOption option; + if (!Enum.TryParse(stringValue, true, out option)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the TargetLanguage parameter because it is not a valid LanguageOption. The supported LanguageOptions are \"CSharp\" and \"VB\".", stringValue)); + } + + this.TargetLanguage = option; +} + +/// +/// Set the EnableNamingAlias property with the given value. +/// +/// The value to set. +public void ValidateAndSetEnableNamingAliasFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the EnableNamingAlias parameter because it is not a valid boolean value.", stringValue)); + } + + this.EnableNamingAlias = boolValue; +} + +/// +/// Set the IgnoreUnexpectedElementsAndAttributes property with the given value. +/// +/// The value to set. +public void ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the IgnoreUnexpectedElementsAndAttributes parameter because it is not a valid boolean value.", stringValue)); + } + + this.IgnoreUnexpectedElementsAndAttributes = boolValue; +} + +/// +/// Set the GenerateDynamicPropertiesCollection property with the given value. +/// +/// The value to set. +public void ValidateAndSetGenerateDynamicPropertiesCollectionFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the GenerateDynamicPropertiesCollection parameter because it is not a valid boolean value.", stringValue)); + } + + this.GenerateDynamicPropertiesCollection = boolValue; +} + +/// +/// Reads the parameter values from the Configuration class and applies them. +/// +private void ApplyParametersFromConfigurationClass() +{ + this.MetadataDocumentUri = Configuration.MetadataDocumentUri; + this.NamespacePrefix = Configuration.NamespacePrefix; + this.UseDataServiceCollection = Configuration.UseDataServiceCollection; + this.ValidateAndSetTargetLanguageFromString(Configuration.TargetLanguage); + this.EnableNamingAlias = Configuration.EnableNamingAlias; + this.TempFilePath = Configuration.TempFilePath; + this.IgnoreUnexpectedElementsAndAttributes = Configuration.IgnoreUnexpectedElementsAndAttributes; + this.GenerateDynamicPropertiesCollection = Configuration.GenerateDynamicPropertiesCollection; + this.DynamicPropertiesCollectionName = Configuration.DynamicPropertiesCollectionName; +} + +/// +/// Reads the parameter values from the command line (TextTransform.exe) and applies them. +/// +private void ApplyParametersFromCommandLine() +{ + if (this.Host == null) + { + return; + } + + string metadataDocumentUri = this.Host.ResolveParameterValue("notempty", "notempty", "MetadataDocumentUri"); + if (!string.IsNullOrEmpty(metadataDocumentUri)) + { + this.MetadataDocumentUri = metadataDocumentUri; + } + + string namespacePrefix = this.Host.ResolveParameterValue("notempty", "notempty", "NamespacePrefix"); + if (!string.IsNullOrEmpty(namespacePrefix)) + { + this.NamespacePrefix = namespacePrefix; + } + + string useDataServiceCollection = this.Host.ResolveParameterValue("notempty", "notempty", "UseDataServiceCollection"); + if (!string.IsNullOrEmpty(useDataServiceCollection)) + { + this.ValidateAndSetUseDataServiceCollectionFromString(useDataServiceCollection); + } + + string targetLanguage = this.Host.ResolveParameterValue("notempty", "notempty", "TargetLanguage"); + if (!string.IsNullOrEmpty(targetLanguage)) + { + this.ValidateAndSetTargetLanguageFromString(targetLanguage); + } + + string enableNamingAlias = this.Host.ResolveParameterValue("notempty", "notempty", "EnableNamingAlias"); + if (!string.IsNullOrEmpty(enableNamingAlias)) + { + this.ValidateAndSetEnableNamingAliasFromString(enableNamingAlias); + } + + string ignoreUnexpectedElementsAndAttributes = this.Host.ResolveParameterValue("notempty", "notempty", "IgnoreUnexpectedElementsAndAttributes"); + if (!string.IsNullOrEmpty(ignoreUnexpectedElementsAndAttributes)) + { + this.ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(ignoreUnexpectedElementsAndAttributes); + } + + string generateDynamicPropertiesCollection = this.Host.ResolveParameterValue("notempty", "notempty", "GenerateDynamicPropertiesCollection"); + if (!string.IsNullOrEmpty(generateDynamicPropertiesCollection)) + { + this.ValidateAndSetGenerateDynamicPropertiesCollectionFromString(generateDynamicPropertiesCollection); + } + + string dynamicPropertiesCollectionName = this.Host.ResolveParameterValue("notempty", "notempty", "DynamicPropertiesCollectionName"); + if (!string.IsNullOrEmpty(dynamicPropertiesCollectionName)) + { + this.DynamicPropertiesCollectionName = dynamicPropertiesCollectionName; + } +} + +/// +/// Context object to provide the model and configuration info to the code generator. +/// +public class CodeGenerationContext +{ + /// + /// The namespace of the term to use when building annotations for indicating the conventions used. + /// + private const string ConventionTermNamespace = "Com.Microsoft.OData.Service.Conventions.V1"; + + /// + /// The name of the term to use when building annotations for indicating the conventions used. + /// + private const string ConventionTermName = "UrlConventions"; + + /// + /// The string value for indicating that the key-as-segment convention is being used in annotations and headers. + /// + private const string KeyAsSegmentConventionName = "KeyAsSegment"; + + /// + /// The XElement for the edmx + /// + private readonly XElement edmx; + + /// + /// The namespacePrefix is used as the only namespace in generated code when there's only one schema in edm model, + /// and as a prefix for the namespace from the model with multiple schemas. If this argument is null, the + /// namespaces from the model are used for all types. + /// + private readonly string namespacePrefix; + + /// + /// The EdmModel to generate code for. + /// + private IEdmModel edmModel; + + /// + /// The array of namespaces in the current edm model. + /// + private string[] namespacesInModel; + + /// + /// The array of warnings occured when parsing edm model. + /// + private string[] warnings; + + /// + /// true if the model contains any structural type with inheritance, false otherwise. + /// + private bool? modelHasInheritance; + + /// + /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. + /// Otherwise this is an empty dictionary. + /// + private Dictionary namespaceMap; + + /// + /// Maps the element type of a navigation source to the navigation source. + /// + private Dictionary> elementTypeToNavigationSourceMap; + + /// + /// HashSet contains the pair of Names and Namespaces of EntityContainers using KeyAsSegment url convention + /// + private HashSet keyAsSegmentContainers; + + /// + /// Constructs an instance of . + /// + /// The Uri to the metadata document. The supported scheme are File, http and https. + public CodeGenerationContext(Uri metadataUri, string namespacePrefix) + : this(GetEdmxStringFromMetadataPath(metadataUri), namespacePrefix) + { + } + + /// + /// Constructs an instance of . + /// + /// The string for the edmx. + /// The namespacePrefix is used as the only namespace in generated code + /// when there's only one schema in edm model, and as a prefix for the namespace from the model with multiple + /// schemas. If this argument is null, the namespaces from the model are used for all types. + public CodeGenerationContext(string edmx, string namespacePrefix) + { + this.edmx = XElement.Parse(edmx); + this.namespacePrefix = namespacePrefix; + } + + /// + /// The EdmModel to generate code for. + /// + public XElement Edmx + { + get { return this.edmx; } + } + + /// + /// The EdmModel to generate code for. + /// + public IEdmModel EdmModel + { + get + { + if (this.edmModel == null) + { + Debug.Assert(this.edmx != null, "this.edmx != null"); + + IEnumerable errors; + CsdlReaderSettings edmxReaderSettings = new CsdlReaderSettings() + { + GetReferencedModelReaderFunc = this.GetReferencedModelReaderFuncWrapper, + IgnoreUnexpectedAttributesAndElements = this.IgnoreUnexpectedElementsAndAttributes + }; + if (!CsdlReader.TryParse(this.edmx.CreateReader(ReaderOptions.None), Enumerable.Empty(), edmxReaderSettings, out this.edmModel, out errors)) + { + Debug.Assert(errors != null, "errors != null"); + throw new InvalidOperationException(errors.FirstOrDefault().ErrorMessage); + } + else if (this.IgnoreUnexpectedElementsAndAttributes) + { + if (errors != null && errors.Any()) + { + this.warnings = errors.Select(e => e.ErrorMessage).ToArray(); + } + } + } + + return this.edmModel; + } + } + + /// + /// The func for user code to overwrite and provide referenced model's XmlReader. + /// + public Func GetReferencedModelReaderFunc + { + get { return getReferencedModelReaderFunc; } + set { this.getReferencedModelReaderFunc = value; } + } + + /// + /// Basic setting for XmlReader. + /// + private static readonly XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true }; + + /// + /// The func for user code to overwrite and provide referenced model's XmlReader. + /// + private Func getReferencedModelReaderFunc = uri => XmlReader.Create(GetEdmxStreamFromUri(uri), settings); + + /// + /// The Wrapper func for user code to overwrite and provide referenced model's stream. + /// + public Func GetReferencedModelReaderFuncWrapper + { + get + { + return (uri) => + { + using (XmlReader reader = GetReferencedModelReaderFunc(uri)) + { + if (reader == null) + { + return null; + } + + XElement element = XElement.Load(reader); + if (this.ReferencesMap == null) + { + this.ReferencesMap = new Dictionary(); + } + + this.ReferencesMap.Add(uri, element); + return element.CreateReader(ReaderOptions.None); + } + }; + } + } + + /// + /// Dictionary that stores uri and referenced xml mapping. + /// + public Dictionary ReferencesMap + { + get; + set; + } + + /// + /// The array of namespaces in the current edm model. + /// + public string[] NamespacesInModel + { + get + { + if (this.namespacesInModel == null) + { + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + this.namespacesInModel = GetElementsFromModelTree(this.EdmModel, (m) => m.SchemaElements.Select(e => e.Namespace)).Distinct().ToArray(); + } + + return this.namespacesInModel; + } + } + + /// + /// The array of warnings occured when parsing edm model. + /// + public string[] Warnings + { + get { return this.warnings ?? (this.warnings = new string[] {}); } + } + + /// + /// true if the model contains any structural type with inheritance, false otherwise. + /// + public bool ModelHasInheritance + { + get + { + if (!this.modelHasInheritance.HasValue) + { + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + this.modelHasInheritance = this.EdmModel.SchemaElementsAcrossModels() + .OfType().Any(t => !t.FullTypeName().StartsWith("Org.OData.Authorization.V1") && t.BaseType != null); + } + + return this.modelHasInheritance.Value; + } + } + + /// + /// true if we need to generate the ResolveNameFromType method, false otherwise. + /// + public bool NeedResolveNameFromType + { + get { return this.ModelHasInheritance || this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } + } + + /// + /// true if we need to generate the ResolveTypeFromName method, false otherwise. + /// + public bool NeedResolveTypeFromName + { + get { return this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } + } + + /// + /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. + /// Otherwise this is an empty dictionary. + /// + public Dictionary NamespaceMap + { + get + { + if (this.namespaceMap == null) + { + if (!string.IsNullOrEmpty(this.namespacePrefix)) + { + if (this.NamespacesInModel.Count() == 1) + { + IEdmEntityContainer container = this.EdmModel.EntityContainer; + string containerNamespace = container == null ? null : container.Namespace; + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => ns == containerNamespace ? + this.namespacePrefix : + this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); + } + else + { + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); + } + } + else if (this.EnableNamingAlias) + { + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => Customization.CustomizeNamespace(ns)); + } + else + { + this.namespaceMap = new Dictionary(); + } + } + + return this.namespaceMap; + } + } + + /// + /// true to use DataServiceCollection in the generated code, false otherwise. + /// + public bool UseDataServiceCollection + { + get; + set; + } + + /// + /// Specifies which specific .Net Framework language the generated code will target. + /// + public LanguageOption TargetLanguage + { + get; + set; + } + + /// + /// The path for the temporary file where the metadata xml document can be stored. + /// + public string TempFilePath + { + get; + set; + } + /// + /// true to use Upper camel case for all class and property names, false otherwise. + /// + public bool EnableNamingAlias + { + get; + set; + } + + /// + /// true to ignore unknown elements or attributes in metadata, false otherwise. + /// + public bool IgnoreUnexpectedElementsAndAttributes + { + get; + set; + } + + /// + /// true to generate open type property dirctionary, false otherwise. + /// + public bool GenerateDynamicPropertiesCollection + { + get; + set; + } + + /// + /// Name of the OpenType dictionary property + /// + public string DynamicPropertiesCollectionName + { + get; + set; + } + + /// + /// Maps the element type of an entity set to the entity set. + /// + public Dictionary> ElementTypeToNavigationSourceMap + { + get + { + return this.elementTypeToNavigationSourceMap ?? (this.elementTypeToNavigationSourceMap = new Dictionary>(EqualityComparer.Default)); + } + } + + /// + /// true if this EntityContainer need to set the UrlConvention to KeyAsSegment, false otherwise. + /// + public bool UseKeyAsSegmentUrlConvention(IEdmEntityContainer currentContainer) + { + if (this.keyAsSegmentContainers == null) + { + this.keyAsSegmentContainers = new HashSet(); + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + IEnumerable annotations = this.EdmModel.VocabularyAnnotations; + foreach(IEdmVocabularyAnnotation valueAnnotation in annotations) + { + IEdmEntityContainer container = valueAnnotation.Target as IEdmEntityContainer; + IEdmTerm valueTerm = valueAnnotation.Term; + IEdmStringConstantExpression expression = valueAnnotation.Value as IEdmStringConstantExpression; + if (container != null && valueTerm != null && expression != null) + { + if (valueTerm.Namespace == ConventionTermNamespace && + valueTerm.Name == ConventionTermName && + expression.Value == KeyAsSegmentConventionName) + { + this.keyAsSegmentContainers.Add(container.FullName()); + } + } + } + } + + return this.keyAsSegmentContainers.Contains(currentContainer.FullName()); + } + + /// + /// Gets the enumeration of schema elements with the given namespace. + /// + /// The namespace of the schema elements to get. + /// The enumeration of schema elements with the given namespace. + public IEnumerable GetSchemaElements(string ns) + { + Debug.Assert(ns != null, "ns != null"); + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + return GetElementsFromModelTree(this.EdmModel, m => m.SchemaElements.Where(e => e.Namespace == ns)); + } + + /// + /// Gets the namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. + /// + /// The schema element to get the full name for. + /// The fixed name of this schemaElement. + /// The current code generate template. + /// The namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. + public string GetPrefixedFullName(IEdmSchemaElement schemaElement, string schemaElementFixedName, ODataClientTemplate template, bool needGlobalPrefix = true) + { + if (schemaElement == null) + { + return null; + } + + return this.GetPrefixedNamespace(schemaElement.Namespace, template, true, needGlobalPrefix) + "." + schemaElementFixedName; + } + + /// + /// Gets the prefixed namespace for the given . + /// + /// The namespace without the prefix. + /// The current code generate template. + /// The flag indicates whether the namespace need to be fixed now. + /// The flag indicates whether the namespace need to be added by gloabal prefix. + /// The prefixed namespace for the given . + public string GetPrefixedNamespace(string ns, ODataClientTemplate template, bool needFix, bool needGlobalPrefix) + { + if (ns == null) + { + return null; + } + + string prefixedNamespace; + if (!this.NamespaceMap.TryGetValue(ns, out prefixedNamespace)) + { + prefixedNamespace = ns; + } + + if (needFix) + { + string[] segments = prefixedNamespace.Split('.'); + prefixedNamespace = string.Empty; + int n = segments.Length; + for (int i = 0; i < n; ++i) + { + if (template.LanguageKeywords.Contains(segments[i])) + { + prefixedNamespace += string.Format(template.FixPattern, segments[i]); + } + else + { + prefixedNamespace += segments[i]; + } + + prefixedNamespace += (i == n - 1 ? string.Empty : "."); + } + } + + if (needGlobalPrefix) + { + prefixedNamespace = template.GlobalPrefix + prefixedNamespace; + } + + return prefixedNamespace; + } + + /// + /// Reads the edmx string from a file path or a http/https path. + /// + /// The Uri to the metadata document. The supported scheme are File, http and https. + private static string GetEdmxStringFromMetadataPath(Uri metadataUri) + { + string content = null; + using (StreamReader streamReader = new StreamReader(GetEdmxStreamFromUri(metadataUri))) + { + content = streamReader.ReadToEnd(); + } + + return content; + } + + /// + /// Get the metadata stream from a file path or a http/https path. + /// + /// The Uri to the stream. The supported scheme are File, http and https. + private static Stream GetEdmxStreamFromUri(Uri metadataUri) + { + Debug.Assert(metadataUri != null, "metadataUri != null"); + Stream metadataStream = null; + if (metadataUri.Scheme == "file") + { + metadataStream = new FileStream(Uri.UnescapeDataString(metadataUri.AbsolutePath), FileMode.Open, FileAccess.Read); + } + else if (metadataUri.Scheme == "http" || metadataUri.Scheme == "https") + { + try + { + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(metadataUri); + WebResponse webResponse = webRequest.GetResponse(); + metadataStream = webResponse.GetResponseStream(); + } + catch (WebException e) + { + HttpWebResponse webResponse = e.Response as HttpWebResponse; + if (webResponse != null && webResponse.StatusCode == HttpStatusCode.Unauthorized) + { + throw new WebException("Failed to access the metadata document. The OData service requires authentication for accessing it. Please download the metadata, store it into a local file, and set the value of “MetadataDocumentUri” in the .odata.config file to the file path. After that, run custom tool again to generate the OData Client code."); + } + else + { + throw e; + } + } + } + else + { + throw new ArgumentException("Only file, http, https schemes are supported for paths to metadata source locations."); + } + + return metadataStream; + } + + private static IEnumerable GetElementsFromModelTree(IEdmModel mainModel, Func> getElementFromOneModelFunc) + { + List ret = new List(); + if(mainModel is EdmCoreModel || mainModel.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null) + { + return ret; + } + + ret.AddRange(getElementFromOneModelFunc(mainModel)); + foreach (var tmp in mainModel.ReferencedModels) + { + if (tmp is EdmCoreModel || + tmp.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null || + tmp.FindDeclaredTerm(CapabilitiesVocabularyConstants.ChangeTracking) != null || + tmp.FindDeclaredTerm(AlternateKeysVocabularyConstants.AlternateKeys) != null || + tmp.FindDeclaredTerm("Org.OData.Authorization.V1.Authorizations") != null) + { + continue; + } + + ret.AddRange(getElementFromOneModelFunc(tmp)); + } + + return ret; + } +} + +/// +/// The template class to generate the OData client code. +/// +public abstract class ODataClientTemplate : TemplateBase +{ + protected const string T4Version = "#VersionNumber#"; + + /// + /// The code generation context. + /// + protected readonly CodeGenerationContext context; + + /// + /// The Dictionary to store identifier mappings when there are duplicate names between properties and Entity/Complex types + /// + protected Dictionary IdentifierMappings = new Dictionary(StringComparer.Ordinal); + + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The code generation context. + public ODataClientTemplate(CodeGenerationContext context) + { + this.context = context; + } + + internal string SingleSuffix + { + get { return "Single"; } + } + + #region Get Language specific keyword names. + internal abstract string GlobalPrefix { get; } + internal abstract string SystemTypeTypeName { get; } + internal abstract string AbstractModifier { get; } + internal abstract string DataServiceActionQueryTypeName { get; } + internal abstract string DataServiceActionQuerySingleOfTStructureTemplate { get; } + internal abstract string DataServiceActionQueryOfTStructureTemplate { get; } + internal abstract string NotifyPropertyChangedModifier { get; } + internal abstract string ClassInheritMarker { get; } + internal abstract string ParameterSeparator { get; } + internal abstract string KeyParameterSeparator { get; } + internal abstract string KeyDictionaryItemSeparator { get; } + internal abstract string SystemNullableStructureTemplate { get; } + internal abstract string ICollectionOfTStructureTemplate { get; } + internal abstract string DataServiceCollectionStructureTemplate { get; } + internal abstract string DataServiceQueryStructureTemplate { get; } + internal abstract string DataServiceQuerySingleStructureTemplate { get; } + internal abstract string ObservableCollectionStructureTemplate { get; } + internal abstract string ObjectModelCollectionStructureTemplate { get; } + internal abstract string DataServiceCollectionConstructorParameters { get; } + internal abstract string NewModifier { get; } + internal abstract string GeoTypeInitializePattern { get; } + internal abstract string Int32TypeName { get; } + internal abstract string ObjectTypeName { get; } + internal abstract string StringTypeName { get; } + internal abstract string BinaryTypeName { get; } + internal abstract string DecimalTypeName { get; } + internal abstract string Int16TypeName { get; } + internal abstract string SingleTypeName { get; } + internal abstract string BooleanTypeName { get; } + internal abstract string DoubleTypeName { get; } + internal abstract string GuidTypeName { get; } + internal abstract string ByteTypeName { get; } + internal abstract string Int64TypeName { get; } + internal abstract string SByteTypeName { get; } + internal abstract string DataServiceStreamLinkTypeName { get; } + internal abstract string GeographyTypeName { get; } + internal abstract string GeographyPointTypeName { get; } + internal abstract string GeographyLineStringTypeName { get; } + internal abstract string GeographyPolygonTypeName { get; } + internal abstract string GeographyCollectionTypeName { get; } + internal abstract string GeographyMultiPolygonTypeName { get; } + internal abstract string GeographyMultiLineStringTypeName { get; } + internal abstract string GeographyMultiPointTypeName { get; } + internal abstract string GeometryTypeName { get; } + internal abstract string GeometryPointTypeName { get; } + internal abstract string GeometryLineStringTypeName { get; } + internal abstract string GeometryPolygonTypeName { get; } + internal abstract string GeometryCollectionTypeName { get; } + internal abstract string GeometryMultiPolygonTypeName { get; } + internal abstract string GeometryMultiLineStringTypeName { get; } + internal abstract string GeometryMultiPointTypeName { get; } + internal abstract string DateTypeName { get; } + internal abstract string DateTimeOffsetTypeName { get; } + internal abstract string DurationTypeName { get; } + internal abstract string TimeOfDayTypeName { get; } + internal abstract string XmlConvertClassName { get; } + internal abstract string EnumTypeName { get; } + internal abstract string DictionaryTypeName { get; } + internal abstract HashSet LanguageKeywords { get; } + internal abstract string FixPattern { get; } + internal abstract string EnumUnderlyingTypeMarker { get; } + internal abstract string ConstantExpressionConstructorWithType { get; } + internal abstract string TypeofFormatter { get; } + internal abstract string UriOperationParameterConstructor { get; } + internal abstract string UriEntityOperationParameterConstructor { get; } + internal abstract string BodyOperationParameterConstructor { get; } + internal abstract string DictionaryConstructor { get; } + internal abstract string BaseEntityType { get; } + internal abstract string OverloadsModifier { get; } + internal abstract string ODataVersion { get; } + internal abstract string ParameterDeclarationTemplate { get; } + internal abstract string DictionaryItemConstructor { get; } + #endregion Get Language specific keyword names. + + #region Language specific write methods. + internal abstract void WriteFileHeader(); + internal abstract void WriteNamespaceStart(string fullNamespace); + internal abstract void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName); + internal abstract void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName); + internal abstract void WriteKeyAsSegmentUrlConvention(); + internal abstract void WriteInitializeResolveName(); + internal abstract void WriteInitializeResolveType(); + internal abstract void WriteClassEndForEntityContainerConstructor(); + internal abstract void WriteMethodStartForResolveTypeFromName(); + internal abstract void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace); + internal abstract void WriteMethodEndForResolveTypeFromName(); + internal abstract void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace); + internal abstract void WriteResolveType(string fullNamespace, string languageDependentNamespace); + internal abstract void WriteMethodEndForResolveNameFromType(bool modelHasInheritance); + internal abstract void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext = true); + internal abstract void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext = true); + internal abstract void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName); + internal abstract void WriteGeneratedEdmModel(string escapedEdmxString); + internal abstract void WriteClassEndForEntityContainer(); + internal abstract void WriteSummaryCommentForStructuredType(string typeName); + internal abstract void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString); + internal abstract void WriteEntityTypeAttribute(); + internal abstract void WriteEntitySetAttribute(string entitySetName); + internal abstract void WriteEntityHasStreamAttribute(); + internal abstract void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName); + internal abstract void WriteSummaryCommentForStaticCreateMethod(string typeName); + internal abstract void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName); + internal abstract void WriteDeclarationStartForStaticCreateMethod(string typeName,string fixedTypeName ); + internal abstract void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater); + internal abstract void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName); + internal abstract void WriteParameterNullCheckForStaticCreateMethod(string parameterName); + internal abstract void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName); + internal abstract void WriteMethodEndForStaticCreateMethod(string instanceName); + internal abstract void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged); + internal abstract void WriteINotifyPropertyChangedImplementation(); + internal abstract void WriteClassEndForStructuredType(); + internal abstract void WriteNamespaceEnd(); + internal abstract void WriteEnumFlags(); + internal abstract void WriteSummaryCommentForEnumType(string enumName); + internal abstract void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType); + internal abstract void WriteMemberForEnumType(string member, string originalMemberName, bool last); + internal abstract void WriteEnumEnd(); + internal abstract void WritePropertyRootNamespace(string containerName, string fullNamespace); + internal abstract void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues); + internal abstract void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues); + internal abstract void WriteConstructorForSingleType(string singleTypeName, string baseTypeName); + internal abstract void WriteExtensionMethodsStart(); + internal abstract void WriteExtensionMethodsEnd(); + internal abstract void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems); + internal abstract void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName); + internal abstract void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues); + #endregion Language specific write methods. + + internal HashSet ClrReferenceTypes { get { + if (clrReferenceTypes == null) + { + clrReferenceTypes = new HashSet() + { + EdmPrimitiveTypeKind.String, EdmPrimitiveTypeKind.Binary, EdmPrimitiveTypeKind.Geography, EdmPrimitiveTypeKind.Stream, + EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeographyPolygon, + EdmPrimitiveTypeKind.GeographyCollection, EdmPrimitiveTypeKind.GeographyMultiPolygon, EdmPrimitiveTypeKind.GeographyMultiLineString, + EdmPrimitiveTypeKind.GeographyMultiPoint, EdmPrimitiveTypeKind.Geometry, EdmPrimitiveTypeKind.GeometryPoint, + EdmPrimitiveTypeKind.GeometryLineString, EdmPrimitiveTypeKind.GeometryPolygon, EdmPrimitiveTypeKind.GeometryCollection, + EdmPrimitiveTypeKind.GeometryMultiPolygon, EdmPrimitiveTypeKind.GeometryMultiLineString, EdmPrimitiveTypeKind.GeometryMultiPoint + }; + } + return clrReferenceTypes; + } } + private HashSet clrReferenceTypes; + + /// + /// Generates code for the OData client. + /// + /// The generated code for the OData client. + public override string TransformText() + { + this.WriteFileHeader(); + this.WriteNamespaces(); + return this.GenerationEnvironment.ToString(); + } + + internal void WriteNamespaces() + { + foreach(string fullNamespace in context.NamespacesInModel) + { + this.WriteNamespace(fullNamespace); + } + } + + internal void WriteNamespace(string fullNamespace) + { + this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false)); + + IEdmSchemaElement[] schemaElements = this.context.GetSchemaElements(fullNamespace).ToArray(); + if (schemaElements.OfType().Any()) { + IEdmEntityContainer container = schemaElements.OfType().Single(); + this.WriteEntityContainer(container, fullNamespace); + } + + Dictionary> boundOperationsMap = new Dictionary>(); + foreach (IEdmOperation operation in schemaElements.OfType()) + { + if (operation.IsBound) + { + IEdmType edmType = operation.Parameters.First().Type.Definition; + IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType; + if (edmStructuredType != null) + { + List operationList; + if (!boundOperationsMap.TryGetValue(edmStructuredType, out operationList)) + { + operationList = new List(); + } + + operationList.Add(operation); + boundOperationsMap[edmStructuredType] = operationList; + } + } + } + + Dictionary> structuredBaseTypeMap = new Dictionary>(); + foreach(IEdmSchemaType type in schemaElements.OfType()) + { + IEdmEnumType enumType = type as IEdmEnumType; + if (enumType != null) + { + this.WriteEnumType(enumType); + } + else + { + IEdmComplexType complexType = type as IEdmComplexType; + if (complexType != null) + { + this.WriteComplexType(complexType, boundOperationsMap); + } + else + { + IEdmEntityType entityType = type as IEdmEntityType; + this.WriteEntityType(entityType, boundOperationsMap); + } + + IEdmStructuredType structuredType = type as IEdmStructuredType; + if (structuredType.BaseType != null) + { + List derivedTypes; + if (!structuredBaseTypeMap.TryGetValue(structuredType.BaseType, out derivedTypes)) + { + structuredBaseTypeMap[structuredType.BaseType] = new List(); + } + + structuredBaseTypeMap[structuredType.BaseType].Add(structuredType); + } + } + } + + if (schemaElements.OfType().Any() || + schemaElements.OfType().Any(o => o.IsBound)) + { + this.WriteExtensionMethodsStart(); + foreach (IEdmEntityType type in schemaElements.OfType()) + { + string entityTypeName = type.Name; + entityTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; + string entityTypeFullName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName), this); + string returnTypeName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName + this.SingleSuffix), this); + + var keyProperties = type.Key(); + if(keyProperties != null && keyProperties.Any()) + { + List keyParameters = new List(); + List keyDictionaryItems = new List(); + List keyNames = new List(); + foreach (IEdmProperty key in keyProperties) + { + string typeName = Utils.GetClrTypeName(key.Type, this.context.UseDataServiceCollection, this, this.context); + string keyName = Utils.CamelCase(key.Name); + keyNames.Add(keyName); + keyParameters.Add(string.Format(this.ParameterDeclarationTemplate, typeName, this.GetFixedName(keyName))); + keyDictionaryItems.Add(string.Format(this.DictionaryItemConstructor, "\"" + key.Name + "\"", this.GetFixedName(keyName))); + } + + string keyParametersString = string.Join(this.KeyParameterSeparator, keyParameters); + string keyDictionaryItemsString = string.Join(this.KeyDictionaryItemSeparator, keyDictionaryItems); + this.WriteByKeyMethods(entityTypeFullName, returnTypeName, keyNames, keyParametersString, keyDictionaryItemsString); + } + + IEdmEntityType current = (IEdmEntityType)type.BaseType; + while (current != null) + { + string baseTypeName = current.Name; + baseTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(baseTypeName) : baseTypeName; + baseTypeName = context.GetPrefixedFullName(current, GetFixedName(baseTypeName), this); + this.WriteCastToMethods(baseTypeName, entityTypeName, entityTypeFullName, returnTypeName); + current = (IEdmEntityType)current.BaseType; + } + } + + HashSet boundOperations = new HashSet(StringComparer.Ordinal); + foreach (IEdmFunction function in schemaElements.OfType()) + { + if (function.IsBound) + { + IEdmTypeReference edmTypeReference = function.Parameters.First().Type; + string functionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(function.Name) : function.Name; + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); + string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); + string fixedFunctionName = GetFixedName(functionName); + string func = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); + + if (!boundOperations.Contains(func)) + { + boundOperations.Add(func); + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + + IEdmStructuredType structuredType; + if (edmTypeReference.IsCollection()) + { + IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; + structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; + } + else + { + structuredType = (IEdmStructuredType)edmTypeReference.Definition; + } + + List derivedTypes; + if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) + { + foreach (IEdmStructuredType type in derivedTypes) + { + IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); + List currentParameters = function.Parameters.Select(p => p.Type).ToList(); + currentParameters[0] = derivedTypeReference; + + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); + string currentFunc = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(currentFunc)) + { + boundOperations.Add(currentFunc); + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + } + } + } + } + + foreach (IEdmAction action in schemaElements.OfType()) + { + if (action.IsBound) + { + IEdmTypeReference edmTypeReference = action.Parameters.First().Type; + string actionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(action.Name) : action.Name; + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); + string returnTypeName; + if (action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); + if (action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string fixedActionName = GetFixedName(actionName); + string ac = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(ac)) + { + boundOperations.Add(ac); + this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); + } + + IEdmStructuredType structuredType; + if (edmTypeReference.IsCollection()) + { + IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; + structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; + } + else + { + structuredType = (IEdmStructuredType)edmTypeReference.Definition; + } + + List derivedTypes; + if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) + { + foreach (IEdmStructuredType type in derivedTypes) + { + IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); + List currentParameters = action.Parameters.Select(p => p.Type).ToList(); + currentParameters[0] = derivedTypeReference; + + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); + string currentAc = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(currentAc)) + { + boundOperations.Add(currentAc); + this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); + } + } + } + } + } + + this.WriteExtensionMethodsEnd(); + } + + this.WriteNamespaceEnd(); + } + + internal bool HasBoundOperations(IEnumerable operations) + { + foreach (IEdmOperation opeartion in operations) + { + if (opeartion.IsBound) + { + return true; + } + } + + return false; + } + + internal void WriteEntityContainer(IEdmEntityContainer container, string fullNamespace) + { + string camelCaseContainerName = container.Name; + if (this.context.EnableNamingAlias) + { + camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); + } + + this.WriteClassStartForEntityContainer(container.Name, camelCaseContainerName, GetFixedName(camelCaseContainerName)); + this.WriteEntityContainerConstructor(container); + + if (this.context.NeedResolveNameFromType) + { + this.WritePropertyRootNamespace(GetFixedName(camelCaseContainerName), this.context.GetPrefixedNamespace(fullNamespace, this, false, false)); + } + + this.WriteResolveTypeFromName(); + this.WriteResolveNameFromType(camelCaseContainerName, fullNamespace); + + foreach (IEdmEntitySet entitySet in container.EntitySets()) + { + IEdmEntityType entitySetElementType = entitySet.EntityType(); + string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); + + string camelCaseEntitySetName = entitySet.Name; + if (this.context.EnableNamingAlias) + { + camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); + } + + this.WriteContextEntitySetProperty(camelCaseEntitySetName, GetFixedName(camelCaseEntitySetName), entitySet.Name, GetFixedName(entitySetElementTypeName)); + List edmNavigationSourceList = null; + if (!this.context.ElementTypeToNavigationSourceMap.TryGetValue(entitySet.EntityType(), out edmNavigationSourceList)) + { + edmNavigationSourceList = new List(); + this.context.ElementTypeToNavigationSourceMap.Add(entitySet.EntityType(), edmNavigationSourceList); + } + + edmNavigationSourceList.Add(entitySet); + } + + foreach (IEdmEntitySet entitySet in container.EntitySets()) + { + IEdmEntityType entitySetElementType = entitySet.EntityType(); + + string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); + + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(/*IsLanguageCaseSensitive*/true); + string parameterName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(entitySetElementType.Name)); + + string camelCaseEntitySetName = entitySet.Name; + if (this.context.EnableNamingAlias) + { + camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); + } + + this.WriteContextAddToEntitySetMethod(camelCaseEntitySetName, entitySet.Name, GetFixedName(entitySetElementTypeName), parameterName); + } + + foreach (IEdmSingleton singleton in container.Singletons()) + { + IEdmEntityType singletonElementType = singleton.EntityType(); + string singletonElementTypeName = GetElementTypeName(singletonElementType, container); + string camelCaseSingletonName = singleton.Name; + if (this.context.EnableNamingAlias) + { + camelCaseSingletonName = Customization.CustomizeNaming(camelCaseSingletonName); + } + + this.WriteContextSingletonProperty(camelCaseSingletonName, GetFixedName(camelCaseSingletonName), singleton.Name, singletonElementTypeName + "Single"); + + List edmNavigationSourceList = null; + if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(singleton.EntityType(), out edmNavigationSourceList)) + { + edmNavigationSourceList.Add(singleton); + } + } + + this.WriteGeneratedEdmModel(Utils.SerializeToString(this.context.Edmx).Replace("\"", "\"\"")); + + bool hasOperationImport = container.OperationImports().OfType().Any(); + foreach (IEdmFunctionImport functionImport in container.OperationImports().OfType()) + { + string parameterString, parameterTypes, parameterExpressionString, parameterValues; + bool useEntityReference; + this.GetParameterStrings(false, false, functionImport.Function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = GetSourceOrReturnTypeName(functionImport.Function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(functionImport.Function.ReturnType, true); + string fixedContainerName = this.GetFixedName(functionImport.Container.Name); + bool isCollectionResult = functionImport.Function.ReturnType.IsCollection(); + string functionImportName = functionImport.Name; + if (this.context.EnableNamingAlias) + { + functionImportName = Customization.CustomizeNaming(functionImportName); + fixedContainerName = Customization.CustomizeNaming(fixedContainerName); + } + + if (functionImport.Function.ReturnType.IsCollection()) + { + this.WriteFunctionImportReturnCollectionResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, parameterString, parameterValues, functionImport.Function.IsComposable, useEntityReference); + } + else + { + this.WriteFunctionImportReturnSingleResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, parameterValues, functionImport.Function.IsComposable, functionImport.Function.ReturnType.IsEntity(), useEntityReference); + } + } + + foreach (IEdmActionImport actionImport in container.OperationImports().OfType()) + { + string parameterString, parameterTypes, parameterExpressionString, parameterValues; + bool useEntityReference; + this.GetParameterStrings(false, true, actionImport.Action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = null; + string fixedContainerName = this.GetFixedName(actionImport.Container.Name); + + if (actionImport.Action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(actionImport.Action.ReturnType); + if (actionImport.Action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string actionImportName = actionImport.Name; + if (this.context.EnableNamingAlias) + { + actionImportName = Customization.CustomizeNaming(actionImportName); + fixedContainerName = Customization.CustomizeNaming(fixedContainerName); + } + + this.WriteActionImport(this.GetFixedName(actionImportName), actionImport.Name, returnTypeName, parameterString, parameterValues); + } + + this.WriteClassEndForEntityContainer(); + } + + internal void WriteEntityContainerConstructor(IEdmEntityContainer container) + { + string camelCaseContainerName = container.Name; + if (this.context.EnableNamingAlias) + { + camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); + } + + this.WriteMethodStartForEntityContainerConstructor(camelCaseContainerName, GetFixedName(camelCaseContainerName)); + + if (this.context.UseKeyAsSegmentUrlConvention(container)) + { + this.WriteKeyAsSegmentUrlConvention(); + } + + if (this.context.NeedResolveNameFromType) + { + this.WriteInitializeResolveName(); + } + + if (this.context.NeedResolveTypeFromName) + { + this.WriteInitializeResolveType(); + } + + this.WriteClassEndForEntityContainerConstructor(); + } + + internal void WriteResolveTypeFromName() + { + if (!this.context.NeedResolveTypeFromName) + { + return; + } + + this.WriteMethodStartForResolveTypeFromName(); + + // NOTE: since multiple namespaces can have the same prefix and match the namespace + // prefix condition, it's important that the prefix check is done is prefix-length + // order, starting with the longest prefix. + IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key); + + string typeName = this.SystemTypeTypeName + " "; + foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) + { + this.WriteResolveNamespace(typeName, namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); + typeName = string.Empty; + } + + this.WriteMethodEndForResolveTypeFromName(); + } + + internal void WriteResolveNameFromType(string containerName, string fullNamespace) + { + if (!this.context.NeedResolveNameFromType) + { + return; + } + + this.WriteMethodStartForResolveNameFromType(GetFixedName(containerName), fullNamespace); + + // NOTE: in this case order also matters, but the length of the CLR + // namespace is what needs to be considered. + IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key); + + foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) + { + this.WriteResolveType(namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); + } + + this.WriteMethodEndForResolveNameFromType(this.context.ModelHasInheritance); + } + + internal void WritePropertiesForSingleType(IEnumerable properties) + { + foreach (IEdmProperty property in properties.Where(i => i.PropertyKind == EdmPropertyKind.Navigation)) + { + string propertyType; + string propertyName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name; + if (property.Type is Microsoft.OData.Edm.EdmCollectionTypeReference) + { + propertyType = GetSourceOrReturnTypeName(property.Type); + WriteContextEntitySetProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); + } + else + { + propertyType = Utils.GetClrTypeName(property.Type, true, this, this.context, true, isEntitySingleType : true); + WriteContextSingletonProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); + } + } + } + + internal void WriteEntityType(IEdmEntityType entityType, Dictionary> boundOperationsMap) + { + string entityTypeName = ((IEdmSchemaElement)entityType).Name; + entityTypeName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; + this.WriteSummaryCommentForStructuredType(entityTypeName + this.SingleSuffix); + this.WriteStructurdTypeDeclaration(entityType, + this.ClassInheritMarker + string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName)), + this.SingleSuffix); + string singleTypeName = (this.context.EnableNamingAlias ? + Customization.CustomizeNaming(((IEdmSchemaElement)entityType).Name) : ((IEdmSchemaElement)entityType).Name) + this.SingleSuffix; + this.WriteConstructorForSingleType(GetFixedName(singleTypeName), string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName))); + IEdmEntityType current = entityType; + while (current != null) + { + this.WritePropertiesForSingleType(current.DeclaredProperties); + current = (IEdmEntityType)current.BaseType; + } + + this.WriteClassEndForStructuredType(); + + this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityType.Name) : entityType.Name); + + if (entityType.Key().Any()) + { + IEnumerable keyProperties = entityType.Key().Select(k => k.Name); + this.WriteKeyPropertiesCommentAndAttribute( + this.context.EnableNamingAlias ? keyProperties.Select(k => Customization.CustomizeNaming(k)) : keyProperties, + string.Join("\", \"", keyProperties)); + } + else + { + this.WriteEntityTypeAttribute(); + } + + if (this.context.UseDataServiceCollection) + { + List navigationSourceList; + if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(entityType, out navigationSourceList)) + { + if(navigationSourceList.Count == 1) + { + this.WriteEntitySetAttribute(navigationSourceList[0].Name); + } + } + } + + if (entityType.HasStream) + { + this.WriteEntityHasStreamAttribute(); + } + + this.WriteStructurdTypeDeclaration(entityType, this.BaseEntityType); + this.SetPropertyIdentifierMappingsIfNameConflicts(entityType.Name, entityType); + this.WriteTypeStaticCreateMethod(entityType.Name, entityType); + this.WritePropertiesForStructuredType(entityType.DeclaredProperties, entityType.IsOpen); + + if (entityType.BaseType == null && this.context.UseDataServiceCollection) + { + this.WriteINotifyPropertyChangedImplementation(); + } + + this.WriteBoundOperations(entityType, boundOperationsMap); + + this.WriteClassEndForStructuredType(); + } + + internal void WriteComplexType(IEdmComplexType complexType, Dictionary> boundOperationsMap) + { + this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(complexType.Name) : complexType.Name); + this.WriteStructurdTypeDeclaration(complexType, string.Empty); + this.SetPropertyIdentifierMappingsIfNameConflicts(complexType.Name, complexType); + this.WriteTypeStaticCreateMethod(complexType.Name, complexType); + this.WritePropertiesForStructuredType(complexType.DeclaredProperties, complexType.IsOpen); + + if (complexType.BaseType == null && this.context.UseDataServiceCollection) + { + this.WriteINotifyPropertyChangedImplementation(); + } + + this.WriteClassEndForStructuredType(); + } + + internal void WriteBoundOperations(IEdmStructuredType structuredType, Dictionary> boundOperationsMap) + { + List operations; + if (boundOperationsMap.TryGetValue(structuredType, out operations)) + { + foreach (IEdmFunction function in operations.OfType()) + { + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, function, boundOperationsMap); + this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); + string functionName = function.Name; + if (this.context.EnableNamingAlias) + { + functionName = Customization.CustomizeNaming(functionName); + } + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionInEntityTypeReturnCollectionResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionInEntityTypeReturnSingleResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + + foreach (IEdmAction action in operations.OfType()) + { + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, action, boundOperationsMap); + this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName; + if (action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); + if (action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string actionName = action.Name; + if (this.context.EnableNamingAlias) + { + actionName = Customization.CustomizeNaming(actionName); + } + + this.WriteBoundActionInEntityType(hideBaseMethod, GetFixedName(actionName), action.Name, returnTypeName, parameterString, action.Namespace, parameterValues); + } + } + } + + internal bool CheckMethodsInBaseClass(IEdmStructuredType structuredType, IEdmOperation operation, Dictionary> boundOperationsMap) + { + if (structuredType != null) + { + List operations; + if (boundOperationsMap.TryGetValue(structuredType, out operations)) + { + foreach (IEdmOperation op in operations) + { + if (this.context.TargetLanguage == LanguageOption.VB) + { + if (operation.Name == op.Name) + { + return true; + } + } + + List targetParameter = operation.Parameters.ToList(); + List checkParameter = op.Parameters.ToList(); + if (operation.Name == op.Name && targetParameter.Count == checkParameter.Count) + { + bool areSame = true; + for (int i = 1; i < targetParameter.Count; ++i) + { + var targetParameterType = targetParameter[i].Type; + var checkParameterType = checkParameter[i].Type; + if (!targetParameterType.Definition.Equals(checkParameterType.Definition) + || targetParameterType.IsNullable != checkParameterType.IsNullable) + { + areSame = false; + break; + } + } + + if (areSame) + { + return true; + } + } + } + } + + return CheckMethodsInBaseClass(structuredType.BaseType, operation, boundOperationsMap); + } + + return false; + } + + internal void WriteEnumType(IEdmEnumType enumType) + { + this.WriteSummaryCommentForEnumType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(enumType.Name) : enumType.Name); + if (enumType.IsFlags) + { + this.WriteEnumFlags(); + } + + string underlyingType = string.Empty; + if (enumType.UnderlyingType != null && enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32) + { + underlyingType = Utils.GetClrTypeName(enumType.UnderlyingType, this); + underlyingType = this.EnumUnderlyingTypeMarker + underlyingType; + } + + this.WriteEnumDeclaration(this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(enumType.Name)) : GetFixedName(enumType.Name), enumType.Name, underlyingType); + this.WriteMembersForEnumType(enumType.Members); + this.WriteEnumEnd(); + } + + internal void WriteStructurdTypeDeclaration(IEdmStructuredType structuredType, string baseEntityType, string typeNameSuffix = null) + { + string abstractModifier = structuredType.IsAbstract && typeNameSuffix == null ? this.AbstractModifier : string.Empty; + string baseTypeName = baseEntityType; + + if (typeNameSuffix == null) + { + if (structuredType.BaseType == null) + { + if (this.context.UseDataServiceCollection) + { + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + baseTypeName += string.IsNullOrEmpty(baseTypeName) ? this.ClassInheritMarker : ", "; + } + + baseTypeName += this.NotifyPropertyChangedModifier; + } + } + else + { + IEdmSchemaElement baseType = (IEdmSchemaElement)structuredType.BaseType; + string baseTypeFixedName = this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(baseType.Name)) : GetFixedName(baseType.Name); + baseTypeName = ((IEdmSchemaElement)structuredType).Namespace == baseType.Namespace ? baseTypeFixedName : this.context.GetPrefixedFullName(baseType, baseTypeFixedName, this); + baseTypeName = this.ClassInheritMarker + baseTypeName; + } + } + + string structuredTypeName = this.context.EnableNamingAlias ? + Customization.CustomizeNaming(((IEdmSchemaElement)structuredType).Name) : ((IEdmSchemaElement)structuredType).Name; + this.WriteClassStartForStructuredType(abstractModifier, GetFixedName(structuredTypeName + typeNameSuffix), ((IEdmSchemaElement)structuredType).Name + typeNameSuffix, baseTypeName); + } + + internal string GetSourceOrReturnTypeName(IEdmTypeReference typeReference, bool isEntitySingleType = false) + { + IEdmCollectionType edmCollectionType = typeReference.Definition as IEdmCollectionType; + bool addNullableTemplate = true; + if (edmCollectionType != null) + { + typeReference = edmCollectionType.ElementType; + addNullableTemplate = false; + } + + return Utils.GetClrTypeName(typeReference, this.context.UseDataServiceCollection, this, this.context, addNullableTemplate, isEntitySingleType:isEntitySingleType); + } + + internal void GetParameterStrings(bool isBound, bool isAction, IEdmOperationParameter[] parameters, out string parameterString, out string parameterTypes, out string parameterExpressionString, out string parameterValues, out bool useEntityReference) + { + parameterString = string.Empty; + parameterExpressionString = string.Empty; + parameterTypes = string.Empty; + parameterValues = string.Empty; + useEntityReference = false; + + int n = parameters.Count(); + for (int i = isBound ? 1 : 0; i < n; ++i) + { + IEdmOperationParameter param = parameters[i]; + if (i == (isBound ? 1 : 0)) + { + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + parameterExpressionString += "\r\n "; + } + else + { + parameterExpressionString += "\r\n "; + } + } + + string typeName = Utils.GetClrTypeName(param.Type, this.context.UseDataServiceCollection, this, this.context, true, true, true); + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + parameterString += typeName; + parameterString += (" " + GetFixedName(param.Name)); + } + else if (this.context.TargetLanguage == LanguageOption.VB) + { + parameterString += GetFixedName(param.Name); + parameterString += (this.EnumUnderlyingTypeMarker + typeName); + } + + parameterString += i == n - 1 ? string.Empty : ", "; + parameterTypes += string.Format(this.TypeofFormatter, typeName) + ", "; + parameterExpressionString += this.GetParameterExpressionString(param, typeName) + ", "; + + if (i != (isBound ? 1 : 0)) + { + parameterValues += ",\r\n "; + } + + if (isAction) + { + parameterValues += string.Format(this.BodyOperationParameterConstructor, param.Name, GetFixedName(param.Name)); + } + else if (param.Type.IsEntity() || (param.Type.IsCollection() && param.Type.AsCollection().ElementType().IsEntity())) + { + useEntityReference = true; + parameterValues += string.Format(this.UriEntityOperationParameterConstructor, param.Name, GetFixedName(param.Name),"useEntityReference"); + } + else + { + parameterValues += string.Format(this.UriOperationParameterConstructor, param.Name, GetFixedName(param.Name)); + } + } + } + + internal string GetParameterExpressionString(IEdmOperationParameter param, string typeName) + { + string clrTypeName; + IEdmType edmType = param.Type.Definition; + IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; + if (edmPrimitiveType != null) + { + clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, this); + if (param.Type.IsNullable && !this.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind)) + { + clrTypeName += "?"; + } + + return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), clrTypeName); + } + + return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), typeName); + } + + // This is to solve duplicate names between property and type + internal void SetPropertyIdentifierMappingsIfNameConflicts(string typeName, IEdmStructuredType structuredType) + { + if (this.context.EnableNamingAlias) + { + typeName = Customization.CustomizeNaming(typeName); + } + + // PropertyName in VB is case-insensitive. + bool isLanguageCaseSensitive = this.context.TargetLanguage == LanguageOption.CSharp; + + // In VB, it is allowed that a type has a property whose name is same with the type's name + bool allowPropertyNameSameWithTypeName = this.context.TargetLanguage == LanguageOption.VB; + + Func customizePropertyName = (name) => { return this.context.EnableNamingAlias ? Customization.CustomizeNaming(name) : name; }; + + var propertyGroups = structuredType.Properties() + .GroupBy(p => isLanguageCaseSensitive ? customizePropertyName(p.Name) : customizePropertyName(p.Name).ToUpperInvariant()); + + // If the group contains more than one property, or the property in the group has the same name with the type (only for C#), we need to rename the property + var propertyToBeRenamedGroups = propertyGroups.Where(g => g.Count() > 1 || !allowPropertyNameSameWithTypeName && g.Key == typeName); + + var knownIdentifiers = propertyGroups.Select(g => customizePropertyName(g.First().Name)).ToList(); + if(!allowPropertyNameSameWithTypeName && !knownIdentifiers.Contains(typeName)) + { + knownIdentifiers.Add(typeName); + } + UniqueIdentifierService uniqueIdentifierService = + new UniqueIdentifierService(knownIdentifiers, isLanguageCaseSensitive); + + IdentifierMappings.Clear(); + foreach (IGrouping g in propertyToBeRenamedGroups) + { + bool hasPropertyNameSameWithCustomizedPropertyName = false; + int itemCount = g.Count(); + for (int i = 0; i < itemCount; i++) + { + var property = g.ElementAt(i); + var customizedPropertyName = customizePropertyName(property.Name); + + if(this.context.EnableNamingAlias && customizedPropertyName == property.Name) + { + hasPropertyNameSameWithCustomizedPropertyName = true; + } + + if(isLanguageCaseSensitive) + { + // If a property name is same as its customized property name, then we don't rename it. + // Or we don't rename the last property in the group + if(customizedPropertyName != typeName + && (customizedPropertyName == property.Name + || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1))) + { + continue; + } + } + else + { + // When EnableNamingAlias = true, If a property name is same as its customized property name, then we don't rename it. + // Or we don't rename the last property in the group. + if((this.context.EnableNamingAlias && customizedPropertyName == property.Name) + || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1)) + { + continue; + } + } + var renamedPropertyName = uniqueIdentifierService.GetUniqueIdentifier(customizedPropertyName); + IdentifierMappings.Add(property.Name, renamedPropertyName); + } + } + } + + internal void WriteTypeStaticCreateMethod(string typeName, IEdmStructuredType structuredType) + { + Debug.Assert(structuredType != null, "structuredType != null"); + if (structuredType.IsAbstract) + { + return; + } + + Func hasDefault = p => p.PropertyKind == EdmPropertyKind.Structural && ((IEdmStructuralProperty)p).DefaultValueString != null; + + if (this.context.EnableNamingAlias) + { + typeName = Customization.CustomizeNaming(typeName); + } + + IEnumerable parameters = structuredType.Properties() + .Where(p => !p.Type.IsNullable && !p.Type.IsCollection() && !hasDefault(p)); + if (!parameters.Any()) + { + return; + } + + this.WriteSummaryCommentForStaticCreateMethod(typeName); + + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( /*IsLanguageCaseSensitive*/true); + string instanceName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(typeName)); + KeyValuePair[] propertyToParameterNamePairs = parameters + .Select(p => + new KeyValuePair(p, + uniqueIdentifierService.GetUniqueParameterName( + IdentifierMappings.ContainsKey(p.Name) ? IdentifierMappings[p.Name] : p.Name))) + .ToArray(); + + foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) + { + string propertyName = propertyToParameterNamePair.Key.Name; + propertyName = IdentifierMappings.ContainsKey(propertyName) ? + IdentifierMappings[propertyName] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(propertyName) : propertyName); + this.WriteParameterCommentForStaticCreateMethod(propertyToParameterNamePair.Value, propertyName); + } + + propertyToParameterNamePairs = propertyToParameterNamePairs + .Select(p => p = new KeyValuePair(p.Key, GetFixedName(p.Value))) + .ToArray(); + + this.WriteDeclarationStartForStaticCreateMethod(typeName, GetFixedName(typeName)); + this.WriteStaticCreateMethodParameters(propertyToParameterNamePairs); + this.WriteDeclarationEndForStaticCreateMethod(GetFixedName(typeName), instanceName); + + foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) + { + IEdmProperty property = propertyToParameterNamePair.Key; + string parameterName = propertyToParameterNamePair.Value; + + Debug.Assert(!property.Type.IsCollection(), "!property.Type.IsCollection()"); + Debug.Assert(!property.Type.IsNullable, "!property.Type.IsNullable"); + + // The static create method only sets non-nullable properties. We should add the null check if the type of the property is not a clr ValueType. + // For now we add the null check if the property type is non-primitive. We should add the null check for non-ValueType primitives in the future. + if (!property.Type.IsPrimitive() && !property.Type.IsEnum()) + { + this.WriteParameterNullCheckForStaticCreateMethod(parameterName); + } + + var uniqIdentifier = IdentifierMappings.ContainsKey(property.Name) ? + IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); + this.WritePropertyValueAssignmentForStaticCreateMethod(instanceName, + GetFixedName(uniqIdentifier), + parameterName); + } + + this.WriteMethodEndForStaticCreateMethod(instanceName); + } + + internal void WriteStaticCreateMethodParameters(KeyValuePair[] propertyToParameterPairs) + { + if (propertyToParameterPairs.Length == 0) + { + return; + } + + // If the number of parameters are greater than 5, we put them in separate lines. + string parameterSeparator = propertyToParameterPairs.Length > 5 ? this.ParameterSeparator : ", "; + for (int idx = 0; idx < propertyToParameterPairs.Length; idx++) + { + KeyValuePair propertyToParameterPair = propertyToParameterPairs[idx]; + + string parameterType = Utils.GetClrTypeName(propertyToParameterPair.Key.Type, this.context.UseDataServiceCollection, this, this.context); + string parameterName = propertyToParameterPair.Value; + if (idx == propertyToParameterPairs.Length - 1) + { + // No separator after the last parameter. + parameterSeparator = string.Empty; + } + + this.WriteParameterForStaticCreateMethod(parameterType, GetFixedName(parameterName), parameterSeparator); + } + } + + internal void WritePropertiesForStructuredType(IEnumerable properties, bool isOpen) + { + bool useDataServiceCollection = this.context.UseDataServiceCollection; + + var propertyInfos = properties.Select(property => + { + string propertyName = IdentifierMappings.ContainsKey(property.Name) ? + IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); + + return new + { + PropertyType = Utils.GetClrTypeName(property.Type, useDataServiceCollection, this, this.context), + PropertyVanillaName = property.Name, + PropertyName = propertyName, + FixedPropertyName = GetFixedName(propertyName), + PrivatePropertyName = "_" + propertyName, + PropertyInitializationValue = Utils.GetPropertyInitializationValue(property, useDataServiceCollection, this, this.context) + }; + }).ToList(); + + if(isOpen && this.context.GenerateDynamicPropertiesCollection) + { + propertyInfos.Add(new + { + PropertyType = string.Format(this.DictionaryTypeName, this.StringTypeName, this.ObjectTypeName), + PropertyVanillaName = string.Empty, // No such property in metadata + PropertyName = this.context.DynamicPropertiesCollectionName, + FixedPropertyName = GetFixedName(this.context.DynamicPropertiesCollectionName), + PrivatePropertyName = "_" + Utils.CamelCase(this.context.DynamicPropertiesCollectionName), + PropertyInitializationValue = string.Format(this.DictionaryConstructor, this.StringTypeName, this.ObjectTypeName) + }); + } + + // Private name should not confict with field name + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(propertyInfos.Select(_ => _.FixedPropertyName), + this.context.TargetLanguage == LanguageOption.CSharp); + + foreach (var propertyInfo in propertyInfos) + { + string privatePropertyName = uniqueIdentifierService.GetUniqueIdentifier("_" + propertyInfo.PropertyName); + + this.WritePropertyForStructuredType( + propertyInfo.PropertyType, + propertyInfo.PropertyVanillaName, + propertyInfo.PropertyName, + propertyInfo.FixedPropertyName, + privatePropertyName, + propertyInfo.PropertyInitializationValue, + useDataServiceCollection); + } + } + + internal void WriteMembersForEnumType(IEnumerable members) + { + int n = members.Count(); + for (int idx = 0; idx < n; ++idx) + { + IEdmEnumMember member = members.ElementAt(idx); + string value = string.Empty; + if (member.Value != null) + { + IEdmEnumMemberValue integerValue = member.Value as IEdmEnumMemberValue; + if (integerValue != null) + { + value = " = " + integerValue.Value.ToString(CultureInfo.InvariantCulture); + } + } + + string memberName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(member.Name) : member.Name; + this.WriteMemberForEnumType(GetFixedName(memberName) + value, member.Name, idx == n - 1); + } + } + + internal string GetFixedName(string originalName) + { + string fixedName = originalName; + + if (this.LanguageKeywords.Contains(fixedName)) + { + fixedName = string.Format(this.FixPattern, fixedName); + } + + return fixedName; + } + + internal string GetElementTypeName(IEdmEntityType elementType, IEdmEntityContainer container) + { + string elementTypeName = elementType.Name; + + if (this.context.EnableNamingAlias) + { + elementTypeName = Customization.CustomizeNaming(elementTypeName); + } + + if (elementType.Namespace != container.Namespace) + { + elementTypeName = this.context.GetPrefixedFullName(elementType, GetFixedName(elementTypeName), this); + } + + return elementTypeName; + } +} + +/// +/// Base class for text transformation +/// +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] +public abstract class TemplateBase +{ + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + + /// + /// Create the template output + /// + public abstract string TransformText(); + + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion +} + +/// +/// Service making names within a scope unique. Initialize a new instance for every scope. +/// +internal sealed class UniqueIdentifierService +{ + // This is the list of keywords we check against when creating parameter names from propert. + // If a name matches this keyword we prefix it. + private static readonly string[] Keywords = new string[] {"class", "event"}; + + /// + /// Hash set to detect identifier collision. + /// + private readonly HashSet knownIdentifiers; + + /// + /// Constructs a . + /// + /// true if the language we are generating the code for is case sensitive, false otherwise. + internal UniqueIdentifierService(bool caseSensitive) + { + this.knownIdentifiers = new HashSet(caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); + } + + /// + /// Constructs a . + /// + /// identifiers used to detect collision. + /// true if the language we are generating the code for is case sensitive, false otherwise. + internal UniqueIdentifierService(IEnumerable identifiers, bool caseSensitive) + { + this.knownIdentifiers = new HashSet(identifiers ?? Enumerable.Empty(), caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); + } + + /// + /// Given an identifier, makes it unique within the scope by adding + /// a suffix (1, 2, 3, ...), and returns the adjusted identifier. + /// + /// Identifier. Must not be null or empty. + /// Identifier adjusted to be unique within the scope. + internal string GetUniqueIdentifier(string identifier) + { + Debug.Assert(!string.IsNullOrEmpty(identifier), "identifier is null or empty"); + + // find a unique name by adding suffix as necessary + int numberOfConflicts = 0; + string uniqueIdentifier = identifier; + while (this.knownIdentifiers.Contains(uniqueIdentifier)) + { + ++numberOfConflicts; + uniqueIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture); + } + + // remember the identifier in this scope + Debug.Assert(!this.knownIdentifiers.Contains(uniqueIdentifier), "we just made it unique"); + this.knownIdentifiers.Add(uniqueIdentifier); + + return uniqueIdentifier; + } + + /// + /// Fix up the given parameter name and make it unique. + /// + /// Parameter name. + /// Fixed parameter name. + internal string GetUniqueParameterName(string name) + { + name = Utils.CamelCase(name); + + // FxCop consider 'iD' as violation, we will change any property that is 'id'(case insensitive) to 'ID' + if (StringComparer.OrdinalIgnoreCase.Equals(name, "id")) + { + name = "ID"; + } + + return this.GetUniqueIdentifier(name); + } +} + +/// +/// Utility class. +/// +internal static class Utils +{ + /// + /// Serializes the xml element to a string. + /// + /// The xml element to serialize. + /// The string representation of the xml. + internal static string SerializeToString(XElement xml) + { + // because comment nodes can contain special characters that are hard to embed in VisualBasic, remove them here + xml.DescendantNodes().OfType().Remove(); + + var stringBuilder = new StringBuilder(); + using (var writer = XmlWriter.Create( + stringBuilder, + new XmlWriterSettings + { + OmitXmlDeclaration = true, + NewLineHandling = NewLineHandling.Replace, + Indent = true, + })) + { + xml.WriteTo(writer); + } + + return stringBuilder.ToString(); + } + + /// + /// Changes the text to use camel case, which lower case for the first character. + /// + /// Text to convert. + /// The converted text in camel case + internal static string CamelCase(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); + } + + return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant() + text.Substring(1); + } + + /// + /// Changes the text to use pascal case, which upper case for the first character. + /// + /// Text to convert. + /// The converted text in pascal case + internal static string PascalCase(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant(); + } + + return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant() + text.Substring(1); + } + + /// + /// Gets the clr type name from the give type reference. + /// + /// The type reference in question. + /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, + /// false to use Collection for collections. + /// ODataClientTemplate instance that call this method. + /// CodeGenerationContext instance in the clientTemplate. + /// This flag indicates whether to return the type name in nullable format + /// The flag indicates whether the namespace need to be added by global prefix + /// This flag indicates whether the edmTypeReference is for an operation parameter + /// The clr type name of the type reference. + internal static string GetClrTypeName(IEdmTypeReference edmTypeReference, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context, bool addNullableTemplate = true, bool needGlobalPrefix = true, bool isOperationParameter = false, bool isEntitySingleType = false) + { + string clrTypeName; + IEdmType edmType = edmTypeReference.Definition; + IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; + if (edmPrimitiveType != null) + { + clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, clientTemplate); + if (edmTypeReference.IsNullable && !clientTemplate.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind) && addNullableTemplate) + { + clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); + } + } + else + { + IEdmComplexType edmComplexType = edmType as IEdmComplexType; + if (edmComplexType != null) + { + clrTypeName = context.GetPrefixedFullName(edmComplexType, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmComplexType.Name)) : clientTemplate.GetFixedName(edmComplexType.Name), clientTemplate); + } + else + { + IEdmEnumType edmEnumType = edmType as IEdmEnumType; + if (edmEnumType != null) + { + clrTypeName = context.GetPrefixedFullName(edmEnumType, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEnumType.Name)) : clientTemplate.GetFixedName(edmEnumType.Name), clientTemplate, needGlobalPrefix); + if (edmTypeReference.IsNullable && addNullableTemplate) + { + clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); + } + } + else + { + IEdmEntityType edmEntityType = edmType as IEdmEntityType; + if (edmEntityType != null) + { + clrTypeName = context.GetPrefixedFullName(edmEntityType, + context.EnableNamingAlias + ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEntityType.Name) + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)) + : clientTemplate.GetFixedName(edmEntityType.Name + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)), + clientTemplate); + } + else + { + IEdmCollectionType edmCollectionType = (IEdmCollectionType)edmType; + IEdmTypeReference elementTypeReference = edmCollectionType.ElementType; + IEdmPrimitiveType primitiveElementType = elementTypeReference.Definition as IEdmPrimitiveType; + if (primitiveElementType != null) + { + clrTypeName = Utils.GetClrTypeName(primitiveElementType, clientTemplate); + } + else + { + IEdmSchemaElement schemaElement = (IEdmSchemaElement)elementTypeReference.Definition; + clrTypeName = context.GetPrefixedFullName(schemaElement, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(schemaElement.Name)) : clientTemplate.GetFixedName(schemaElement.Name), clientTemplate); + } + + string collectionTypeName = isOperationParameter + ? clientTemplate.ICollectionOfTStructureTemplate + : (useDataServiceCollection + ? (elementTypeReference.TypeKind() == EdmTypeKind.Entity + ? clientTemplate.DataServiceCollectionStructureTemplate + : clientTemplate.ObservableCollectionStructureTemplate) + : clientTemplate.ObjectModelCollectionStructureTemplate); + + clrTypeName = string.Format(collectionTypeName, clrTypeName); + } + } + } + } + + return clrTypeName; + } + + /// + /// Gets the value expression to initualize the property with. + /// + /// The property in question. + /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, + /// false to use Collection for collections. + /// ODataClientTemplate instance that call this method. + /// CodeGenerationContext instance in the clientTemplate. + /// The value expression to initualize the property with. + internal static string GetPropertyInitializationValue(IEdmProperty property, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context) + { + IEdmTypeReference edmTypeReference = property.Type; + IEdmCollectionTypeReference edmCollectionTypeReference = edmTypeReference as IEdmCollectionTypeReference; + if (edmCollectionTypeReference == null) + { + IEdmStructuralProperty structuredProperty = property as IEdmStructuralProperty; + if (structuredProperty != null) + { + if (!string.IsNullOrEmpty(structuredProperty.DefaultValueString)) + { + string valueClrType = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + string defaultValue = structuredProperty.DefaultValueString; + bool isCSharpTemplate = clientTemplate is ODataClientCSharpTemplate; + if (edmTypeReference.Definition.TypeKind == EdmTypeKind.Enum) + { + var enumValues = defaultValue.Split(','); + string fullenumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + string enumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context, false, false); + List customizedEnumValues = new List(); + foreach(var enumValue in enumValues) + { + string currentEnumValue = enumValue.Trim(); + int indexFirst = currentEnumValue.IndexOf('\'') + 1; + int indexLast = currentEnumValue.LastIndexOf('\''); + if (indexFirst > 0 && indexLast > indexFirst) + { + currentEnumValue = currentEnumValue.Substring(indexFirst, indexLast - indexFirst); + } + + var customizedEnumValue = context.EnableNamingAlias ? Customization.CustomizeNaming(currentEnumValue) : currentEnumValue; + if (isCSharpTemplate) + { + currentEnumValue = "(" + fullenumTypeName + ")" + clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + customizedEnumValue + "\")"; + } + else + { + currentEnumValue = clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + currentEnumValue + "\")"; + } + customizedEnumValues.Add(currentEnumValue); + } + if (isCSharpTemplate) + { + return string.Join(" | ", customizedEnumValues); + } + else + { + return string.Join(" Or ", customizedEnumValues); + } + } + + if (valueClrType.Equals(clientTemplate.StringTypeName)) + { + defaultValue = "\"" + defaultValue + "\""; + } + else if (valueClrType.Equals(clientTemplate.BinaryTypeName)) + { + defaultValue = "System.Text.Encoding.UTF8.GetBytes(\"" + defaultValue + "\")"; + } + else if (valueClrType.Equals(clientTemplate.SingleTypeName)) + { + if (isCSharpTemplate) + { + defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "f"; + } + else + { + defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "F"; + } + } + else if (valueClrType.Equals(clientTemplate.DecimalTypeName)) + { + if (isCSharpTemplate) + { + // decimal in C# must be initialized with 'm' at the end, like Decimal dec = 3.00m + defaultValue = defaultValue.EndsWith("m", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "m"; + } + else + { + // decimal in VB must be initialized with 'D' at the end, like Decimal dec = 3.00D + defaultValue = defaultValue.ToLower().Replace("m", "D"); + defaultValue = defaultValue.EndsWith("D", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "D"; + } + } + else if (valueClrType.Equals(clientTemplate.GuidTypeName) + | valueClrType.Equals(clientTemplate.DateTimeOffsetTypeName) + | valueClrType.Equals(clientTemplate.DateTypeName) + | valueClrType.Equals(clientTemplate.TimeOfDayTypeName)) + { + defaultValue = valueClrType + ".Parse(\"" + defaultValue + "\")"; + } + else if (valueClrType.Equals(clientTemplate.DurationTypeName)) + { + defaultValue = clientTemplate.XmlConvertClassName + ".ToTimeSpan(\"" + defaultValue + "\")"; + } + else if (valueClrType.Contains("Microsoft.Spatial")) + { + defaultValue = string.Format(clientTemplate.GeoTypeInitializePattern, valueClrType, defaultValue); + } + + return defaultValue; + } + else + { + // doesn't have a default value + return null; + } + } + else + { + // only structured property has default value + return null; + } + } + else + { + string constructorParameters; + if (edmCollectionTypeReference.ElementType().IsEntity() && useDataServiceCollection) + { + constructorParameters = clientTemplate.DataServiceCollectionConstructorParameters; + } + else + { + constructorParameters = "()"; + } + + string clrTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + return clientTemplate.NewModifier + clrTypeName + constructorParameters; + } + } + + /// + /// Gets the clr type name from the give Edm primitive type. + /// + /// The Edm primitive type in question. + /// ODataClientTemplate instance that call this method. + /// The clr type name of the Edm primitive type. + internal static string GetClrTypeName(IEdmPrimitiveType edmPrimitiveType, ODataClientTemplate clientTemplate) + { + EdmPrimitiveTypeKind kind = edmPrimitiveType.PrimitiveKind; + + string type="UNKNOWN"; + if (kind==EdmPrimitiveTypeKind.Int32) + { + type= clientTemplate.Int32TypeName; + } + else if (kind== EdmPrimitiveTypeKind.String) + { + type= clientTemplate.StringTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Binary) + { + type= clientTemplate.BinaryTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Decimal) + { + type= clientTemplate.DecimalTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Int16) + { + type= clientTemplate.Int16TypeName; + } + else if(kind==EdmPrimitiveTypeKind.Single) + { + type= clientTemplate.SingleTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Boolean) + { + type= clientTemplate.BooleanTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Double) + { + type= clientTemplate.DoubleTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Guid) + { + type= clientTemplate.GuidTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Byte) + { + type= clientTemplate.ByteTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Int64) + { + type= clientTemplate.Int64TypeName; + } + else if (kind== EdmPrimitiveTypeKind.SByte) + { + type= clientTemplate.SByteTypeName; + } + else if (kind == EdmPrimitiveTypeKind.Stream) + { + type= clientTemplate.DataServiceStreamLinkTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Geography) + { + type= clientTemplate.GeographyTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyPoint) + { + type= clientTemplate.GeographyPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyLineString) + { + type= clientTemplate.GeographyLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyPolygon) + { + type= clientTemplate.GeographyPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyCollection) + { + type= clientTemplate.GeographyCollectionTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiPolygon) + { + type= clientTemplate.GeographyMultiPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiLineString) + { + type= clientTemplate.GeographyMultiLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiPoint) + { + type= clientTemplate.GeographyMultiPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Geometry) + { + type= clientTemplate.GeometryTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryPoint) + { + type= clientTemplate.GeometryPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryLineString) + { + type= clientTemplate.GeometryLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryPolygon) + { + type= clientTemplate.GeometryPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryCollection) + { + type= clientTemplate.GeometryCollectionTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiPolygon) + { + type= clientTemplate.GeometryMultiPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiLineString) + { + type= clientTemplate.GeometryMultiLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiPoint) + { + type= clientTemplate.GeometryMultiPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.DateTimeOffset) + { + type= clientTemplate.DateTimeOffsetTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Duration) + { + type= clientTemplate.DurationTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Date) + { + type= clientTemplate.DateTypeName; + } + else if (kind== EdmPrimitiveTypeKind.TimeOfDay) + { + type= clientTemplate.TimeOfDayTypeName; + } + else + { + throw new Exception("Type "+kind.ToString()+" is unrecognized"); + } + + return type; + } +} + +public sealed class ODataClientCSharpTemplate : ODataClientTemplate +{ + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The code generation context. + public ODataClientCSharpTemplate(CodeGenerationContext context) + : base(context) + { + } + + internal override string GlobalPrefix { get {return "global::"; } } + internal override string SystemTypeTypeName { get { return "global::System.Type"; } } + internal override string AbstractModifier { get { return " abstract"; } } + internal override string DataServiceActionQueryTypeName { get { return "global::Microsoft.OData.Client.DataServiceActionQuery"; } } + internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuerySingle<{0}>"; } } + internal override string DataServiceActionQueryOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuery<{0}>"; } } + internal override string NotifyPropertyChangedModifier { get { return "global::System.ComponentModel.INotifyPropertyChanged"; } } + internal override string ClassInheritMarker { get { return " : "; } } + internal override string ParameterSeparator { get { return ", \r\n "; } } + internal override string KeyParameterSeparator { get { return ", \r\n "; } } + internal override string KeyDictionaryItemSeparator { get { return ", \r\n "; } } + internal override string SystemNullableStructureTemplate { get { return "global::System.Nullable<{0}>"; } } + internal override string ICollectionOfTStructureTemplate { get { return "global::System.Collections.Generic.ICollection<{0}>"; } } + internal override string DataServiceCollectionStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceCollection<{0}>"; } } + internal override string DataServiceQueryStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuery<{0}>"; } } + internal override string DataServiceQuerySingleStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuerySingle<{0}>"; } } + internal override string ObservableCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.ObservableCollection<{0}>"; } } + internal override string ObjectModelCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.Collection<{0}>"; } } + internal override string DataServiceCollectionConstructorParameters { get { return "(null, global::Microsoft.OData.Client.TrackingMode.None)"; } } + internal override string NewModifier { get { return "new "; } } + internal override string GeoTypeInitializePattern { get { return "global::Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(false).Read<{0}>(new global::System.IO.StringReader(\"{1}\"))"; } } + internal override string Int32TypeName { get { return "int"; } } + internal override string ObjectTypeName { get { return "object"; } } + internal override string StringTypeName { get { return "string"; } } + internal override string BinaryTypeName { get { return "byte[]"; } } + internal override string DecimalTypeName { get { return "decimal"; } } + internal override string Int16TypeName { get { return "short"; } } + internal override string SingleTypeName { get { return "float"; } } + internal override string BooleanTypeName { get { return "bool"; } } + internal override string DoubleTypeName { get { return "double"; } } + internal override string GuidTypeName { get { return "global::System.Guid"; } } + internal override string ByteTypeName { get { return "byte"; } } + internal override string Int64TypeName { get { return "long"; } } + internal override string SByteTypeName { get { return "sbyte"; } } + internal override string DataServiceStreamLinkTypeName { get { return "global::Microsoft.OData.Client.DataServiceStreamLink"; } } + internal override string GeographyTypeName { get { return "global::Microsoft.Spatial.Geography"; } } + internal override string GeographyPointTypeName { get { return "global::Microsoft.Spatial.GeographyPoint"; } } + internal override string GeographyLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyLineString"; } } + internal override string GeographyPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyPolygon"; } } + internal override string GeographyCollectionTypeName { get { return "global::Microsoft.Spatial.GeographyCollection"; } } + internal override string GeographyMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPolygon"; } } + internal override string GeographyMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyMultiLineString"; } } + internal override string GeographyMultiPointTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPoint"; } } + internal override string GeometryTypeName { get { return "global::Microsoft.Spatial.Geometry"; } } + internal override string GeometryPointTypeName { get { return "global::Microsoft.Spatial.GeometryPoint"; } } + internal override string GeometryLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryLineString"; } } + internal override string GeometryPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryPolygon"; } } + internal override string GeometryCollectionTypeName { get { return "global::Microsoft.Spatial.GeometryCollection"; } } + internal override string GeometryMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPolygon"; } } + internal override string GeometryMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryMultiLineString"; } } + internal override string GeometryMultiPointTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPoint"; } } + internal override string DateTypeName { get { return "global::Microsoft.OData.Edm.Date"; } } + internal override string DateTimeOffsetTypeName { get { return "global::System.DateTimeOffset"; } } + internal override string DurationTypeName { get { return "global::System.TimeSpan"; } } + internal override string TimeOfDayTypeName { get { return "global::Microsoft.OData.Edm.TimeOfDay"; } } + internal override string XmlConvertClassName { get { return "global::System.Xml.XmlConvert"; } } + internal override string EnumTypeName { get { return "global::System.Enum"; } } + internal override string DictionaryTypeName { get { return "global::System.Collections.Generic.Dictionary<{0}, {1}>"; } } + internal override string FixPattern { get { return "@{0}"; } } + internal override string EnumUnderlyingTypeMarker { get { return " : "; } } + internal override string ConstantExpressionConstructorWithType { get { return "global::System.Linq.Expressions.Expression.Constant({0}, typeof({1}))"; } } + internal override string TypeofFormatter { get { return "typeof({0})"; } } + internal override string UriOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } + internal override string UriEntityOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } + internal override string BodyOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } + internal override string DictionaryConstructor { get { return $"new {DictionaryTypeName}()"; } } + internal override string BaseEntityType { get { return " : global::Microsoft.OData.Client.BaseEntityType"; } } + internal override string OverloadsModifier { get { return "new "; } } + internal override string ODataVersion { get { return "global::Microsoft.OData.ODataVersion.V4"; } } + internal override string ParameterDeclarationTemplate { get { return "{0} {1}"; } } + internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } + internal override HashSet LanguageKeywords { get { + if (CSharpKeywords == null) + { + CSharpKeywords = new HashSet(StringComparer.Ordinal) + { + "abstract", "as", "base", "byte", "bool", "break", "case", "catch", "char", "checked", "class", "const", "continue", + "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "for", + "foreach", "finally", "fixed", "float", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", + "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", + "readonly", "ref", "return", "sbyte", "sealed", "string", "short", "sizeof", "stackalloc", "static", "struct", "switch", + "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "volatile", + "void", "while" + }; + } + return CSharpKeywords; + } } + private HashSet CSharpKeywords; + + internal override void WriteFileHeader() + { +#>//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:<#= Environment.Version #> +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generation date: <#= DateTime.Now.ToString(global::System.Globalization.CultureInfo.CurrentCulture) #> +<#+ + } + + internal override void WriteNamespaceStart(string fullNamespace) + { +#> +namespace <#= fullNamespace #> +{ +<#+ + } + + internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) + { +#> + /// + /// There are no comments for <#= containerName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalContainerName #>")] +<#+ + } +#> + public partial class <#= fixedContainerName #> : global::Microsoft.OData.Client.DataServiceContext + { +<#+ + } + + internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) + { +#> + /// + /// Initialize a new <#= containerName #> object. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public <#= fixedContainerName #>(global::System.Uri serviceRoot) : + base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4) + { +<#+ + } + + internal override void WriteKeyAsSegmentUrlConvention() + { +#> + this.UrlKeyDelimiter = global::Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash; +<#+ + } + + internal override void WriteInitializeResolveName() + { +#> + this.ResolveName = new global::System.Func(this.ResolveNameFromType); +<#+ + } + + internal override void WriteInitializeResolveType() + { +#> + this.ResolveType = new global::System.Func(this.ResolveTypeFromName); +<#+ + } + + internal override void WriteClassEndForEntityContainerConstructor() + { +#> + this.OnContextCreated(); + this.Format.LoadServiceModel = GeneratedEdmModel.GetInstance; + this.Format.UseJson(); + } + partial void OnContextCreated(); +<#+ + } + + internal override void WriteMethodStartForResolveTypeFromName() + { +#> + /// + /// Since the namespace configured for this service reference + /// in Visual Studio is different from the one indicated in the + /// server schema, use type-mappers to map between the two. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected global::System.Type ResolveTypeFromName(string typeName) + { +<#+ + } + + internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) + { +#> + <#= typeName #>resolvedType = this.DefaultResolveType(typeName, "<#= fullNamespace #>", "<#= languageDependentNamespace #>"); + if ((resolvedType != null)) + { + return resolvedType; + } +<#+ + } + + internal override void WriteMethodEndForResolveTypeFromName() + { +#> + return null; + } +<#+ + } + + internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) + { + + } + + internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) + { +#> + /// + /// Since the namespace configured for this service reference + /// in Visual Studio is different from the one indicated in the + /// server schema, use type-mappers to map between the two. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected string ResolveNameFromType(global::System.Type clientType) + { +<#+ + if (this.context.EnableNamingAlias) + { +#> + global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true)); +<#+ + } + } + + internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) + { +#> + if (clientType.Namespace.Equals("<#= languageDependentNamespace #>", global::System.StringComparison.Ordinal)) + { +<#+ + if (this.context.EnableNamingAlias) + { +#> + if (originalNameAttribute != null) + { + return string.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName); + } +<#+ + } +#> + return string.Concat("<#= fullNamespace #>.", clientType.Name); + } +<#+ + } + + internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) + { + if (this.context.EnableNamingAlias && modelHasInheritance) + { +#> + if (originalNameAttribute != null) + { + return clientType.Namespace + "." + originalNameAttribute.OriginalName; + } +<#+ + } +#> + return <#= modelHasInheritance ? "clientType.FullName" : "null" #>; + } +<#+ + } + + internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) + { +#> + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path) + : base(context, path) {} + + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path, bool isComposable) + : base(context, path, isComposable) {} + + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(<#= baseTypeName #> query) + : base(query) {} + +<#+ + } + + internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) + { +#> + /// + /// There are no comments for <#= entitySetName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEntitySetName #>")] +<#+ + } +#> + public global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> <#= entitySetFixedName #> + { + get + { +<#+ + if (!inContext) + { +#> + if (!this.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } +<#+ + } +#> + if ((this._<#= entitySetName #> == null)) + { + this._<#= entitySetName #> = <#= inContext ? "base" : "Context" #>.CreateQuery<<#= entitySetElementTypeName #>>(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>); + } + return this._<#= entitySetName #>; + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> _<#= entitySetName #>; +<#+ + } + + internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) + { +#> + /// + /// There are no comments for <#= singletonName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalSingletonName #>")] +<#+ + } +#> + public <#= singletonElementTypeName #> <#= singletonFixedName #> + { + get + { +<#+ + if (!inContext) + { +#> + if (!this.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } +<#+ + } +#> + if ((this._<#= singletonName #> == null)) + { + this._<#= singletonName #> = new <#= singletonElementTypeName #>(<#= inContext ? "this" : "this.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>); + } + return this._<#= singletonName #>; + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private <#= singletonElementTypeName #> _<#= singletonName #>; +<#+ + } + + internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) + { +#> + /// + /// There are no comments for <#= entitySetName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public void AddTo<#= entitySetName #>(<#= typeName #> <#= parameterName #>) + { + base.AddObject("<#= originalEntitySetName #>", <#= parameterName #>); + } +<#+ + } + + internal override void WriteGeneratedEdmModel(string escapedEdmxString) + { + + string path = this.context.TempFilePath; + + if (!String.IsNullOrEmpty(path)) + { + using (StreamWriter writer = new StreamWriter(path, true)) + { + writer.WriteLine(escapedEdmxString); + } + } + + bool useTempFile = !String.IsNullOrEmpty(path) && System.IO.File.Exists(path); +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private abstract class GeneratedEdmModel + { +<#+ + if (this.context.ReferencesMap != null) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Collections.Generic.Dictionary ReferencesMap = new global::System.Collections.Generic.Dictionary() + { +<#+ + foreach(var reference in this.context.ReferencesMap) + { +#> + {@"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", @"<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"") #>"}, +<#+ + } +#> + }; +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString(); +<#+ + if (useTempFile) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private const string filePath = @"<#= path #>"; +<#+ + } + else + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private const string Edmx = @"<#= escapedEdmxString #>"; +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public static global::Microsoft.OData.Edm.IEdmModel GetInstance() + { + return ParsedModel; + } +<#+ + if (this.context.ReferencesMap != null) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader getReferencedModelFromMap(global::System.Uri uri) + { + string referencedEdmx; + if (ReferencesMap.TryGetValue(uri.OriginalString, out referencedEdmx)) + { + return CreateXmlReader(referencedEdmx); + } + + return null; + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() + { +<#+ + if (useTempFile) + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(); +<#+ + } + else + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); +<#+ + } +#> + try + { + return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, getReferencedModelFromMap); + } + finally + { + ((global::System.IDisposable)(reader)).Dispose(); + } + } +<#+ + } + else + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() + { +<#+ + if (useTempFile) + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(); +<#+ + } + else + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); +<#+ + } +#> + try + { + global::System.Collections.Generic.IEnumerable errors; + global::Microsoft.OData.Edm.IEdmModel edmModel; + + if (!global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, <#= this.context.IgnoreUnexpectedElementsAndAttributes ? "true" : "false" #>, out edmModel, out errors)) + { + global::System.Text.StringBuilder errorMessages = new System.Text.StringBuilder(); + foreach (var error in errors) + { + errorMessages.Append(error.ErrorMessage); + errorMessages.Append("; "); + } + throw new global::System.InvalidOperationException(errorMessages.ToString()); + } + + return edmModel; + } + finally + { + ((global::System.IDisposable)(reader)).Dispose(); + } + } +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse) + { + return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse)); + } +<#+ + if (useTempFile) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader CreateXmlReader() + { + return global::System.Xml.XmlReader.Create(new global::System.IO.StreamReader(filePath)); + } +<#+ + } +#> + } +<#+ + } + + internal override void WriteClassEndForEntityContainer() + { +#> + } +<#+ + } + + internal override void WriteSummaryCommentForStructuredType(string typeName) + { +#> + /// + /// There are no comments for <#= typeName #> in the schema. + /// +<#+ + } + + internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) + { +#> + /// +<#+ + foreach (string key in keyProperties) + { +#> + /// <#= key #> +<#+ + } +#> + /// + [global::Microsoft.OData.Client.Key("<#= keyString #>")] +<#+ + } + + internal override void WriteEntityTypeAttribute() + { +#> + [global::Microsoft.OData.Client.EntityType()] +<#+ + } + + internal override void WriteEntitySetAttribute(string entitySetName) + { +#> + [global::Microsoft.OData.Client.EntitySet("<#= entitySetName #>")] +<#+ + } + + internal override void WriteEntityHasStreamAttribute() + { +#> + [global::Microsoft.OData.Client.HasStream()] +<#+ + } + + internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalTypeName #>")] +<#+ + } +#> + public<#= abstractModifier #> partial class <#= typeName #><#= baseTypeName #> + { +<#+ + } + + internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) + { +#> + /// + /// Create a new <#= typeName #> object. + /// +<#+ + } + + internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) + { +#> + /// Initial value of <#= propertyName #>. +<#+ + } + + internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public static <#= fixedTypeName #> Create<#= typeName #>(<#+ + } + + internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) + { +#><#= parameterTypeName #> <#= parameterName #><#= parameterSeparater #><#+ + } + + internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) + { + #>) + { + <#= typeName #> <#= instanceName #> = new <#= typeName #>(); +<#+ + } + + internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) + { +#> + if ((<#= parameterName #> == null)) + { + throw new global::System.ArgumentNullException("<#= parameterName #>"); + } +<#+ + } + + internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) + { +#> + <#= instanceName #>.<#= propertyName #> = <#= parameterName #>; +<#+ + } + + internal override void WriteMethodEndForStaticCreateMethod(string instanceName) + { +#> + return <#= instanceName #>; + } +<#+ + } + + internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) + { +#> + /// + /// There are no comments for Property <#= propertyName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalPropertyName #>")] +<#+ + } +#> + public <#= propertyType #> <#= fixedPropertyName #> + { + get + { + return this.<#= privatePropertyName #>; + } + set + { + this.On<#= propertyName #>Changing(value); + this.<#= privatePropertyName #> = value; + this.On<#= propertyName #>Changed(); +<#+ + if (writeOnPropertyChanged) + { +#> + this.OnPropertyChanged("<#= originalPropertyName #>"); +<#+ + } +#> + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private <#= propertyType #> <#= privatePropertyName #><#= propertyInitializationValue != null ? " = " + propertyInitializationValue : string.Empty #>; + partial void On<#= propertyName #>Changing(<#= propertyType #> value); + partial void On<#= propertyName #>Changed(); +<#+ + } + + internal override void WriteINotifyPropertyChangedImplementation() + { +#> + /// + /// This event is raised when the value of the property is changed + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + /// + /// The value of the property is changed + /// + /// property name + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected virtual void OnPropertyChanged(string property) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property)); + } + } +<#+ + } + + internal override void WriteClassEndForStructuredType() + { +#> + } +<#+ + } + + internal override void WriteEnumFlags() + { +#> + [global::System.Flags] +<#+ + } + + internal override void WriteSummaryCommentForEnumType(string enumName) + { +#> + /// + /// There are no comments for <#= enumName #> in the schema. + /// +<#+ + } + + internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEnumName #>")] +<#+ + } +#> + public enum <#= enumName #><#= underlyingType #> + { +<#+ + } + + internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalMemberName #>")] +<#+ + } +#> + <#= member #><#= last ? string.Empty : "," #> +<#+ + } + + internal override void WriteEnumEnd() + { +#> + } +<#+ + } + + internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + return this.CreateFunctionQuery<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.CreateFunctionQuerySingle<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + global::System.Uri requestUri; + Context.TryGetUri(this, out requestUri); + return this.Context.CreateFunctionQuery<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>); + } +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + global::System.Uri requestUri; + Context.TryGetUri(this, out requestUri); + + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.Context.CreateFunctionQuerySingle<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public <#= returnTypeName #> <#= actionName #>(<#= parameters #>) + { + return new <#= returnTypeName #>(this, this.BaseUri.OriginalString.Trim('/') + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= returnTypeName #> <#= actionName #>(<#= parameters #>) + { + global::Microsoft.OData.Client.EntityDescriptor resource = Context.EntityTracker.TryGetEntityDescriptor(this); + if (resource == null) + { + throw new global::System.Exception("cannot find entity"); + } + + return new <#= returnTypeName #>(this.Context, resource.EditLink.OriginalString.Trim('/') + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteExtensionMethodsStart() + { +#> + /// + /// Class containing all extension methods + /// + public static class ExtensionMethods + { +<#+ + } + + internal override void WriteExtensionMethodsEnd() + { +#> + } +<#+ + } + + internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) + { +#> + /// + /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + /// + /// source entity set + /// dictionary with the names and values of keys + public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, global::System.Collections.Generic.Dictionary keys) + { + return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); + } + /// + /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + /// + /// source entity set +<#+ + foreach (var key in keys) + { +#> + /// The value of <#= key #> +<#+ + } +#> + public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, + <#= keyParameters #>) + { + global::System.Collections.Generic.Dictionary keys = new global::System.Collections.Generic.Dictionary + { + <#= keyDictionaryItems #> + }; + return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); + } +<#+ + } + + internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) + { +#> + /// + /// Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> + /// + /// source entity + public static <#= returnTypeName #> CastTo<#= derivedTypeName #>(this global::Microsoft.OData.Client.DataServiceQuerySingle<<#= baseTypeName #>> source) + { + global::Microsoft.OData.Client.DataServiceQuerySingle<<#= derivedTypeFullName #>> query = source.CastTo<<#= derivedTypeFullName #>>(); + return new <#= returnTypeName #>(source.Context, query.GetPath(null)); + } +<#+ + } + + internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public static <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public static global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = true" : string.Empty #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return source.CreateFunctionQuery<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public static <#= returnTypeName #> <#= actionName #>(this <#= boundSourceType #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return new <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteNamespaceEnd() + { +#> +} +<#+ + } +} + +public sealed class ODataClientVBTemplate : ODataClientTemplate +{ + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The cotion context. + public ODataClientVBTemplate(CodeGenerationContext context) + : base(context) + { + } + + internal override string GlobalPrefix { get { return string.Empty; } } + internal override string SystemTypeTypeName { get { return "Global.System.Type"; } } + internal override string AbstractModifier { get { return " MustInherit"; } } + internal override string DataServiceActionQueryTypeName { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery"; } } + internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuerySingle(Of {0})"; } } + internal override string DataServiceActionQueryOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery(Of {0})"; } } + internal override string NotifyPropertyChangedModifier { get { return "\r\n Implements Global.System.ComponentModel.INotifyPropertyChanged"; } } + internal override string ClassInheritMarker { get { return "\r\n Inherits "; } } + internal override string ParameterSeparator { get { return ", _\r\n "; } } + internal override string KeyParameterSeparator { get { return ", _\r\n "; } } + internal override string KeyDictionaryItemSeparator { get { return ", _\r\n "; } } + internal override string SystemNullableStructureTemplate { get { return "Global.System.Nullable(Of {0})"; } } + internal override string ICollectionOfTStructureTemplate { get { return "Global.System.Collections.Generic.ICollection(Of {0})"; } } + internal override string DataServiceCollectionStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceCollection(Of {0})"; } } + internal override string DataServiceQueryStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuery(Of {0})"; } } + internal override string DataServiceQuerySingleStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuerySingle(Of {0})"; } } + internal override string ObservableCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.ObservableCollection(Of {0})"; } } + internal override string ObjectModelCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.Collection(Of {0})"; } } + internal override string DataServiceCollectionConstructorParameters { get { return "(Nothing, Global.Microsoft.OData.Client.TrackingMode.None)"; } } + internal override string NewModifier { get { return "New "; } } + internal override string GeoTypeInitializePattern { get { return "Global.Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(False).Read(Of {0})(New Global.System.IO.StringReader(\"{1}\"))"; } } + internal override string Int32TypeName { get { return "Integer"; } } + internal override string ObjectTypeName { get { return "Object"; } } + internal override string StringTypeName { get { return "String"; } } + internal override string BinaryTypeName { get { return "Byte()"; } } + internal override string DecimalTypeName { get { return "Decimal"; } } + internal override string Int16TypeName { get { return "Short"; } } + internal override string SingleTypeName { get { return "Single"; } } + internal override string BooleanTypeName { get { return "Boolean"; } } + internal override string DoubleTypeName { get { return "Double"; } } + internal override string GuidTypeName { get { return "Global.System.Guid"; } } + internal override string ByteTypeName { get { return "Byte"; } } + internal override string Int64TypeName { get { return "Long"; } } + internal override string SByteTypeName { get { return "SByte"; } } + internal override string DataServiceStreamLinkTypeName { get { return "Global.Microsoft.OData.Client.DataServiceStreamLink"; } } + internal override string GeographyTypeName { get { return "Global.Microsoft.Spatial.Geography"; } } + internal override string GeographyPointTypeName { get { return "Global.Microsoft.Spatial.GeographyPoint"; } } + internal override string GeographyLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyLineString"; } } + internal override string GeographyPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyPolygon"; } } + internal override string GeographyCollectionTypeName { get { return "Global.Microsoft.Spatial.GeographyCollection"; } } + internal override string GeographyMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPolygon"; } } + internal override string GeographyMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiLineString"; } } + internal override string GeographyMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPoint"; } } + internal override string GeometryTypeName { get { return "Global.Microsoft.Spatial.Geometry"; } } + internal override string GeometryPointTypeName { get { return "Global.Microsoft.Spatial.GeometryPoint"; } } + internal override string GeometryLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryLineString"; } } + internal override string GeometryPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryPolygon"; } } + internal override string GeometryCollectionTypeName { get { return "Global.Microsoft.Spatial.GeometryCollection"; } } + internal override string GeometryMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPolygon"; } } + internal override string GeometryMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiLineString"; } } + internal override string GeometryMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPoint"; } } + internal override string DateTypeName { get { return "Global.Microsoft.OData.Edm.Date"; } } + internal override string DateTimeOffsetTypeName { get { return "Global.System.DateTimeOffset"; } } + internal override string DurationTypeName { get { return "Global.System.TimeSpan"; } } + internal override string TimeOfDayTypeName { get { return "Global.Microsoft.OData.Edm.TimeOfDay"; } } + internal override string XmlConvertClassName { get { return "Global.System.Xml.XmlConvert"; } } + internal override string EnumTypeName { get { return "Global.System.Enum"; } } + internal override string DictionaryTypeName { get { return "Global.System.Collections.Generic.Dictionary(Of {0}, {1})"; } } + internal override string FixPattern { get { return "[{0}]"; } } + internal override string EnumUnderlyingTypeMarker { get { return " As "; } } + internal override string ConstantExpressionConstructorWithType { get { return "Global.System.Linq.Expressions.Expression.Constant({0}, GetType({1}))"; } } + internal override string TypeofFormatter { get { return "GetType({0})"; } } + internal override string UriOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } + internal override string UriEntityOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } + internal override string BodyOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } + internal override string DictionaryConstructor { get { return $"New {DictionaryTypeName}"; } } + internal override string BaseEntityType { get { return "\r\n Inherits Global.Microsoft.OData.Client.BaseEntityType"; } } + internal override string OverloadsModifier { get { return "Overloads "; } } + internal override string ODataVersion { get { return "Global.Microsoft.OData.ODataVersion.V4"; } } + internal override string ParameterDeclarationTemplate { get { return "{1} As {0}"; } } + internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } + internal override HashSet LanguageKeywords { get { + if (VBKeywords == null) + { + VBKeywords = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte", "ByVal", + "Call", "Case", "Catch", "CBool", "", "CByte", "CChar", "CDate", "CDbl", "CDec", "Char", + "CInt", "Class", "CLng", "CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", + "CType", "CUInt", "CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", + "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", + "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", + "GetXMLNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In", "Inherits", + "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like", "Long", "Loop", "Me", + "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", "Namespace", "Narrowing", "New", "Next", + "Not", "Nothing", "NotInheritable", "NotOverridable", "Object", "Of", "On", "Operator", "Option", "Optional", + "Or", "OrElse", "Out", "Overloads", "Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", + "Protected", "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "SByte", + "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", + "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast", "TypeOf", + "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While", "Widening", "With", + "WithEvents", "WriteOnly", "Xor" + }; + } + return VBKeywords; + } } + private HashSet VBKeywords; + + internal override void WriteFileHeader() + { +#>'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:<#= Environment.Version #> +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict Off +Option Explicit On + + +'Generation date: <#= DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture) #> +<#+ + } + + internal override void WriteNamespaceStart(string fullNamespace) + { +#> +Namespace <#= fullNamespace #> +<#+ + } + + internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) + { +#> + ''' + '''There are no comments for <#= containerName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Partial Public Class <#= fixedContainerName #> + Inherits Global.Microsoft.OData.Client.DataServiceContext +<#+ + } + + internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) + { +#> + ''' + '''Initialize a new <#= containerName #> object. + ''' + ")> _ + Public Sub New(ByVal serviceRoot As Global.System.Uri) + MyBase.New(serviceRoot, Global.Microsoft.OData.Client.ODataProtocolVersion.V4) +<#+ + } + + internal override void WriteKeyAsSegmentUrlConvention() + { +#> + Me.UrlKeyDelimiter = Global.Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash +<#+ + } + + internal override void WriteInitializeResolveName() + { +#> + Me.ResolveName = AddressOf Me.ResolveNameFromType +<#+ + } + + internal override void WriteInitializeResolveType() + { +#> + Me.ResolveType = AddressOf Me.ResolveTypeFromName +<#+ + } + + internal override void WriteClassEndForEntityContainerConstructor() + { +#> + Me.OnContextCreated + Me.Format.LoadServiceModel = AddressOf GeneratedEdmModel.GetInstance + Me.Format.UseJson() + End Sub + Partial Private Sub OnContextCreated() + End Sub +<#+ + } + + internal override void WriteMethodStartForResolveTypeFromName() + { +#> + ''' + '''Since the namespace configured for this service reference + '''in Visual Studio is different from the one indicated in the + '''server schema, use type-mappers to map between the two. + ''' + ")> _ + Protected Function ResolveTypeFromName(ByVal typeName As String) As Global.System.Type +<#+ + } + + internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) + { + if (!string.IsNullOrEmpty(typeName)) + { +#> + Dim resolvedType As <#= typeName #>= Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) +<#+ + } + else + { +#> + resolvedType = Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) +<#+ + } +#> + If (Not (resolvedType) Is Nothing) Then + Return resolvedType + End If +<#+ + } + + internal override void WriteMethodEndForResolveTypeFromName() + { +#> + Return Nothing + End Function +<#+ + } + + internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) + { +#> + ")> _ + Private Shared ROOTNAMESPACE As String = GetType(<#= containerName #>).Namespace.Remove(GetType(<#= containerName #>).Namespace.LastIndexOf("<#= fullNamespace #>")) +<#+ + } + + internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) + { +#> + ''' + '''Since the namespace configured for this service reference + '''in Visual Studio is different from the one indicated in the + '''server schema, use type-mappers to map between the two. + ''' + ")> _ + Protected Function ResolveNameFromType(ByVal clientType As Global.System.Type) As String +<#+ + if (this.context.EnableNamingAlias) + { +#> + Dim originalNameAttribute As Global.Microsoft.OData.Client.OriginalNameAttribute = + CType(Global.System.Linq.Enumerable.SingleOrDefault(Global.Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, GetType(Global.Microsoft.OData.Client.OriginalNameAttribute), true)), Global.Microsoft.OData.Client.OriginalNameAttribute) +<#+ + } + } + + internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) + { +#> + If clientType.Namespace.Equals(String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>"), Global.System.StringComparison.OrdinalIgnoreCase) Then +<#+ + if (this.context.EnableNamingAlias) + { +#> + If (Not (originalNameAttribute) Is Nothing) Then + Return String.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName) + End If +<#+ + } +#> + Return String.Concat("<#= fullNamespace #>.", clientType.Name) + End If +<#+ + } + + internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) + { + if (this.context.EnableNamingAlias && modelHasInheritance) + { +#> + If (Not (originalNameAttribute) Is Nothing) Then + Dim fullName As String = clientType.FullName.Substring(ROOTNAMESPACE.Length) + Return fullName.Remove(fullName.LastIndexOf(clientType.Name)) + originalNameAttribute.OriginalName + End If +<#+ + } +#> + Return <#= modelHasInheritance ? "clientType.FullName.Substring(ROOTNAMESPACE.Length)" : "Nothing" #> + End Function +<#+ + } + + internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) + { +#> + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String) + MyBase.New(context, path) + End Sub + + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String, ByVal isComposable As Boolean) + MyBase.New(context, path, isComposable) + End Sub + + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal query As <#= baseTypeName #>) + MyBase.New(query) + End Sub +<#+ + } + + internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) + { +#> + ''' + '''There are no comments for <#= entitySetName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public ReadOnly Property <#= entitySetFixedName #>() As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) + Get +<#+ + if (!inContext) + { +#> + If Not Me.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If +<#+ + } +#> + If (Me._<#= entitySetName #> Is Nothing) Then + Me._<#= entitySetName #> = <#= inContext ? "MyBase" : "Context"#>.CreateQuery(Of <#= entitySetElementTypeName #>)(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>) + End If + Return Me._<#= entitySetName #> + End Get + End Property + ")> _ + Private _<#= entitySetName #> As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) +<#+ + } + + internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) + { +#> + ''' + '''There are no comments for <#= singletonName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public ReadOnly Property <#= singletonFixedName #>() As <#= singletonElementTypeName #> + Get +<#+ + if (!inContext) + { +#> + If Not Me.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If +<#+ + } +#> + If (Me._<#= singletonName #> Is Nothing) Then + Me._<#= singletonName #> = New <#= singletonElementTypeName #>(<#= inContext ? "Me" : "Me.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>) + End If + Return Me._<#= singletonName #> + End Get + End Property + ")> _ + Private _<#= singletonName #> As <#= singletonElementTypeName #> +<#+ + } + + internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) + { +#> + ''' + '''There are no comments for <#= entitySetName #> in the schema. + ''' + ")> _ + Public Sub AddTo<#= entitySetName #>(ByVal <#= parameterName #> As <#= typeName #>) + MyBase.AddObject("<#= originalEntitySetName #>", <#= parameterName #>) + End Sub +<#+ + } + + internal override void WriteGeneratedEdmModel(string escapedEdmxString) + { + escapedEdmxString = escapedEdmxString.Replace("\r\n", "\" & _\r\n \""); +#> + ")> _ + Private MustInherit Class GeneratedEdmModel +<#+ + if (this.context.ReferencesMap != null) + { +#> + ")> _ + Private Shared ReferencesMap As Global.System.Collections.Generic.Dictionary(Of String, String) = New Global.System.Collections.Generic.Dictionary(Of String, String) From + { +<#+ + int count = this.context.ReferencesMap.Count(); + foreach(var reference in this.context.ReferencesMap) + { +#> + {"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", "<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"").Replace("\r\n", "\" & _\r\n \"") #>"}<#= (--count>0?",":"")#> +<#+ + } +#> + } +<#+ + } +#> + ")> _ + Private Shared ParsedModel As Global.Microsoft.OData.Edm.IEdmModel = LoadModelFromString + ")> _ + Private Const Edmx As String = "<#= escapedEdmxString #>" + ")> _ + Public Shared Function GetInstance() As Global.Microsoft.OData.Edm.IEdmModel + Return ParsedModel + End Function +<#+ + if (this.context.ReferencesMap != null) + { +#> + ")> _ + Private Shared Function getReferencedModelFromMap(ByVal uri As Global.System.Uri) As Global.System.Xml.XmlReader + Dim referencedEdmx As String = Nothing + If (ReferencesMap.TryGetValue(uri.OriginalString, referencedEdmx)) Then + Return CreateXmlReader(referencedEdmx) + End If + Return Nothing + End Function + ")> _ + Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel + Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) + Try + Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, AddressOf getReferencedModelFromMap) + Finally + CType(reader,Global.System.IDisposable).Dispose + End Try + End Function +<#+ + } + else + { +#> + ")> _ + Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel + Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) + Try + Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader) + Finally + CType(reader,Global.System.IDisposable).Dispose + End Try + End Function +<#+ + } +#> + ")> _ + Private Shared Function CreateXmlReader(ByVal edmxToParse As String) As Global.System.Xml.XmlReader + Return Global.System.Xml.XmlReader.Create(New Global.System.IO.StringReader(edmxToParse)) + End Function + End Class +<#+ + } + + internal override void WriteClassEndForEntityContainer() + { +#> + End Class +<#+ + } + + internal override void WriteSummaryCommentForStructuredType(string typeName) + { +#> + ''' + '''There are no comments for <#= typeName #> in the schema. + ''' +<#+ + } + + internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) + { +#> + ''' +<#+ + foreach (string key in keyProperties) + { +#> + '''<#= key #> +<#+ + } +#> + ''' + ")> _ +<#+ + } + + internal override void WriteEntityTypeAttribute() + { +#> + _ +<#+ + } + + internal override void WriteEntitySetAttribute(string entitySetName) + { +#> + ")> _ +<#+ + } + + internal override void WriteEntityHasStreamAttribute() + { +#> + _ +<#+ + } + + internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Partial Public<#= abstractModifier #> Class <#= typeName #><#= baseTypeName #> +<#+ + } + + internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) + { +#> + ''' + '''Create a new <#= typeName #> object. + ''' +<#+ + } + + internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) + { +#> + '''Initial value of <#= propertyName #>. +<#+ + } + + internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) + { +#> + ")> _ + Public Shared Function Create<#= typeName #>(<#+ + + } + + internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) + { +#>ByVal <#= parameterName #> As <#= parameterTypeName #><#= parameterSeparater #><#+ + } + + internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) + { + #>) As <#= typeName #> + Dim <#= instanceName #> As <#= typeName #> = New <#= typeName #>() +<#+ + } + + internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) + { +#> + If (<#= parameterName #> Is Nothing) Then + Throw New Global.System.ArgumentNullException("<#= parameterName #>") + End If +<#+ + } + + internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) + { +#> + <#= instanceName #>.<#= propertyName #> = <#= parameterName #> +<#+ + } + + internal override void WriteMethodEndForStaticCreateMethod(string instanceName) + { +#> + Return <#= instanceName #> + End Function +<#+ + } + + internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) + { +#> + ''' + '''There are no comments for Property <#= propertyName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) + { +#> + ")> _ +<#+ + } +#> + Public Property <#= fixedPropertyName #>() As <#= propertyType #> + Get + Return Me.<#= privatePropertyName #> + End Get + Set + Me.On<#= propertyName #>Changing(value) + Me.<#= privatePropertyName #> = value + Me.On<#= propertyName #>Changed +<#+ + if (writeOnPropertyChanged) + { +#> + Me.OnPropertyChanged("<#= originalPropertyName #>") +<#+ + } +#> + End Set + End Property + ")> _ +<#+ + string constructorString = string.Empty; + if (!string.IsNullOrEmpty(propertyInitializationValue)) + { + constructorString = " = " + propertyInitializationValue; + } +#> + Private <#= privatePropertyName #> As <#= propertyType #><#= constructorString #> + Partial Private Sub On<#= propertyName #>Changing(ByVal value As <#= propertyType #>) + End Sub + Partial Private Sub On<#= propertyName #>Changed() + End Sub +<#+ + } + + internal override void WriteINotifyPropertyChangedImplementation() + { +#> + ''' + ''' This event is raised when the value of the property is changed + ''' + ")> _ + Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements Global.System.ComponentModel.INotifyPropertyChanged.PropertyChanged + ''' + ''' The value of the property is changed + ''' + ''' property name + ")> _ + Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) + If (Not (Me.PropertyChangedEvent) Is Nothing) Then + RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property])) + End If + End Sub +<#+ + } + + internal override void WriteClassEndForStructuredType() + { +#> + End Class +<#+ + } + + internal override void WriteEnumFlags() + { +#> + +<#+ + } + + internal override void WriteSummaryCommentForEnumType(string enumName) + { +#> + ''' + '''There are no comments for <#= enumName #> in the schema. + ''' +<#+ + } + + internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Enum <#= enumName #><#= underlyingType #> +<#+ + } + + internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + <#= member #> +<#+ + } + + internal override void WriteEnumEnd() + { +#> + End Enum +<#+ + } + + internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + Return Me.CreateFunctionQuery(Of <#= returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #> <#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + Dim requestUri As Global.System.Uri = Nothing + Context.TryGetUri(Me, requestUri) + Return Me.Context.CreateFunctionQuery(Of <#= returnTypeName #>)("", String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))) + "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + Dim requestUri As Global.System.Uri = Nothing + Context.TryGetUri(Me, requestUri) + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.Context.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)(String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))), "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> + Return New <#= returnTypeName #>(Me, Me.BaseUri.OriginalString.Trim("/"C) + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> + Dim resource As Global.Microsoft.OData.Client.EntityDescriptor = Context.EntityTracker.TryGetEntityDescriptor(Me) + If resource Is Nothing Then + Throw New Global.System.Exception("cannot find entity") + End If + + Return New <#= returnTypeName #>(Me.Context, resource.EditLink.OriginalString.Trim("/"C) + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteExtensionMethodsStart() + { +#> + ''' + ''' Class containing all extension methods + ''' + Public Module ExtensionMethods +<#+ + } + + internal override void WriteExtensionMethodsEnd() + { +#> + End Module +<#+ + } + + internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) + { +#> + ''' + ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + ''' + ''' source entity set + ''' dictionary with the names and values of keys + + Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), ByVal keys As Global.System.Collections.Generic.Dictionary(Of String, Object)) As <#= returnTypeName #> + Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) + End Function + ''' + ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + ''' + ''' source entity set +<#+ + foreach (var key in keys) + { +#> + ''' The value of <#= key #> +<#+ + } +#> + + Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), + <#= keyParameters #>) As <#= returnTypeName #> + Dim keys As Global.System.Collections.Generic.Dictionary(Of String, Object) = New Global.System.Collections.Generic.Dictionary(Of String, Object)() From + { + <#= keyDictionaryItems #> + } + Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) + End Function +<#+ + } + + internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) + { +#> + ''' + ''' Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> + ''' + ''' source entity + + Public Function CastTo<#= derivedTypeName #>(ByVal source As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= baseTypeName #>)) As <#= returnTypeName #> + Dim query As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= derivedTypeFullName #>) = source.CastTo(Of <#= derivedTypeFullName #>)() + Return New <#= returnTypeName #>(source.Context, query.GetPath(Nothing)) + End Function +<#+ + } + + internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + + Return source.CreateFunctionQuery(Of <#= returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= actionName #>(ByVal source As <#= boundSourceType #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) As <#= returnTypeName #> + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + Return New <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteNamespaceEnd() + { +#> +End Namespace +<#+ + } +} +#> \ No newline at end of file From 26a52d4b86eb2bf71d3791937c2f7c19b519f04d Mon Sep 17 00:00:00 2001 From: Andrii Snihyr Date: Thu, 28 Mar 2019 17:44:46 -0700 Subject: [PATCH 2/2] fix line-endings --- src/CodeGen/ODataT4CodeGenerator.tt | 178 +- src/CodeGen/ODataT4CodeGenerator.ttinclude | 10558 +++++++++---------- 2 files changed, 5368 insertions(+), 5368 deletions(-) diff --git a/src/CodeGen/ODataT4CodeGenerator.tt b/src/CodeGen/ODataT4CodeGenerator.tt index a7589df3a8..76a0fde213 100644 --- a/src/CodeGen/ODataT4CodeGenerator.tt +++ b/src/CodeGen/ODataT4CodeGenerator.tt @@ -1,89 +1,89 @@ -<#@ include file="ODataT4CodeGenerator.ttinclude" #> -<#+ -public static class Configuration -{ - // The URI of the metadata document. The value must be set to a valid service document URI or a local file path - // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx" - // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of - // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail. - public const string MetadataDocumentUri = ""; - - // The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false. - public const bool UseDataServiceCollection = true; - - // The namespace of the client code generated. It replaces the original namespace in the metadata document, - // unless the model has several namespaces. - public const string NamespacePrefix = "$rootnamespace$"; - - // The target language of the generated client code. The value must be set to "CSharp" or "VB". - public const string TargetLanguage = "OutputLanguage"; - - // The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path. - // For example - "C:\\temp\\Test.xml" - public const string TempFilePath = ""; - - // This flag indicates whether to enable naming alias. The value must be set to true or false. - public const bool EnableNamingAlias = true; - - // This flag indicates whether to ignore unexpected elements and attributes in the metadata document and generate - // the client code if any. The value must be set to true or false. - public const bool IgnoreUnexpectedElementsAndAttributes = true; - - // This flag indicates whether to generate an additional Dictionary property - // to store dynamic properties in open types. The value must be set to true or false. - public const bool GenerateDynamicPropertiesCollection = true; - - // This defines the name of Dictionary properties - // that store dynamic properties in open types. This property is only applicable if - // GenerateDynamicPropertiesCollection is set to true. This value must be - // a valid identifier name. - public const string DynamicPropertiesCollectionName = "DynamicProperties"; -} - -public static class Customization -{ - /// - /// Changes the text to use upper camel case, which upper case for the first character. - /// - /// Text to convert. - /// The converted text in upper camel case - internal static string CustomizeNaming(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return Char.ToUpperInvariant(text[0]).ToString(CultureInfo.InvariantCulture); - } - - return Char.ToUpperInvariant(text[0]) + text.Substring(1); - } - - /// - /// Changes the namespace to use upper camel case, which upper case for the first character of all segments. - /// - /// Namespace to convert. - /// The converted namespace in upper camel case - internal static string CustomizeNamespace(string fullNamespace) - { - if (string.IsNullOrEmpty(fullNamespace)) - { - return fullNamespace; - } - - string[] segs = fullNamespace.Split('.'); - string upperNamespace = string.Empty; - int n = segs.Length; - for (int i = 0; i < n; ++i) - { - upperNamespace += Customization.CustomizeNaming(segs[i]); - upperNamespace += (i == n - 1 ? string.Empty : "."); - } - - return upperNamespace; - } -} -#> +<#@ include file="ODataT4CodeGenerator.ttinclude" #> +<#+ +public static class Configuration +{ + // The URI of the metadata document. The value must be set to a valid service document URI or a local file path + // eg : "http://services.odata.org/V4/OData/OData.svc/", "File:///C:/Odata.edmx", or @"C:\Odata.edmx" + // ### Notice ### If the OData service requires authentication for accessing the metadata document, the value of + // MetadataDocumentUri has to be set to a local file path, or the client code generation process will fail. + public const string MetadataDocumentUri = ""; + + // The use of DataServiceCollection enables entity and property tracking. The value must be set to true or false. + public const bool UseDataServiceCollection = true; + + // The namespace of the client code generated. It replaces the original namespace in the metadata document, + // unless the model has several namespaces. + public const string NamespacePrefix = "$rootnamespace$"; + + // The target language of the generated client code. The value must be set to "CSharp" or "VB". + public const string TargetLanguage = "OutputLanguage"; + + // The path for the temporary file where the metadata xml document can be stored. Use this if your metadata is too big to be stored in a string literal. Ensure that you have write permission for this path. + // For example - "C:\\temp\\Test.xml" + public const string TempFilePath = ""; + + // This flag indicates whether to enable naming alias. The value must be set to true or false. + public const bool EnableNamingAlias = true; + + // This flag indicates whether to ignore unexpected elements and attributes in the metadata document and generate + // the client code if any. The value must be set to true or false. + public const bool IgnoreUnexpectedElementsAndAttributes = true; + + // This flag indicates whether to generate an additional Dictionary property + // to store dynamic properties in open types. The value must be set to true or false. + public const bool GenerateDynamicPropertiesCollection = true; + + // This defines the name of Dictionary properties + // that store dynamic properties in open types. This property is only applicable if + // GenerateDynamicPropertiesCollection is set to true. This value must be + // a valid identifier name. + public const string DynamicPropertiesCollectionName = "DynamicProperties"; +} + +public static class Customization +{ + /// + /// Changes the text to use upper camel case, which upper case for the first character. + /// + /// Text to convert. + /// The converted text in upper camel case + internal static string CustomizeNaming(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return Char.ToUpperInvariant(text[0]).ToString(CultureInfo.InvariantCulture); + } + + return Char.ToUpperInvariant(text[0]) + text.Substring(1); + } + + /// + /// Changes the namespace to use upper camel case, which upper case for the first character of all segments. + /// + /// Namespace to convert. + /// The converted namespace in upper camel case + internal static string CustomizeNamespace(string fullNamespace) + { + if (string.IsNullOrEmpty(fullNamespace)) + { + return fullNamespace; + } + + string[] segs = fullNamespace.Split('.'); + string upperNamespace = string.Empty; + int n = segs.Length; + for (int i = 0; i < n; ++i) + { + upperNamespace += Customization.CustomizeNaming(segs[i]); + upperNamespace += (i == n - 1 ? string.Empty : "."); + } + + return upperNamespace; + } +} +#> diff --git a/src/CodeGen/ODataT4CodeGenerator.ttinclude b/src/CodeGen/ODataT4CodeGenerator.ttinclude index 67d68d988b..95a2a8f24b 100644 --- a/src/CodeGen/ODataT4CodeGenerator.ttinclude +++ b/src/CodeGen/ODataT4CodeGenerator.ttinclude @@ -1,5280 +1,5280 @@ -<# -/* -OData Client T4 Template ver. #VersionNumber# -Copyright (c) Microsoft Corporation -All rights reserved. -MIT License -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#> -<#@ template debug="true" hostSpecific="true" visibility="internal" linePragmas="false"#> -<#@ output extension=".cs" #> -<#@ Assembly Name="System.Core.dll" #> -<#@ Assembly Name="System.IO.dll" #> -<#@ Assembly Name="System.Runtime.dll" #> -<#@ Assembly Name="System.Xml.dll" #> -<#@ Assembly Name="System.Xml.Linq.dll" #> -<#@ Assembly Name="System.Xml.ReaderWriter.dll" #> -<#@ Assembly Name="System.Windows.Forms.dll" #> -<#@ Assembly Name="Microsoft.OData.Client.dll" #> -<#@ Assembly Name="Microsoft.OData.Core.dll" #> -<#@ Assembly Name="Microsoft.OData.Edm.dll" #> -<#@ Assembly Name="Microsoft.Spatial.dll" #> -<#@ Import Namespace="System" #> -<#@ Import Namespace="System.IO" #> -<#@ Import Namespace="System.Diagnostics" #> -<#@ Import Namespace="System.Globalization" #> -<#@ Import Namespace="System.Linq" #> -<#@ Import Namespace="System.Xml"#> -<#@ Import Namespace="System.Xml.Linq" #> -<#@ Import Namespace="System.Collections.Generic" #> -<#@ Import Namespace="Microsoft.OData.Edm.Csdl" #> -<#@ Import Namespace="Microsoft.OData.Edm" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.V1" #> -<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.Community.V1" #> -<#@ Import Namespace="System.Text"#> -<#@ Import Namespace="System.Net"#> -<# - CodeGenerationContext context; - if (!string.IsNullOrWhiteSpace(this.Edmx)) - { - context = new CodeGenerationContext(this.Edmx, this.NamespacePrefix) - { - UseDataServiceCollection = this.UseDataServiceCollection, - TargetLanguage = this.TargetLanguage, - EnableNamingAlias = this.EnableNamingAlias, - TempFilePath = this.TempFilePath, - IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, - GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, - DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName - }; - } - else - { - this.ApplyParametersFromCommandLine(); - if (string.IsNullOrEmpty(metadataDocumentUri)) - { - this.ApplyParametersFromConfigurationClass(); - } - - context = new CodeGenerationContext(new Uri(this.MetadataDocumentUri, UriKind.Absolute), this.NamespacePrefix) - { - UseDataServiceCollection = this.UseDataServiceCollection, - TargetLanguage = this.TargetLanguage, - EnableNamingAlias = this.EnableNamingAlias, - TempFilePath = this.TempFilePath, - IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, - GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, - DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName - }; - } - - if (this.GetReferencedModelReaderFunc != null) - { - context.GetReferencedModelReaderFunc = this.GetReferencedModelReaderFunc; - } - - ODataClientTemplate template; - switch(this.TargetLanguage) - { - case LanguageOption.CSharp: - template = new ODataClientCSharpTemplate(context); - break; - case LanguageOption.VB: - template = new ODataClientVBTemplate(context); - break; - - default: - throw new NotSupportedException(string.Format("Code gen for the target language '{0}' is not supported.", this.TargetLanguage.ToString())); - } - -#><#=template.TransformText()#><# - foreach (string warning in context.Warnings) - { - this.Warning(warning); - } -#><#+ -/// -/// The string for the edmx content. -/// -public string Edmx -{ - get; - set; -} - -/// -/// The Uri string to the metadata document. -/// -public string MetadataDocumentUri -{ - get - { - return this.metadataDocumentUri; - } - - set - { - value = Uri.UnescapeDataString(value); - Uri uri; - if (!Uri.TryCreate(value, UriKind.Absolute, out uri)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" is not a valid MetadataDocumentUri because is it not a valid absolute Uri. The MetadataDocumentUri must be set to an absolute Uri referencing the $metadata endpoint of an OData service.", value)); - } - - if (uri.Scheme == "http" || uri.Scheme == "https") - { - value = uri.Scheme + "://" + uri.Authority + uri.AbsolutePath; - value = value.TrimEnd('/'); - if (!value.EndsWith("$metadata")) - { - value += "/$metadata"; - } - } - - this.metadataDocumentUri = value; - } -} - -private string metadataDocumentUri; - -/// -/// The Func to get referenced model's XmlReader. Must have value when the this.Edmx xml or this.metadataDocumentUri's model has referneced model. -/// -public Func GetReferencedModelReaderFunc -{ - get; - set; -} - -/// -/// The NamespacePrefix is used as the only namespace for types in the same namespace as the default container, -/// and as a prefix for the namespace from the model for everything else. If this argument is null, the -/// namespaces from the model are used for all types. -/// -public string NamespacePrefix -{ - get - { - return this.namespacePrefix; - } - - set - { - if (string.IsNullOrWhiteSpace(value)) - { - this.namespacePrefix = null; - } - else - { - this.namespacePrefix = value; - } - } -} - -private string namespacePrefix; - -/// -/// true to use DataServiceCollection in the generated code, false otherwise. -/// -public bool UseDataServiceCollection -{ - get; - set; -} - -/// -/// Specifies which specific .Net Framework language the generated code will target. -/// -public LanguageOption TargetLanguage -{ - get; - set; -} - -/// -/// true to use Upper camel case for all class and property names, false otherwise. -/// -public bool EnableNamingAlias -{ - get; - set; -} - -/// -/// The path for the temporary file where the metadata xml document can be stored. -/// -public string TempFilePath -{ - get; - set; -} - -/// -/// true to ignore unknown elements or attributes in metadata, false otherwise. -/// -public bool IgnoreUnexpectedElementsAndAttributes -{ - get; - set; -} - - /// - /// true to generate open type property dirctionary, false otherwise. - /// - public bool GenerateDynamicPropertiesCollection - { - get; - set; - } - - /// - /// Name of the OpenType dictionary property - /// - public string DynamicPropertiesCollectionName - { - get; - set; - } - -/// -/// Generate code targeting a specific .Net Framework language. -/// -public enum LanguageOption -{ - /// Generate code for C# language. - CSharp = 0, - - /// Generate code for Visual Basic language. - VB = 1, -} - -/// -/// Set the UseDataServiceCollection property with the given value. -/// -/// The value to set. -public void ValidateAndSetUseDataServiceCollectionFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the UseDataServiceCollection parameter because it is not a valid boolean value.", stringValue)); - } - - this.UseDataServiceCollection = boolValue; -} - -/// -/// Tries to set the TargetLanguage property with the given value. -/// -/// The value to set. -public void ValidateAndSetTargetLanguageFromString(string stringValue) -{ - LanguageOption option; - if (!Enum.TryParse(stringValue, true, out option)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the TargetLanguage parameter because it is not a valid LanguageOption. The supported LanguageOptions are \"CSharp\" and \"VB\".", stringValue)); - } - - this.TargetLanguage = option; -} - -/// -/// Set the EnableNamingAlias property with the given value. -/// -/// The value to set. -public void ValidateAndSetEnableNamingAliasFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the EnableNamingAlias parameter because it is not a valid boolean value.", stringValue)); - } - - this.EnableNamingAlias = boolValue; -} - -/// -/// Set the IgnoreUnexpectedElementsAndAttributes property with the given value. -/// -/// The value to set. -public void ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the IgnoreUnexpectedElementsAndAttributes parameter because it is not a valid boolean value.", stringValue)); - } - - this.IgnoreUnexpectedElementsAndAttributes = boolValue; -} - -/// -/// Set the GenerateDynamicPropertiesCollection property with the given value. -/// -/// The value to set. -public void ValidateAndSetGenerateDynamicPropertiesCollectionFromString(string stringValue) -{ - bool boolValue; - if (!bool.TryParse(stringValue, out boolValue)) - { - // ******************************************************************************************************** - // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator - // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter - // value then hit Ctrl-S to save the .tt file to refresh the code generation. - // ******************************************************************************************************** - throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the GenerateDynamicPropertiesCollection parameter because it is not a valid boolean value.", stringValue)); - } - - this.GenerateDynamicPropertiesCollection = boolValue; -} - -/// -/// Reads the parameter values from the Configuration class and applies them. -/// -private void ApplyParametersFromConfigurationClass() -{ - this.MetadataDocumentUri = Configuration.MetadataDocumentUri; - this.NamespacePrefix = Configuration.NamespacePrefix; - this.UseDataServiceCollection = Configuration.UseDataServiceCollection; - this.ValidateAndSetTargetLanguageFromString(Configuration.TargetLanguage); - this.EnableNamingAlias = Configuration.EnableNamingAlias; - this.TempFilePath = Configuration.TempFilePath; - this.IgnoreUnexpectedElementsAndAttributes = Configuration.IgnoreUnexpectedElementsAndAttributes; - this.GenerateDynamicPropertiesCollection = Configuration.GenerateDynamicPropertiesCollection; - this.DynamicPropertiesCollectionName = Configuration.DynamicPropertiesCollectionName; -} - -/// -/// Reads the parameter values from the command line (TextTransform.exe) and applies them. -/// -private void ApplyParametersFromCommandLine() -{ - if (this.Host == null) - { - return; - } - - string metadataDocumentUri = this.Host.ResolveParameterValue("notempty", "notempty", "MetadataDocumentUri"); - if (!string.IsNullOrEmpty(metadataDocumentUri)) - { - this.MetadataDocumentUri = metadataDocumentUri; - } - - string namespacePrefix = this.Host.ResolveParameterValue("notempty", "notempty", "NamespacePrefix"); - if (!string.IsNullOrEmpty(namespacePrefix)) - { - this.NamespacePrefix = namespacePrefix; - } - - string useDataServiceCollection = this.Host.ResolveParameterValue("notempty", "notempty", "UseDataServiceCollection"); - if (!string.IsNullOrEmpty(useDataServiceCollection)) - { - this.ValidateAndSetUseDataServiceCollectionFromString(useDataServiceCollection); - } - - string targetLanguage = this.Host.ResolveParameterValue("notempty", "notempty", "TargetLanguage"); - if (!string.IsNullOrEmpty(targetLanguage)) - { - this.ValidateAndSetTargetLanguageFromString(targetLanguage); - } - - string enableNamingAlias = this.Host.ResolveParameterValue("notempty", "notempty", "EnableNamingAlias"); - if (!string.IsNullOrEmpty(enableNamingAlias)) - { - this.ValidateAndSetEnableNamingAliasFromString(enableNamingAlias); - } - - string ignoreUnexpectedElementsAndAttributes = this.Host.ResolveParameterValue("notempty", "notempty", "IgnoreUnexpectedElementsAndAttributes"); - if (!string.IsNullOrEmpty(ignoreUnexpectedElementsAndAttributes)) - { - this.ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(ignoreUnexpectedElementsAndAttributes); - } - - string generateDynamicPropertiesCollection = this.Host.ResolveParameterValue("notempty", "notempty", "GenerateDynamicPropertiesCollection"); - if (!string.IsNullOrEmpty(generateDynamicPropertiesCollection)) - { - this.ValidateAndSetGenerateDynamicPropertiesCollectionFromString(generateDynamicPropertiesCollection); - } - - string dynamicPropertiesCollectionName = this.Host.ResolveParameterValue("notempty", "notempty", "DynamicPropertiesCollectionName"); - if (!string.IsNullOrEmpty(dynamicPropertiesCollectionName)) - { - this.DynamicPropertiesCollectionName = dynamicPropertiesCollectionName; - } -} - -/// -/// Context object to provide the model and configuration info to the code generator. -/// -public class CodeGenerationContext -{ - /// - /// The namespace of the term to use when building annotations for indicating the conventions used. - /// - private const string ConventionTermNamespace = "Com.Microsoft.OData.Service.Conventions.V1"; - - /// - /// The name of the term to use when building annotations for indicating the conventions used. - /// - private const string ConventionTermName = "UrlConventions"; - - /// - /// The string value for indicating that the key-as-segment convention is being used in annotations and headers. - /// - private const string KeyAsSegmentConventionName = "KeyAsSegment"; - - /// - /// The XElement for the edmx - /// - private readonly XElement edmx; - - /// - /// The namespacePrefix is used as the only namespace in generated code when there's only one schema in edm model, - /// and as a prefix for the namespace from the model with multiple schemas. If this argument is null, the - /// namespaces from the model are used for all types. - /// - private readonly string namespacePrefix; - - /// - /// The EdmModel to generate code for. - /// - private IEdmModel edmModel; - - /// - /// The array of namespaces in the current edm model. - /// - private string[] namespacesInModel; - - /// - /// The array of warnings occured when parsing edm model. - /// - private string[] warnings; - - /// - /// true if the model contains any structural type with inheritance, false otherwise. - /// - private bool? modelHasInheritance; - - /// - /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. - /// Otherwise this is an empty dictionary. - /// - private Dictionary namespaceMap; - - /// - /// Maps the element type of a navigation source to the navigation source. - /// - private Dictionary> elementTypeToNavigationSourceMap; - - /// - /// HashSet contains the pair of Names and Namespaces of EntityContainers using KeyAsSegment url convention - /// - private HashSet keyAsSegmentContainers; - - /// - /// Constructs an instance of . - /// - /// The Uri to the metadata document. The supported scheme are File, http and https. - public CodeGenerationContext(Uri metadataUri, string namespacePrefix) - : this(GetEdmxStringFromMetadataPath(metadataUri), namespacePrefix) - { - } - - /// - /// Constructs an instance of . - /// - /// The string for the edmx. - /// The namespacePrefix is used as the only namespace in generated code - /// when there's only one schema in edm model, and as a prefix for the namespace from the model with multiple - /// schemas. If this argument is null, the namespaces from the model are used for all types. - public CodeGenerationContext(string edmx, string namespacePrefix) - { - this.edmx = XElement.Parse(edmx); - this.namespacePrefix = namespacePrefix; - } - - /// - /// The EdmModel to generate code for. - /// - public XElement Edmx - { - get { return this.edmx; } - } - - /// - /// The EdmModel to generate code for. - /// - public IEdmModel EdmModel - { - get - { - if (this.edmModel == null) - { - Debug.Assert(this.edmx != null, "this.edmx != null"); - - IEnumerable errors; - CsdlReaderSettings edmxReaderSettings = new CsdlReaderSettings() - { - GetReferencedModelReaderFunc = this.GetReferencedModelReaderFuncWrapper, - IgnoreUnexpectedAttributesAndElements = this.IgnoreUnexpectedElementsAndAttributes - }; - if (!CsdlReader.TryParse(this.edmx.CreateReader(ReaderOptions.None), Enumerable.Empty(), edmxReaderSettings, out this.edmModel, out errors)) - { - Debug.Assert(errors != null, "errors != null"); - throw new InvalidOperationException(errors.FirstOrDefault().ErrorMessage); - } - else if (this.IgnoreUnexpectedElementsAndAttributes) - { - if (errors != null && errors.Any()) - { - this.warnings = errors.Select(e => e.ErrorMessage).ToArray(); - } - } - } - - return this.edmModel; - } - } - - /// - /// The func for user code to overwrite and provide referenced model's XmlReader. - /// - public Func GetReferencedModelReaderFunc - { - get { return getReferencedModelReaderFunc; } - set { this.getReferencedModelReaderFunc = value; } - } - - /// - /// Basic setting for XmlReader. - /// - private static readonly XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true }; - - /// - /// The func for user code to overwrite and provide referenced model's XmlReader. - /// - private Func getReferencedModelReaderFunc = uri => XmlReader.Create(GetEdmxStreamFromUri(uri), settings); - - /// - /// The Wrapper func for user code to overwrite and provide referenced model's stream. - /// - public Func GetReferencedModelReaderFuncWrapper - { - get - { - return (uri) => - { - using (XmlReader reader = GetReferencedModelReaderFunc(uri)) - { - if (reader == null) - { - return null; - } - - XElement element = XElement.Load(reader); - if (this.ReferencesMap == null) - { - this.ReferencesMap = new Dictionary(); - } - - this.ReferencesMap.Add(uri, element); - return element.CreateReader(ReaderOptions.None); - } - }; - } - } - - /// - /// Dictionary that stores uri and referenced xml mapping. - /// - public Dictionary ReferencesMap - { - get; - set; - } - - /// - /// The array of namespaces in the current edm model. - /// - public string[] NamespacesInModel - { - get - { - if (this.namespacesInModel == null) - { - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - this.namespacesInModel = GetElementsFromModelTree(this.EdmModel, (m) => m.SchemaElements.Select(e => e.Namespace)).Distinct().ToArray(); - } - - return this.namespacesInModel; - } - } - - /// - /// The array of warnings occured when parsing edm model. - /// - public string[] Warnings - { - get { return this.warnings ?? (this.warnings = new string[] {}); } - } - - /// - /// true if the model contains any structural type with inheritance, false otherwise. - /// - public bool ModelHasInheritance - { - get - { - if (!this.modelHasInheritance.HasValue) - { - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - this.modelHasInheritance = this.EdmModel.SchemaElementsAcrossModels() - .OfType().Any(t => !t.FullTypeName().StartsWith("Org.OData.Authorization.V1") && t.BaseType != null); - } - - return this.modelHasInheritance.Value; - } - } - - /// - /// true if we need to generate the ResolveNameFromType method, false otherwise. - /// - public bool NeedResolveNameFromType - { - get { return this.ModelHasInheritance || this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } - } - - /// - /// true if we need to generate the ResolveTypeFromName method, false otherwise. - /// - public bool NeedResolveTypeFromName - { - get { return this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } - } - - /// - /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. - /// Otherwise this is an empty dictionary. - /// - public Dictionary NamespaceMap - { - get - { - if (this.namespaceMap == null) - { - if (!string.IsNullOrEmpty(this.namespacePrefix)) - { - if (this.NamespacesInModel.Count() == 1) - { - IEdmEntityContainer container = this.EdmModel.EntityContainer; - string containerNamespace = container == null ? null : container.Namespace; - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => ns == containerNamespace ? - this.namespacePrefix : - this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); - } - else - { - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); - } - } - else if (this.EnableNamingAlias) - { - this.namespaceMap = this.NamespacesInModel - .Distinct() - .ToDictionary( - ns => ns, - ns => Customization.CustomizeNamespace(ns)); - } - else - { - this.namespaceMap = new Dictionary(); - } - } - - return this.namespaceMap; - } - } - - /// - /// true to use DataServiceCollection in the generated code, false otherwise. - /// - public bool UseDataServiceCollection - { - get; - set; - } - - /// - /// Specifies which specific .Net Framework language the generated code will target. - /// - public LanguageOption TargetLanguage - { - get; - set; - } - - /// - /// The path for the temporary file where the metadata xml document can be stored. - /// - public string TempFilePath - { - get; - set; - } - /// - /// true to use Upper camel case for all class and property names, false otherwise. - /// - public bool EnableNamingAlias - { - get; - set; - } - - /// - /// true to ignore unknown elements or attributes in metadata, false otherwise. - /// - public bool IgnoreUnexpectedElementsAndAttributes - { - get; - set; - } - - /// - /// true to generate open type property dirctionary, false otherwise. - /// - public bool GenerateDynamicPropertiesCollection - { - get; - set; - } - - /// - /// Name of the OpenType dictionary property - /// - public string DynamicPropertiesCollectionName - { - get; - set; - } - - /// - /// Maps the element type of an entity set to the entity set. - /// - public Dictionary> ElementTypeToNavigationSourceMap - { - get - { - return this.elementTypeToNavigationSourceMap ?? (this.elementTypeToNavigationSourceMap = new Dictionary>(EqualityComparer.Default)); - } - } - - /// - /// true if this EntityContainer need to set the UrlConvention to KeyAsSegment, false otherwise. - /// - public bool UseKeyAsSegmentUrlConvention(IEdmEntityContainer currentContainer) - { - if (this.keyAsSegmentContainers == null) - { - this.keyAsSegmentContainers = new HashSet(); - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - IEnumerable annotations = this.EdmModel.VocabularyAnnotations; - foreach(IEdmVocabularyAnnotation valueAnnotation in annotations) - { - IEdmEntityContainer container = valueAnnotation.Target as IEdmEntityContainer; - IEdmTerm valueTerm = valueAnnotation.Term; - IEdmStringConstantExpression expression = valueAnnotation.Value as IEdmStringConstantExpression; - if (container != null && valueTerm != null && expression != null) - { - if (valueTerm.Namespace == ConventionTermNamespace && - valueTerm.Name == ConventionTermName && - expression.Value == KeyAsSegmentConventionName) - { - this.keyAsSegmentContainers.Add(container.FullName()); - } - } - } - } - - return this.keyAsSegmentContainers.Contains(currentContainer.FullName()); - } - - /// - /// Gets the enumeration of schema elements with the given namespace. - /// - /// The namespace of the schema elements to get. - /// The enumeration of schema elements with the given namespace. - public IEnumerable GetSchemaElements(string ns) - { - Debug.Assert(ns != null, "ns != null"); - Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); - return GetElementsFromModelTree(this.EdmModel, m => m.SchemaElements.Where(e => e.Namespace == ns)); - } - - /// - /// Gets the namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. - /// - /// The schema element to get the full name for. - /// The fixed name of this schemaElement. - /// The current code generate template. - /// The namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. - public string GetPrefixedFullName(IEdmSchemaElement schemaElement, string schemaElementFixedName, ODataClientTemplate template, bool needGlobalPrefix = true) - { - if (schemaElement == null) - { - return null; - } - - return this.GetPrefixedNamespace(schemaElement.Namespace, template, true, needGlobalPrefix) + "." + schemaElementFixedName; - } - - /// - /// Gets the prefixed namespace for the given . - /// - /// The namespace without the prefix. - /// The current code generate template. - /// The flag indicates whether the namespace need to be fixed now. - /// The flag indicates whether the namespace need to be added by gloabal prefix. - /// The prefixed namespace for the given . - public string GetPrefixedNamespace(string ns, ODataClientTemplate template, bool needFix, bool needGlobalPrefix) - { - if (ns == null) - { - return null; - } - - string prefixedNamespace; - if (!this.NamespaceMap.TryGetValue(ns, out prefixedNamespace)) - { - prefixedNamespace = ns; - } - - if (needFix) - { - string[] segments = prefixedNamespace.Split('.'); - prefixedNamespace = string.Empty; - int n = segments.Length; - for (int i = 0; i < n; ++i) - { - if (template.LanguageKeywords.Contains(segments[i])) - { - prefixedNamespace += string.Format(template.FixPattern, segments[i]); - } - else - { - prefixedNamespace += segments[i]; - } - - prefixedNamespace += (i == n - 1 ? string.Empty : "."); - } - } - - if (needGlobalPrefix) - { - prefixedNamespace = template.GlobalPrefix + prefixedNamespace; - } - - return prefixedNamespace; - } - - /// - /// Reads the edmx string from a file path or a http/https path. - /// - /// The Uri to the metadata document. The supported scheme are File, http and https. - private static string GetEdmxStringFromMetadataPath(Uri metadataUri) - { - string content = null; - using (StreamReader streamReader = new StreamReader(GetEdmxStreamFromUri(metadataUri))) - { - content = streamReader.ReadToEnd(); - } - - return content; - } - - /// - /// Get the metadata stream from a file path or a http/https path. - /// - /// The Uri to the stream. The supported scheme are File, http and https. - private static Stream GetEdmxStreamFromUri(Uri metadataUri) - { - Debug.Assert(metadataUri != null, "metadataUri != null"); - Stream metadataStream = null; - if (metadataUri.Scheme == "file") - { - metadataStream = new FileStream(Uri.UnescapeDataString(metadataUri.AbsolutePath), FileMode.Open, FileAccess.Read); - } - else if (metadataUri.Scheme == "http" || metadataUri.Scheme == "https") - { - try - { - HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(metadataUri); - WebResponse webResponse = webRequest.GetResponse(); - metadataStream = webResponse.GetResponseStream(); - } - catch (WebException e) - { - HttpWebResponse webResponse = e.Response as HttpWebResponse; - if (webResponse != null && webResponse.StatusCode == HttpStatusCode.Unauthorized) - { - throw new WebException("Failed to access the metadata document. The OData service requires authentication for accessing it. Please download the metadata, store it into a local file, and set the value of “MetadataDocumentUri” in the .odata.config file to the file path. After that, run custom tool again to generate the OData Client code."); - } - else - { - throw e; - } - } - } - else - { - throw new ArgumentException("Only file, http, https schemes are supported for paths to metadata source locations."); - } - - return metadataStream; - } - - private static IEnumerable GetElementsFromModelTree(IEdmModel mainModel, Func> getElementFromOneModelFunc) - { - List ret = new List(); - if(mainModel is EdmCoreModel || mainModel.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null) - { - return ret; - } - - ret.AddRange(getElementFromOneModelFunc(mainModel)); - foreach (var tmp in mainModel.ReferencedModels) - { - if (tmp is EdmCoreModel || - tmp.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null || - tmp.FindDeclaredTerm(CapabilitiesVocabularyConstants.ChangeTracking) != null || - tmp.FindDeclaredTerm(AlternateKeysVocabularyConstants.AlternateKeys) != null || - tmp.FindDeclaredTerm("Org.OData.Authorization.V1.Authorizations") != null) - { - continue; - } - - ret.AddRange(getElementFromOneModelFunc(tmp)); - } - - return ret; - } -} - -/// -/// The template class to generate the OData client code. -/// -public abstract class ODataClientTemplate : TemplateBase -{ - protected const string T4Version = "#VersionNumber#"; - - /// - /// The code generation context. - /// - protected readonly CodeGenerationContext context; - - /// - /// The Dictionary to store identifier mappings when there are duplicate names between properties and Entity/Complex types - /// - protected Dictionary IdentifierMappings = new Dictionary(StringComparer.Ordinal); - - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The code generation context. - public ODataClientTemplate(CodeGenerationContext context) - { - this.context = context; - } - - internal string SingleSuffix - { - get { return "Single"; } - } - - #region Get Language specific keyword names. - internal abstract string GlobalPrefix { get; } - internal abstract string SystemTypeTypeName { get; } - internal abstract string AbstractModifier { get; } - internal abstract string DataServiceActionQueryTypeName { get; } - internal abstract string DataServiceActionQuerySingleOfTStructureTemplate { get; } - internal abstract string DataServiceActionQueryOfTStructureTemplate { get; } - internal abstract string NotifyPropertyChangedModifier { get; } - internal abstract string ClassInheritMarker { get; } - internal abstract string ParameterSeparator { get; } - internal abstract string KeyParameterSeparator { get; } - internal abstract string KeyDictionaryItemSeparator { get; } - internal abstract string SystemNullableStructureTemplate { get; } - internal abstract string ICollectionOfTStructureTemplate { get; } - internal abstract string DataServiceCollectionStructureTemplate { get; } - internal abstract string DataServiceQueryStructureTemplate { get; } - internal abstract string DataServiceQuerySingleStructureTemplate { get; } - internal abstract string ObservableCollectionStructureTemplate { get; } - internal abstract string ObjectModelCollectionStructureTemplate { get; } - internal abstract string DataServiceCollectionConstructorParameters { get; } - internal abstract string NewModifier { get; } - internal abstract string GeoTypeInitializePattern { get; } - internal abstract string Int32TypeName { get; } - internal abstract string ObjectTypeName { get; } - internal abstract string StringTypeName { get; } - internal abstract string BinaryTypeName { get; } - internal abstract string DecimalTypeName { get; } - internal abstract string Int16TypeName { get; } - internal abstract string SingleTypeName { get; } - internal abstract string BooleanTypeName { get; } - internal abstract string DoubleTypeName { get; } - internal abstract string GuidTypeName { get; } - internal abstract string ByteTypeName { get; } - internal abstract string Int64TypeName { get; } - internal abstract string SByteTypeName { get; } - internal abstract string DataServiceStreamLinkTypeName { get; } - internal abstract string GeographyTypeName { get; } - internal abstract string GeographyPointTypeName { get; } - internal abstract string GeographyLineStringTypeName { get; } - internal abstract string GeographyPolygonTypeName { get; } - internal abstract string GeographyCollectionTypeName { get; } - internal abstract string GeographyMultiPolygonTypeName { get; } - internal abstract string GeographyMultiLineStringTypeName { get; } - internal abstract string GeographyMultiPointTypeName { get; } - internal abstract string GeometryTypeName { get; } - internal abstract string GeometryPointTypeName { get; } - internal abstract string GeometryLineStringTypeName { get; } - internal abstract string GeometryPolygonTypeName { get; } - internal abstract string GeometryCollectionTypeName { get; } - internal abstract string GeometryMultiPolygonTypeName { get; } - internal abstract string GeometryMultiLineStringTypeName { get; } - internal abstract string GeometryMultiPointTypeName { get; } - internal abstract string DateTypeName { get; } - internal abstract string DateTimeOffsetTypeName { get; } - internal abstract string DurationTypeName { get; } - internal abstract string TimeOfDayTypeName { get; } - internal abstract string XmlConvertClassName { get; } - internal abstract string EnumTypeName { get; } - internal abstract string DictionaryTypeName { get; } - internal abstract HashSet LanguageKeywords { get; } - internal abstract string FixPattern { get; } - internal abstract string EnumUnderlyingTypeMarker { get; } - internal abstract string ConstantExpressionConstructorWithType { get; } - internal abstract string TypeofFormatter { get; } - internal abstract string UriOperationParameterConstructor { get; } - internal abstract string UriEntityOperationParameterConstructor { get; } - internal abstract string BodyOperationParameterConstructor { get; } - internal abstract string DictionaryConstructor { get; } - internal abstract string BaseEntityType { get; } - internal abstract string OverloadsModifier { get; } - internal abstract string ODataVersion { get; } - internal abstract string ParameterDeclarationTemplate { get; } - internal abstract string DictionaryItemConstructor { get; } - #endregion Get Language specific keyword names. - - #region Language specific write methods. - internal abstract void WriteFileHeader(); - internal abstract void WriteNamespaceStart(string fullNamespace); - internal abstract void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName); - internal abstract void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName); - internal abstract void WriteKeyAsSegmentUrlConvention(); - internal abstract void WriteInitializeResolveName(); - internal abstract void WriteInitializeResolveType(); - internal abstract void WriteClassEndForEntityContainerConstructor(); - internal abstract void WriteMethodStartForResolveTypeFromName(); - internal abstract void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace); - internal abstract void WriteMethodEndForResolveTypeFromName(); - internal abstract void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace); - internal abstract void WriteResolveType(string fullNamespace, string languageDependentNamespace); - internal abstract void WriteMethodEndForResolveNameFromType(bool modelHasInheritance); - internal abstract void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext = true); - internal abstract void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext = true); - internal abstract void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName); - internal abstract void WriteGeneratedEdmModel(string escapedEdmxString); - internal abstract void WriteClassEndForEntityContainer(); - internal abstract void WriteSummaryCommentForStructuredType(string typeName); - internal abstract void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString); - internal abstract void WriteEntityTypeAttribute(); - internal abstract void WriteEntitySetAttribute(string entitySetName); - internal abstract void WriteEntityHasStreamAttribute(); - internal abstract void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName); - internal abstract void WriteSummaryCommentForStaticCreateMethod(string typeName); - internal abstract void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName); - internal abstract void WriteDeclarationStartForStaticCreateMethod(string typeName,string fixedTypeName ); - internal abstract void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater); - internal abstract void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName); - internal abstract void WriteParameterNullCheckForStaticCreateMethod(string parameterName); - internal abstract void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName); - internal abstract void WriteMethodEndForStaticCreateMethod(string instanceName); - internal abstract void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged); - internal abstract void WriteINotifyPropertyChangedImplementation(); - internal abstract void WriteClassEndForStructuredType(); - internal abstract void WriteNamespaceEnd(); - internal abstract void WriteEnumFlags(); - internal abstract void WriteSummaryCommentForEnumType(string enumName); - internal abstract void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType); - internal abstract void WriteMemberForEnumType(string member, string originalMemberName, bool last); - internal abstract void WriteEnumEnd(); - internal abstract void WritePropertyRootNamespace(string containerName, string fullNamespace); - internal abstract void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues); - internal abstract void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues); - internal abstract void WriteConstructorForSingleType(string singleTypeName, string baseTypeName); - internal abstract void WriteExtensionMethodsStart(); - internal abstract void WriteExtensionMethodsEnd(); - internal abstract void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems); - internal abstract void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName); - internal abstract void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); - internal abstract void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); - internal abstract void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues); - #endregion Language specific write methods. - - internal HashSet ClrReferenceTypes { get { - if (clrReferenceTypes == null) - { - clrReferenceTypes = new HashSet() - { - EdmPrimitiveTypeKind.String, EdmPrimitiveTypeKind.Binary, EdmPrimitiveTypeKind.Geography, EdmPrimitiveTypeKind.Stream, - EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeographyPolygon, - EdmPrimitiveTypeKind.GeographyCollection, EdmPrimitiveTypeKind.GeographyMultiPolygon, EdmPrimitiveTypeKind.GeographyMultiLineString, - EdmPrimitiveTypeKind.GeographyMultiPoint, EdmPrimitiveTypeKind.Geometry, EdmPrimitiveTypeKind.GeometryPoint, - EdmPrimitiveTypeKind.GeometryLineString, EdmPrimitiveTypeKind.GeometryPolygon, EdmPrimitiveTypeKind.GeometryCollection, - EdmPrimitiveTypeKind.GeometryMultiPolygon, EdmPrimitiveTypeKind.GeometryMultiLineString, EdmPrimitiveTypeKind.GeometryMultiPoint - }; - } - return clrReferenceTypes; - } } - private HashSet clrReferenceTypes; - - /// - /// Generates code for the OData client. - /// - /// The generated code for the OData client. - public override string TransformText() - { - this.WriteFileHeader(); - this.WriteNamespaces(); - return this.GenerationEnvironment.ToString(); - } - - internal void WriteNamespaces() - { - foreach(string fullNamespace in context.NamespacesInModel) - { - this.WriteNamespace(fullNamespace); - } - } - - internal void WriteNamespace(string fullNamespace) - { - this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false)); - - IEdmSchemaElement[] schemaElements = this.context.GetSchemaElements(fullNamespace).ToArray(); - if (schemaElements.OfType().Any()) { - IEdmEntityContainer container = schemaElements.OfType().Single(); - this.WriteEntityContainer(container, fullNamespace); - } - - Dictionary> boundOperationsMap = new Dictionary>(); - foreach (IEdmOperation operation in schemaElements.OfType()) - { - if (operation.IsBound) - { - IEdmType edmType = operation.Parameters.First().Type.Definition; - IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType; - if (edmStructuredType != null) - { - List operationList; - if (!boundOperationsMap.TryGetValue(edmStructuredType, out operationList)) - { - operationList = new List(); - } - - operationList.Add(operation); - boundOperationsMap[edmStructuredType] = operationList; - } - } - } - - Dictionary> structuredBaseTypeMap = new Dictionary>(); - foreach(IEdmSchemaType type in schemaElements.OfType()) - { - IEdmEnumType enumType = type as IEdmEnumType; - if (enumType != null) - { - this.WriteEnumType(enumType); - } - else - { - IEdmComplexType complexType = type as IEdmComplexType; - if (complexType != null) - { - this.WriteComplexType(complexType, boundOperationsMap); - } - else - { - IEdmEntityType entityType = type as IEdmEntityType; - this.WriteEntityType(entityType, boundOperationsMap); - } - - IEdmStructuredType structuredType = type as IEdmStructuredType; - if (structuredType.BaseType != null) - { - List derivedTypes; - if (!structuredBaseTypeMap.TryGetValue(structuredType.BaseType, out derivedTypes)) - { - structuredBaseTypeMap[structuredType.BaseType] = new List(); - } - - structuredBaseTypeMap[structuredType.BaseType].Add(structuredType); - } - } - } - - if (schemaElements.OfType().Any() || - schemaElements.OfType().Any(o => o.IsBound)) - { - this.WriteExtensionMethodsStart(); - foreach (IEdmEntityType type in schemaElements.OfType()) - { - string entityTypeName = type.Name; - entityTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; - string entityTypeFullName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName), this); - string returnTypeName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName + this.SingleSuffix), this); - - var keyProperties = type.Key(); - if(keyProperties != null && keyProperties.Any()) - { - List keyParameters = new List(); - List keyDictionaryItems = new List(); - List keyNames = new List(); - foreach (IEdmProperty key in keyProperties) - { - string typeName = Utils.GetClrTypeName(key.Type, this.context.UseDataServiceCollection, this, this.context); - string keyName = Utils.CamelCase(key.Name); - keyNames.Add(keyName); - keyParameters.Add(string.Format(this.ParameterDeclarationTemplate, typeName, this.GetFixedName(keyName))); - keyDictionaryItems.Add(string.Format(this.DictionaryItemConstructor, "\"" + key.Name + "\"", this.GetFixedName(keyName))); - } - - string keyParametersString = string.Join(this.KeyParameterSeparator, keyParameters); - string keyDictionaryItemsString = string.Join(this.KeyDictionaryItemSeparator, keyDictionaryItems); - this.WriteByKeyMethods(entityTypeFullName, returnTypeName, keyNames, keyParametersString, keyDictionaryItemsString); - } - - IEdmEntityType current = (IEdmEntityType)type.BaseType; - while (current != null) - { - string baseTypeName = current.Name; - baseTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(baseTypeName) : baseTypeName; - baseTypeName = context.GetPrefixedFullName(current, GetFixedName(baseTypeName), this); - this.WriteCastToMethods(baseTypeName, entityTypeName, entityTypeFullName, returnTypeName); - current = (IEdmEntityType)current.BaseType; - } - } - - HashSet boundOperations = new HashSet(StringComparer.Ordinal); - foreach (IEdmFunction function in schemaElements.OfType()) - { - if (function.IsBound) - { - IEdmTypeReference edmTypeReference = function.Parameters.First().Type; - string functionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(function.Name) : function.Name; - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); - string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); - string fixedFunctionName = GetFixedName(functionName); - string func = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); - - if (!boundOperations.Contains(func)) - { - boundOperations.Add(func); - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - - IEdmStructuredType structuredType; - if (edmTypeReference.IsCollection()) - { - IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; - structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; - } - else - { - structuredType = (IEdmStructuredType)edmTypeReference.Definition; - } - - List derivedTypes; - if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) - { - foreach (IEdmStructuredType type in derivedTypes) - { - IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); - List currentParameters = function.Parameters.Select(p => p.Type).ToList(); - currentParameters[0] = derivedTypeReference; - - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); - string currentFunc = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(currentFunc)) - { - boundOperations.Add(currentFunc); - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - } - } - } - } - - foreach (IEdmAction action in schemaElements.OfType()) - { - if (action.IsBound) - { - IEdmTypeReference edmTypeReference = action.Parameters.First().Type; - string actionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(action.Name) : action.Name; - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); - string returnTypeName; - if (action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); - if (action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string fixedActionName = GetFixedName(actionName); - string ac = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(ac)) - { - boundOperations.Add(ac); - this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); - } - - IEdmStructuredType structuredType; - if (edmTypeReference.IsCollection()) - { - IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; - structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; - } - else - { - structuredType = (IEdmStructuredType)edmTypeReference.Definition; - } - - List derivedTypes; - if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) - { - foreach (IEdmStructuredType type in derivedTypes) - { - IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); - List currentParameters = action.Parameters.Select(p => p.Type).ToList(); - currentParameters[0] = derivedTypeReference; - - sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); - string currentAc = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); - if (!boundOperations.Contains(currentAc)) - { - boundOperations.Add(currentAc); - this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); - } - } - } - } - } - - this.WriteExtensionMethodsEnd(); - } - - this.WriteNamespaceEnd(); - } - - internal bool HasBoundOperations(IEnumerable operations) - { - foreach (IEdmOperation opeartion in operations) - { - if (opeartion.IsBound) - { - return true; - } - } - - return false; - } - - internal void WriteEntityContainer(IEdmEntityContainer container, string fullNamespace) - { - string camelCaseContainerName = container.Name; - if (this.context.EnableNamingAlias) - { - camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); - } - - this.WriteClassStartForEntityContainer(container.Name, camelCaseContainerName, GetFixedName(camelCaseContainerName)); - this.WriteEntityContainerConstructor(container); - - if (this.context.NeedResolveNameFromType) - { - this.WritePropertyRootNamespace(GetFixedName(camelCaseContainerName), this.context.GetPrefixedNamespace(fullNamespace, this, false, false)); - } - - this.WriteResolveTypeFromName(); - this.WriteResolveNameFromType(camelCaseContainerName, fullNamespace); - - foreach (IEdmEntitySet entitySet in container.EntitySets()) - { - IEdmEntityType entitySetElementType = entitySet.EntityType(); - string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); - - string camelCaseEntitySetName = entitySet.Name; - if (this.context.EnableNamingAlias) - { - camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); - } - - this.WriteContextEntitySetProperty(camelCaseEntitySetName, GetFixedName(camelCaseEntitySetName), entitySet.Name, GetFixedName(entitySetElementTypeName)); - List edmNavigationSourceList = null; - if (!this.context.ElementTypeToNavigationSourceMap.TryGetValue(entitySet.EntityType(), out edmNavigationSourceList)) - { - edmNavigationSourceList = new List(); - this.context.ElementTypeToNavigationSourceMap.Add(entitySet.EntityType(), edmNavigationSourceList); - } - - edmNavigationSourceList.Add(entitySet); - } - - foreach (IEdmEntitySet entitySet in container.EntitySets()) - { - IEdmEntityType entitySetElementType = entitySet.EntityType(); - - string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); - - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(/*IsLanguageCaseSensitive*/true); - string parameterName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(entitySetElementType.Name)); - - string camelCaseEntitySetName = entitySet.Name; - if (this.context.EnableNamingAlias) - { - camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); - } - - this.WriteContextAddToEntitySetMethod(camelCaseEntitySetName, entitySet.Name, GetFixedName(entitySetElementTypeName), parameterName); - } - - foreach (IEdmSingleton singleton in container.Singletons()) - { - IEdmEntityType singletonElementType = singleton.EntityType(); - string singletonElementTypeName = GetElementTypeName(singletonElementType, container); - string camelCaseSingletonName = singleton.Name; - if (this.context.EnableNamingAlias) - { - camelCaseSingletonName = Customization.CustomizeNaming(camelCaseSingletonName); - } - - this.WriteContextSingletonProperty(camelCaseSingletonName, GetFixedName(camelCaseSingletonName), singleton.Name, singletonElementTypeName + "Single"); - - List edmNavigationSourceList = null; - if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(singleton.EntityType(), out edmNavigationSourceList)) - { - edmNavigationSourceList.Add(singleton); - } - } - - this.WriteGeneratedEdmModel(Utils.SerializeToString(this.context.Edmx).Replace("\"", "\"\"")); - - bool hasOperationImport = container.OperationImports().OfType().Any(); - foreach (IEdmFunctionImport functionImport in container.OperationImports().OfType()) - { - string parameterString, parameterTypes, parameterExpressionString, parameterValues; - bool useEntityReference; - this.GetParameterStrings(false, false, functionImport.Function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = GetSourceOrReturnTypeName(functionImport.Function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(functionImport.Function.ReturnType, true); - string fixedContainerName = this.GetFixedName(functionImport.Container.Name); - bool isCollectionResult = functionImport.Function.ReturnType.IsCollection(); - string functionImportName = functionImport.Name; - if (this.context.EnableNamingAlias) - { - functionImportName = Customization.CustomizeNaming(functionImportName); - fixedContainerName = Customization.CustomizeNaming(fixedContainerName); - } - - if (functionImport.Function.ReturnType.IsCollection()) - { - this.WriteFunctionImportReturnCollectionResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, parameterString, parameterValues, functionImport.Function.IsComposable, useEntityReference); - } - else - { - this.WriteFunctionImportReturnSingleResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, parameterValues, functionImport.Function.IsComposable, functionImport.Function.ReturnType.IsEntity(), useEntityReference); - } - } - - foreach (IEdmActionImport actionImport in container.OperationImports().OfType()) - { - string parameterString, parameterTypes, parameterExpressionString, parameterValues; - bool useEntityReference; - this.GetParameterStrings(false, true, actionImport.Action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = null; - string fixedContainerName = this.GetFixedName(actionImport.Container.Name); - - if (actionImport.Action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(actionImport.Action.ReturnType); - if (actionImport.Action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string actionImportName = actionImport.Name; - if (this.context.EnableNamingAlias) - { - actionImportName = Customization.CustomizeNaming(actionImportName); - fixedContainerName = Customization.CustomizeNaming(fixedContainerName); - } - - this.WriteActionImport(this.GetFixedName(actionImportName), actionImport.Name, returnTypeName, parameterString, parameterValues); - } - - this.WriteClassEndForEntityContainer(); - } - - internal void WriteEntityContainerConstructor(IEdmEntityContainer container) - { - string camelCaseContainerName = container.Name; - if (this.context.EnableNamingAlias) - { - camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); - } - - this.WriteMethodStartForEntityContainerConstructor(camelCaseContainerName, GetFixedName(camelCaseContainerName)); - - if (this.context.UseKeyAsSegmentUrlConvention(container)) - { - this.WriteKeyAsSegmentUrlConvention(); - } - - if (this.context.NeedResolveNameFromType) - { - this.WriteInitializeResolveName(); - } - - if (this.context.NeedResolveTypeFromName) - { - this.WriteInitializeResolveType(); - } - - this.WriteClassEndForEntityContainerConstructor(); - } - - internal void WriteResolveTypeFromName() - { - if (!this.context.NeedResolveTypeFromName) - { - return; - } - - this.WriteMethodStartForResolveTypeFromName(); - - // NOTE: since multiple namespaces can have the same prefix and match the namespace - // prefix condition, it's important that the prefix check is done is prefix-length - // order, starting with the longest prefix. - IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key); - - string typeName = this.SystemTypeTypeName + " "; - foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) - { - this.WriteResolveNamespace(typeName, namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); - typeName = string.Empty; - } - - this.WriteMethodEndForResolveTypeFromName(); - } - - internal void WriteResolveNameFromType(string containerName, string fullNamespace) - { - if (!this.context.NeedResolveNameFromType) - { - return; - } - - this.WriteMethodStartForResolveNameFromType(GetFixedName(containerName), fullNamespace); - - // NOTE: in this case order also matters, but the length of the CLR - // namespace is what needs to be considered. - IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key); - - foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) - { - this.WriteResolveType(namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); - } - - this.WriteMethodEndForResolveNameFromType(this.context.ModelHasInheritance); - } - - internal void WritePropertiesForSingleType(IEnumerable properties) - { - foreach (IEdmProperty property in properties.Where(i => i.PropertyKind == EdmPropertyKind.Navigation)) - { - string propertyType; - string propertyName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name; - if (property.Type is Microsoft.OData.Edm.EdmCollectionTypeReference) - { - propertyType = GetSourceOrReturnTypeName(property.Type); - WriteContextEntitySetProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); - } - else - { - propertyType = Utils.GetClrTypeName(property.Type, true, this, this.context, true, isEntitySingleType : true); - WriteContextSingletonProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); - } - } - } - - internal void WriteEntityType(IEdmEntityType entityType, Dictionary> boundOperationsMap) - { - string entityTypeName = ((IEdmSchemaElement)entityType).Name; - entityTypeName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; - this.WriteSummaryCommentForStructuredType(entityTypeName + this.SingleSuffix); - this.WriteStructurdTypeDeclaration(entityType, - this.ClassInheritMarker + string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName)), - this.SingleSuffix); - string singleTypeName = (this.context.EnableNamingAlias ? - Customization.CustomizeNaming(((IEdmSchemaElement)entityType).Name) : ((IEdmSchemaElement)entityType).Name) + this.SingleSuffix; - this.WriteConstructorForSingleType(GetFixedName(singleTypeName), string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName))); - IEdmEntityType current = entityType; - while (current != null) - { - this.WritePropertiesForSingleType(current.DeclaredProperties); - current = (IEdmEntityType)current.BaseType; - } - - this.WriteClassEndForStructuredType(); - - this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityType.Name) : entityType.Name); - - if (entityType.Key().Any()) - { - IEnumerable keyProperties = entityType.Key().Select(k => k.Name); - this.WriteKeyPropertiesCommentAndAttribute( - this.context.EnableNamingAlias ? keyProperties.Select(k => Customization.CustomizeNaming(k)) : keyProperties, - string.Join("\", \"", keyProperties)); - } - else - { - this.WriteEntityTypeAttribute(); - } - - if (this.context.UseDataServiceCollection) - { - List navigationSourceList; - if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(entityType, out navigationSourceList)) - { - if(navigationSourceList.Count == 1) - { - this.WriteEntitySetAttribute(navigationSourceList[0].Name); - } - } - } - - if (entityType.HasStream) - { - this.WriteEntityHasStreamAttribute(); - } - - this.WriteStructurdTypeDeclaration(entityType, this.BaseEntityType); - this.SetPropertyIdentifierMappingsIfNameConflicts(entityType.Name, entityType); - this.WriteTypeStaticCreateMethod(entityType.Name, entityType); - this.WritePropertiesForStructuredType(entityType.DeclaredProperties, entityType.IsOpen); - - if (entityType.BaseType == null && this.context.UseDataServiceCollection) - { - this.WriteINotifyPropertyChangedImplementation(); - } - - this.WriteBoundOperations(entityType, boundOperationsMap); - - this.WriteClassEndForStructuredType(); - } - - internal void WriteComplexType(IEdmComplexType complexType, Dictionary> boundOperationsMap) - { - this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(complexType.Name) : complexType.Name); - this.WriteStructurdTypeDeclaration(complexType, string.Empty); - this.SetPropertyIdentifierMappingsIfNameConflicts(complexType.Name, complexType); - this.WriteTypeStaticCreateMethod(complexType.Name, complexType); - this.WritePropertiesForStructuredType(complexType.DeclaredProperties, complexType.IsOpen); - - if (complexType.BaseType == null && this.context.UseDataServiceCollection) - { - this.WriteINotifyPropertyChangedImplementation(); - } - - this.WriteClassEndForStructuredType(); - } - - internal void WriteBoundOperations(IEdmStructuredType structuredType, Dictionary> boundOperationsMap) - { - List operations; - if (boundOperationsMap.TryGetValue(structuredType, out operations)) - { - foreach (IEdmFunction function in operations.OfType()) - { - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, function, boundOperationsMap); - this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); - string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); - string functionName = function.Name; - if (this.context.EnableNamingAlias) - { - functionName = Customization.CustomizeNaming(functionName); - } - - if (function.ReturnType.IsCollection()) - { - this.WriteBoundFunctionInEntityTypeReturnCollectionResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); - } - else - { - this.WriteBoundFunctionInEntityTypeReturnSingleResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); - } - } - - foreach (IEdmAction action in operations.OfType()) - { - string parameterString, parameterExpressionString, parameterTypes, parameterValues; - bool useEntityReference; - bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, action, boundOperationsMap); - this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); - string returnTypeName; - if (action.ReturnType != null) - { - returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); - if (action.ReturnType.IsCollection()) - { - returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); - } - else - { - returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); - } - } - else - { - returnTypeName = this.DataServiceActionQueryTypeName; - } - - string actionName = action.Name; - if (this.context.EnableNamingAlias) - { - actionName = Customization.CustomizeNaming(actionName); - } - - this.WriteBoundActionInEntityType(hideBaseMethod, GetFixedName(actionName), action.Name, returnTypeName, parameterString, action.Namespace, parameterValues); - } - } - } - - internal bool CheckMethodsInBaseClass(IEdmStructuredType structuredType, IEdmOperation operation, Dictionary> boundOperationsMap) - { - if (structuredType != null) - { - List operations; - if (boundOperationsMap.TryGetValue(structuredType, out operations)) - { - foreach (IEdmOperation op in operations) - { - if (this.context.TargetLanguage == LanguageOption.VB) - { - if (operation.Name == op.Name) - { - return true; - } - } - - List targetParameter = operation.Parameters.ToList(); - List checkParameter = op.Parameters.ToList(); - if (operation.Name == op.Name && targetParameter.Count == checkParameter.Count) - { - bool areSame = true; - for (int i = 1; i < targetParameter.Count; ++i) - { - var targetParameterType = targetParameter[i].Type; - var checkParameterType = checkParameter[i].Type; - if (!targetParameterType.Definition.Equals(checkParameterType.Definition) - || targetParameterType.IsNullable != checkParameterType.IsNullable) - { - areSame = false; - break; - } - } - - if (areSame) - { - return true; - } - } - } - } - - return CheckMethodsInBaseClass(structuredType.BaseType, operation, boundOperationsMap); - } - - return false; - } - - internal void WriteEnumType(IEdmEnumType enumType) - { - this.WriteSummaryCommentForEnumType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(enumType.Name) : enumType.Name); - if (enumType.IsFlags) - { - this.WriteEnumFlags(); - } - - string underlyingType = string.Empty; - if (enumType.UnderlyingType != null && enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32) - { - underlyingType = Utils.GetClrTypeName(enumType.UnderlyingType, this); - underlyingType = this.EnumUnderlyingTypeMarker + underlyingType; - } - - this.WriteEnumDeclaration(this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(enumType.Name)) : GetFixedName(enumType.Name), enumType.Name, underlyingType); - this.WriteMembersForEnumType(enumType.Members); - this.WriteEnumEnd(); - } - - internal void WriteStructurdTypeDeclaration(IEdmStructuredType structuredType, string baseEntityType, string typeNameSuffix = null) - { - string abstractModifier = structuredType.IsAbstract && typeNameSuffix == null ? this.AbstractModifier : string.Empty; - string baseTypeName = baseEntityType; - - if (typeNameSuffix == null) - { - if (structuredType.BaseType == null) - { - if (this.context.UseDataServiceCollection) - { - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - baseTypeName += string.IsNullOrEmpty(baseTypeName) ? this.ClassInheritMarker : ", "; - } - - baseTypeName += this.NotifyPropertyChangedModifier; - } - } - else - { - IEdmSchemaElement baseType = (IEdmSchemaElement)structuredType.BaseType; - string baseTypeFixedName = this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(baseType.Name)) : GetFixedName(baseType.Name); - baseTypeName = ((IEdmSchemaElement)structuredType).Namespace == baseType.Namespace ? baseTypeFixedName : this.context.GetPrefixedFullName(baseType, baseTypeFixedName, this); - baseTypeName = this.ClassInheritMarker + baseTypeName; - } - } - - string structuredTypeName = this.context.EnableNamingAlias ? - Customization.CustomizeNaming(((IEdmSchemaElement)structuredType).Name) : ((IEdmSchemaElement)structuredType).Name; - this.WriteClassStartForStructuredType(abstractModifier, GetFixedName(structuredTypeName + typeNameSuffix), ((IEdmSchemaElement)structuredType).Name + typeNameSuffix, baseTypeName); - } - - internal string GetSourceOrReturnTypeName(IEdmTypeReference typeReference, bool isEntitySingleType = false) - { - IEdmCollectionType edmCollectionType = typeReference.Definition as IEdmCollectionType; - bool addNullableTemplate = true; - if (edmCollectionType != null) - { - typeReference = edmCollectionType.ElementType; - addNullableTemplate = false; - } - - return Utils.GetClrTypeName(typeReference, this.context.UseDataServiceCollection, this, this.context, addNullableTemplate, isEntitySingleType:isEntitySingleType); - } - - internal void GetParameterStrings(bool isBound, bool isAction, IEdmOperationParameter[] parameters, out string parameterString, out string parameterTypes, out string parameterExpressionString, out string parameterValues, out bool useEntityReference) - { - parameterString = string.Empty; - parameterExpressionString = string.Empty; - parameterTypes = string.Empty; - parameterValues = string.Empty; - useEntityReference = false; - - int n = parameters.Count(); - for (int i = isBound ? 1 : 0; i < n; ++i) - { - IEdmOperationParameter param = parameters[i]; - if (i == (isBound ? 1 : 0)) - { - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - parameterExpressionString += "\r\n "; - } - else - { - parameterExpressionString += "\r\n "; - } - } - - string typeName = Utils.GetClrTypeName(param.Type, this.context.UseDataServiceCollection, this, this.context, true, true, true); - if (this.context.TargetLanguage == LanguageOption.CSharp) - { - parameterString += typeName; - parameterString += (" " + GetFixedName(param.Name)); - } - else if (this.context.TargetLanguage == LanguageOption.VB) - { - parameterString += GetFixedName(param.Name); - parameterString += (this.EnumUnderlyingTypeMarker + typeName); - } - - parameterString += i == n - 1 ? string.Empty : ", "; - parameterTypes += string.Format(this.TypeofFormatter, typeName) + ", "; - parameterExpressionString += this.GetParameterExpressionString(param, typeName) + ", "; - - if (i != (isBound ? 1 : 0)) - { - parameterValues += ",\r\n "; - } - - if (isAction) - { - parameterValues += string.Format(this.BodyOperationParameterConstructor, param.Name, GetFixedName(param.Name)); - } - else if (param.Type.IsEntity() || (param.Type.IsCollection() && param.Type.AsCollection().ElementType().IsEntity())) - { - useEntityReference = true; - parameterValues += string.Format(this.UriEntityOperationParameterConstructor, param.Name, GetFixedName(param.Name),"useEntityReference"); - } - else - { - parameterValues += string.Format(this.UriOperationParameterConstructor, param.Name, GetFixedName(param.Name)); - } - } - } - - internal string GetParameterExpressionString(IEdmOperationParameter param, string typeName) - { - string clrTypeName; - IEdmType edmType = param.Type.Definition; - IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; - if (edmPrimitiveType != null) - { - clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, this); - if (param.Type.IsNullable && !this.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind)) - { - clrTypeName += "?"; - } - - return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), clrTypeName); - } - - return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), typeName); - } - - // This is to solve duplicate names between property and type - internal void SetPropertyIdentifierMappingsIfNameConflicts(string typeName, IEdmStructuredType structuredType) - { - if (this.context.EnableNamingAlias) - { - typeName = Customization.CustomizeNaming(typeName); - } - - // PropertyName in VB is case-insensitive. - bool isLanguageCaseSensitive = this.context.TargetLanguage == LanguageOption.CSharp; - - // In VB, it is allowed that a type has a property whose name is same with the type's name - bool allowPropertyNameSameWithTypeName = this.context.TargetLanguage == LanguageOption.VB; - - Func customizePropertyName = (name) => { return this.context.EnableNamingAlias ? Customization.CustomizeNaming(name) : name; }; - - var propertyGroups = structuredType.Properties() - .GroupBy(p => isLanguageCaseSensitive ? customizePropertyName(p.Name) : customizePropertyName(p.Name).ToUpperInvariant()); - - // If the group contains more than one property, or the property in the group has the same name with the type (only for C#), we need to rename the property - var propertyToBeRenamedGroups = propertyGroups.Where(g => g.Count() > 1 || !allowPropertyNameSameWithTypeName && g.Key == typeName); - - var knownIdentifiers = propertyGroups.Select(g => customizePropertyName(g.First().Name)).ToList(); - if(!allowPropertyNameSameWithTypeName && !knownIdentifiers.Contains(typeName)) - { - knownIdentifiers.Add(typeName); - } - UniqueIdentifierService uniqueIdentifierService = - new UniqueIdentifierService(knownIdentifiers, isLanguageCaseSensitive); - - IdentifierMappings.Clear(); - foreach (IGrouping g in propertyToBeRenamedGroups) - { - bool hasPropertyNameSameWithCustomizedPropertyName = false; - int itemCount = g.Count(); - for (int i = 0; i < itemCount; i++) - { - var property = g.ElementAt(i); - var customizedPropertyName = customizePropertyName(property.Name); - - if(this.context.EnableNamingAlias && customizedPropertyName == property.Name) - { - hasPropertyNameSameWithCustomizedPropertyName = true; - } - - if(isLanguageCaseSensitive) - { - // If a property name is same as its customized property name, then we don't rename it. - // Or we don't rename the last property in the group - if(customizedPropertyName != typeName - && (customizedPropertyName == property.Name - || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1))) - { - continue; - } - } - else - { - // When EnableNamingAlias = true, If a property name is same as its customized property name, then we don't rename it. - // Or we don't rename the last property in the group. - if((this.context.EnableNamingAlias && customizedPropertyName == property.Name) - || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1)) - { - continue; - } - } - var renamedPropertyName = uniqueIdentifierService.GetUniqueIdentifier(customizedPropertyName); - IdentifierMappings.Add(property.Name, renamedPropertyName); - } - } - } - - internal void WriteTypeStaticCreateMethod(string typeName, IEdmStructuredType structuredType) - { - Debug.Assert(structuredType != null, "structuredType != null"); - if (structuredType.IsAbstract) - { - return; - } - - Func hasDefault = p => p.PropertyKind == EdmPropertyKind.Structural && ((IEdmStructuralProperty)p).DefaultValueString != null; - - if (this.context.EnableNamingAlias) - { - typeName = Customization.CustomizeNaming(typeName); - } - - IEnumerable parameters = structuredType.Properties() - .Where(p => !p.Type.IsNullable && !p.Type.IsCollection() && !hasDefault(p)); - if (!parameters.Any()) - { - return; - } - - this.WriteSummaryCommentForStaticCreateMethod(typeName); - - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( /*IsLanguageCaseSensitive*/true); - string instanceName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(typeName)); - KeyValuePair[] propertyToParameterNamePairs = parameters - .Select(p => - new KeyValuePair(p, - uniqueIdentifierService.GetUniqueParameterName( - IdentifierMappings.ContainsKey(p.Name) ? IdentifierMappings[p.Name] : p.Name))) - .ToArray(); - - foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) - { - string propertyName = propertyToParameterNamePair.Key.Name; - propertyName = IdentifierMappings.ContainsKey(propertyName) ? - IdentifierMappings[propertyName] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(propertyName) : propertyName); - this.WriteParameterCommentForStaticCreateMethod(propertyToParameterNamePair.Value, propertyName); - } - - propertyToParameterNamePairs = propertyToParameterNamePairs - .Select(p => p = new KeyValuePair(p.Key, GetFixedName(p.Value))) - .ToArray(); - - this.WriteDeclarationStartForStaticCreateMethod(typeName, GetFixedName(typeName)); - this.WriteStaticCreateMethodParameters(propertyToParameterNamePairs); - this.WriteDeclarationEndForStaticCreateMethod(GetFixedName(typeName), instanceName); - - foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) - { - IEdmProperty property = propertyToParameterNamePair.Key; - string parameterName = propertyToParameterNamePair.Value; - - Debug.Assert(!property.Type.IsCollection(), "!property.Type.IsCollection()"); - Debug.Assert(!property.Type.IsNullable, "!property.Type.IsNullable"); - - // The static create method only sets non-nullable properties. We should add the null check if the type of the property is not a clr ValueType. - // For now we add the null check if the property type is non-primitive. We should add the null check for non-ValueType primitives in the future. - if (!property.Type.IsPrimitive() && !property.Type.IsEnum()) - { - this.WriteParameterNullCheckForStaticCreateMethod(parameterName); - } - - var uniqIdentifier = IdentifierMappings.ContainsKey(property.Name) ? - IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); - this.WritePropertyValueAssignmentForStaticCreateMethod(instanceName, - GetFixedName(uniqIdentifier), - parameterName); - } - - this.WriteMethodEndForStaticCreateMethod(instanceName); - } - - internal void WriteStaticCreateMethodParameters(KeyValuePair[] propertyToParameterPairs) - { - if (propertyToParameterPairs.Length == 0) - { - return; - } - - // If the number of parameters are greater than 5, we put them in separate lines. - string parameterSeparator = propertyToParameterPairs.Length > 5 ? this.ParameterSeparator : ", "; - for (int idx = 0; idx < propertyToParameterPairs.Length; idx++) - { - KeyValuePair propertyToParameterPair = propertyToParameterPairs[idx]; - - string parameterType = Utils.GetClrTypeName(propertyToParameterPair.Key.Type, this.context.UseDataServiceCollection, this, this.context); - string parameterName = propertyToParameterPair.Value; - if (idx == propertyToParameterPairs.Length - 1) - { - // No separator after the last parameter. - parameterSeparator = string.Empty; - } - - this.WriteParameterForStaticCreateMethod(parameterType, GetFixedName(parameterName), parameterSeparator); - } - } - - internal void WritePropertiesForStructuredType(IEnumerable properties, bool isOpen) - { - bool useDataServiceCollection = this.context.UseDataServiceCollection; - - var propertyInfos = properties.Select(property => - { - string propertyName = IdentifierMappings.ContainsKey(property.Name) ? - IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); - - return new - { - PropertyType = Utils.GetClrTypeName(property.Type, useDataServiceCollection, this, this.context), - PropertyVanillaName = property.Name, - PropertyName = propertyName, - FixedPropertyName = GetFixedName(propertyName), - PrivatePropertyName = "_" + propertyName, - PropertyInitializationValue = Utils.GetPropertyInitializationValue(property, useDataServiceCollection, this, this.context) - }; - }).ToList(); - - if(isOpen && this.context.GenerateDynamicPropertiesCollection) - { - propertyInfos.Add(new - { - PropertyType = string.Format(this.DictionaryTypeName, this.StringTypeName, this.ObjectTypeName), - PropertyVanillaName = string.Empty, // No such property in metadata - PropertyName = this.context.DynamicPropertiesCollectionName, - FixedPropertyName = GetFixedName(this.context.DynamicPropertiesCollectionName), - PrivatePropertyName = "_" + Utils.CamelCase(this.context.DynamicPropertiesCollectionName), - PropertyInitializationValue = string.Format(this.DictionaryConstructor, this.StringTypeName, this.ObjectTypeName) - }); - } - - // Private name should not confict with field name - UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(propertyInfos.Select(_ => _.FixedPropertyName), - this.context.TargetLanguage == LanguageOption.CSharp); - - foreach (var propertyInfo in propertyInfos) - { - string privatePropertyName = uniqueIdentifierService.GetUniqueIdentifier("_" + propertyInfo.PropertyName); - - this.WritePropertyForStructuredType( - propertyInfo.PropertyType, - propertyInfo.PropertyVanillaName, - propertyInfo.PropertyName, - propertyInfo.FixedPropertyName, - privatePropertyName, - propertyInfo.PropertyInitializationValue, - useDataServiceCollection); - } - } - - internal void WriteMembersForEnumType(IEnumerable members) - { - int n = members.Count(); - for (int idx = 0; idx < n; ++idx) - { - IEdmEnumMember member = members.ElementAt(idx); - string value = string.Empty; - if (member.Value != null) - { - IEdmEnumMemberValue integerValue = member.Value as IEdmEnumMemberValue; - if (integerValue != null) - { - value = " = " + integerValue.Value.ToString(CultureInfo.InvariantCulture); - } - } - - string memberName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(member.Name) : member.Name; - this.WriteMemberForEnumType(GetFixedName(memberName) + value, member.Name, idx == n - 1); - } - } - - internal string GetFixedName(string originalName) - { - string fixedName = originalName; - - if (this.LanguageKeywords.Contains(fixedName)) - { - fixedName = string.Format(this.FixPattern, fixedName); - } - - return fixedName; - } - - internal string GetElementTypeName(IEdmEntityType elementType, IEdmEntityContainer container) - { - string elementTypeName = elementType.Name; - - if (this.context.EnableNamingAlias) - { - elementTypeName = Customization.CustomizeNaming(elementTypeName); - } - - if (elementType.Namespace != container.Namespace) - { - elementTypeName = this.context.GetPrefixedFullName(elementType, GetFixedName(elementTypeName), this); - } - - return elementTypeName; - } -} - -/// -/// Base class for text transformation -/// -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] -public abstract class TemplateBase -{ - #region Fields - private global::System.Text.StringBuilder generationEnvironmentField; - private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; - private global::System.Collections.Generic.List indentLengthsField; - private string currentIndentField = ""; - private bool endsWithNewline; - private global::System.Collections.Generic.IDictionary sessionField; - #endregion - #region Properties - /// - /// The string builder that generation-time code is using to assemble generated output - /// - protected System.Text.StringBuilder GenerationEnvironment - { - get - { - if ((this.generationEnvironmentField == null)) - { - this.generationEnvironmentField = new global::System.Text.StringBuilder(); - } - return this.generationEnvironmentField; - } - set - { - this.generationEnvironmentField = value; - } - } - /// - /// The error collection for the generation process - /// - public System.CodeDom.Compiler.CompilerErrorCollection Errors - { - get - { - if ((this.errorsField == null)) - { - this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); - } - return this.errorsField; - } - } - /// - /// A list of the lengths of each indent that was added with PushIndent - /// - private System.Collections.Generic.List indentLengths - { - get - { - if ((this.indentLengthsField == null)) - { - this.indentLengthsField = new global::System.Collections.Generic.List(); - } - return this.indentLengthsField; - } - } - /// - /// Gets the current indent we use when adding lines to the output - /// - public string CurrentIndent - { - get - { - return this.currentIndentField; - } - } - /// - /// Current transformation session - /// - public virtual global::System.Collections.Generic.IDictionary Session - { - get - { - return this.sessionField; - } - set - { - this.sessionField = value; - } - } - #endregion - - /// - /// Create the template output - /// - public abstract string TransformText(); - - #region Transform-time helpers - /// - /// Write text directly into the generated output - /// - public void Write(string textToAppend) - { - if (string.IsNullOrEmpty(textToAppend)) - { - return; - } - // If we're starting off, or if the previous text ended with a newline, - // we have to append the current indent first. - if (((this.GenerationEnvironment.Length == 0) - || this.endsWithNewline)) - { - this.GenerationEnvironment.Append(this.currentIndentField); - this.endsWithNewline = false; - } - // Check if the current text ends with a newline - if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) - { - this.endsWithNewline = true; - } - // This is an optimization. If the current indent is "", then we don't have to do any - // of the more complex stuff further down. - if ((this.currentIndentField.Length == 0)) - { - this.GenerationEnvironment.Append(textToAppend); - return; - } - // Everywhere there is a newline in the text, add an indent after it - textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); - // If the text ends with a newline, then we should strip off the indent added at the very end - // because the appropriate indent will be added when the next time Write() is called - if (this.endsWithNewline) - { - this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); - } - else - { - this.GenerationEnvironment.Append(textToAppend); - } - } - /// - /// Write text directly into the generated output - /// - public void WriteLine(string textToAppend) - { - this.Write(textToAppend); - this.GenerationEnvironment.AppendLine(); - this.endsWithNewline = true; - } - /// - /// Write formatted text directly into the generated output - /// - public void Write(string format, params object[] args) - { - this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); - } - /// - /// Write formatted text directly into the generated output - /// - public void WriteLine(string format, params object[] args) - { - this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); - } - /// - /// Raise an error - /// - public void Error(string message) - { - System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); - error.ErrorText = message; - this.Errors.Add(error); - } - /// - /// Raise a warning - /// - public void Warning(string message) - { - System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); - error.ErrorText = message; - error.IsWarning = true; - this.Errors.Add(error); - } - /// - /// Increase the indent - /// - public void PushIndent(string indent) - { - if ((indent == null)) - { - throw new global::System.ArgumentNullException("indent"); - } - this.currentIndentField = (this.currentIndentField + indent); - this.indentLengths.Add(indent.Length); - } - /// - /// Remove the last indent that was added with PushIndent - /// - public string PopIndent() - { - string returnValue = ""; - if ((this.indentLengths.Count > 0)) - { - int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; - this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); - if ((indentLength > 0)) - { - returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); - this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); - } - } - return returnValue; - } - /// - /// Remove any indentation - /// - public void ClearIndent() - { - this.indentLengths.Clear(); - this.currentIndentField = ""; - } - #endregion - #region ToString Helpers - /// - /// Utility class to produce culture-oriented representation of an object as a string. - /// - public class ToStringInstanceHelper - { - private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; - /// - /// Gets or sets format provider to be used by ToStringWithCulture method. - /// - public System.IFormatProvider FormatProvider - { - get - { - return this.formatProviderField ; - } - set - { - if ((value != null)) - { - this.formatProviderField = value; - } - } - } - /// - /// This is called from the compile/run appdomain to convert objects within an expression block to a string - /// - public string ToStringWithCulture(object objectToConvert) - { - if ((objectToConvert == null)) - { - throw new global::System.ArgumentNullException("objectToConvert"); - } - System.Type t = objectToConvert.GetType(); - System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { - typeof(System.IFormatProvider)}); - if ((method == null)) - { - return objectToConvert.ToString(); - } - else - { - return ((string)(method.Invoke(objectToConvert, new object[] { - this.formatProviderField }))); - } - } - } - private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); - /// - /// Helper to produce culture-oriented representation of an object as a string - /// - public ToStringInstanceHelper ToStringHelper - { - get - { - return this.toStringHelperField; - } - } - #endregion -} - -/// -/// Service making names within a scope unique. Initialize a new instance for every scope. -/// -internal sealed class UniqueIdentifierService -{ - // This is the list of keywords we check against when creating parameter names from propert. - // If a name matches this keyword we prefix it. - private static readonly string[] Keywords = new string[] {"class", "event"}; - - /// - /// Hash set to detect identifier collision. - /// - private readonly HashSet knownIdentifiers; - - /// - /// Constructs a . - /// - /// true if the language we are generating the code for is case sensitive, false otherwise. - internal UniqueIdentifierService(bool caseSensitive) - { - this.knownIdentifiers = new HashSet(caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); - } - - /// - /// Constructs a . - /// - /// identifiers used to detect collision. - /// true if the language we are generating the code for is case sensitive, false otherwise. - internal UniqueIdentifierService(IEnumerable identifiers, bool caseSensitive) - { - this.knownIdentifiers = new HashSet(identifiers ?? Enumerable.Empty(), caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); - } - - /// - /// Given an identifier, makes it unique within the scope by adding - /// a suffix (1, 2, 3, ...), and returns the adjusted identifier. - /// - /// Identifier. Must not be null or empty. - /// Identifier adjusted to be unique within the scope. - internal string GetUniqueIdentifier(string identifier) - { - Debug.Assert(!string.IsNullOrEmpty(identifier), "identifier is null or empty"); - - // find a unique name by adding suffix as necessary - int numberOfConflicts = 0; - string uniqueIdentifier = identifier; - while (this.knownIdentifiers.Contains(uniqueIdentifier)) - { - ++numberOfConflicts; - uniqueIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture); - } - - // remember the identifier in this scope - Debug.Assert(!this.knownIdentifiers.Contains(uniqueIdentifier), "we just made it unique"); - this.knownIdentifiers.Add(uniqueIdentifier); - - return uniqueIdentifier; - } - - /// - /// Fix up the given parameter name and make it unique. - /// - /// Parameter name. - /// Fixed parameter name. - internal string GetUniqueParameterName(string name) - { - name = Utils.CamelCase(name); - - // FxCop consider 'iD' as violation, we will change any property that is 'id'(case insensitive) to 'ID' - if (StringComparer.OrdinalIgnoreCase.Equals(name, "id")) - { - name = "ID"; - } - - return this.GetUniqueIdentifier(name); - } -} - -/// -/// Utility class. -/// -internal static class Utils -{ - /// - /// Serializes the xml element to a string. - /// - /// The xml element to serialize. - /// The string representation of the xml. - internal static string SerializeToString(XElement xml) - { - // because comment nodes can contain special characters that are hard to embed in VisualBasic, remove them here - xml.DescendantNodes().OfType().Remove(); - - var stringBuilder = new StringBuilder(); - using (var writer = XmlWriter.Create( - stringBuilder, - new XmlWriterSettings - { - OmitXmlDeclaration = true, - NewLineHandling = NewLineHandling.Replace, - Indent = true, - })) - { - xml.WriteTo(writer); - } - - return stringBuilder.ToString(); - } - - /// - /// Changes the text to use camel case, which lower case for the first character. - /// - /// Text to convert. - /// The converted text in camel case - internal static string CamelCase(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); - } - - return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant() + text.Substring(1); - } - - /// - /// Changes the text to use pascal case, which upper case for the first character. - /// - /// Text to convert. - /// The converted text in pascal case - internal static string PascalCase(string text) - { - if (string.IsNullOrEmpty(text)) - { - return text; - } - - if (text.Length == 1) - { - return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant(); - } - - return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant() + text.Substring(1); - } - - /// - /// Gets the clr type name from the give type reference. - /// - /// The type reference in question. - /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, - /// false to use Collection for collections. - /// ODataClientTemplate instance that call this method. - /// CodeGenerationContext instance in the clientTemplate. - /// This flag indicates whether to return the type name in nullable format - /// The flag indicates whether the namespace need to be added by global prefix - /// This flag indicates whether the edmTypeReference is for an operation parameter - /// The clr type name of the type reference. - internal static string GetClrTypeName(IEdmTypeReference edmTypeReference, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context, bool addNullableTemplate = true, bool needGlobalPrefix = true, bool isOperationParameter = false, bool isEntitySingleType = false) - { - string clrTypeName; - IEdmType edmType = edmTypeReference.Definition; - IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; - if (edmPrimitiveType != null) - { - clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, clientTemplate); - if (edmTypeReference.IsNullable && !clientTemplate.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind) && addNullableTemplate) - { - clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); - } - } - else - { - IEdmComplexType edmComplexType = edmType as IEdmComplexType; - if (edmComplexType != null) - { - clrTypeName = context.GetPrefixedFullName(edmComplexType, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmComplexType.Name)) : clientTemplate.GetFixedName(edmComplexType.Name), clientTemplate); - } - else - { - IEdmEnumType edmEnumType = edmType as IEdmEnumType; - if (edmEnumType != null) - { - clrTypeName = context.GetPrefixedFullName(edmEnumType, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEnumType.Name)) : clientTemplate.GetFixedName(edmEnumType.Name), clientTemplate, needGlobalPrefix); - if (edmTypeReference.IsNullable && addNullableTemplate) - { - clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); - } - } - else - { - IEdmEntityType edmEntityType = edmType as IEdmEntityType; - if (edmEntityType != null) - { - clrTypeName = context.GetPrefixedFullName(edmEntityType, - context.EnableNamingAlias - ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEntityType.Name) + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)) - : clientTemplate.GetFixedName(edmEntityType.Name + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)), - clientTemplate); - } - else - { - IEdmCollectionType edmCollectionType = (IEdmCollectionType)edmType; - IEdmTypeReference elementTypeReference = edmCollectionType.ElementType; - IEdmPrimitiveType primitiveElementType = elementTypeReference.Definition as IEdmPrimitiveType; - if (primitiveElementType != null) - { - clrTypeName = Utils.GetClrTypeName(primitiveElementType, clientTemplate); - } - else - { - IEdmSchemaElement schemaElement = (IEdmSchemaElement)elementTypeReference.Definition; - clrTypeName = context.GetPrefixedFullName(schemaElement, - context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(schemaElement.Name)) : clientTemplate.GetFixedName(schemaElement.Name), clientTemplate); - } - - string collectionTypeName = isOperationParameter - ? clientTemplate.ICollectionOfTStructureTemplate - : (useDataServiceCollection - ? (elementTypeReference.TypeKind() == EdmTypeKind.Entity - ? clientTemplate.DataServiceCollectionStructureTemplate - : clientTemplate.ObservableCollectionStructureTemplate) - : clientTemplate.ObjectModelCollectionStructureTemplate); - - clrTypeName = string.Format(collectionTypeName, clrTypeName); - } - } - } - } - - return clrTypeName; - } - - /// - /// Gets the value expression to initualize the property with. - /// - /// The property in question. - /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, - /// false to use Collection for collections. - /// ODataClientTemplate instance that call this method. - /// CodeGenerationContext instance in the clientTemplate. - /// The value expression to initualize the property with. - internal static string GetPropertyInitializationValue(IEdmProperty property, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context) - { - IEdmTypeReference edmTypeReference = property.Type; - IEdmCollectionTypeReference edmCollectionTypeReference = edmTypeReference as IEdmCollectionTypeReference; - if (edmCollectionTypeReference == null) - { - IEdmStructuralProperty structuredProperty = property as IEdmStructuralProperty; - if (structuredProperty != null) - { - if (!string.IsNullOrEmpty(structuredProperty.DefaultValueString)) - { - string valueClrType = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - string defaultValue = structuredProperty.DefaultValueString; - bool isCSharpTemplate = clientTemplate is ODataClientCSharpTemplate; - if (edmTypeReference.Definition.TypeKind == EdmTypeKind.Enum) - { - var enumValues = defaultValue.Split(','); - string fullenumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - string enumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context, false, false); - List customizedEnumValues = new List(); - foreach(var enumValue in enumValues) - { - string currentEnumValue = enumValue.Trim(); - int indexFirst = currentEnumValue.IndexOf('\'') + 1; - int indexLast = currentEnumValue.LastIndexOf('\''); - if (indexFirst > 0 && indexLast > indexFirst) - { - currentEnumValue = currentEnumValue.Substring(indexFirst, indexLast - indexFirst); - } - - var customizedEnumValue = context.EnableNamingAlias ? Customization.CustomizeNaming(currentEnumValue) : currentEnumValue; - if (isCSharpTemplate) - { - currentEnumValue = "(" + fullenumTypeName + ")" + clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + customizedEnumValue + "\")"; - } - else - { - currentEnumValue = clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + currentEnumValue + "\")"; - } - customizedEnumValues.Add(currentEnumValue); - } - if (isCSharpTemplate) - { - return string.Join(" | ", customizedEnumValues); - } - else - { - return string.Join(" Or ", customizedEnumValues); - } - } - - if (valueClrType.Equals(clientTemplate.StringTypeName)) - { - defaultValue = "\"" + defaultValue + "\""; - } - else if (valueClrType.Equals(clientTemplate.BinaryTypeName)) - { - defaultValue = "System.Text.Encoding.UTF8.GetBytes(\"" + defaultValue + "\")"; - } - else if (valueClrType.Equals(clientTemplate.SingleTypeName)) - { - if (isCSharpTemplate) - { - defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "f"; - } - else - { - defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "F"; - } - } - else if (valueClrType.Equals(clientTemplate.DecimalTypeName)) - { - if (isCSharpTemplate) - { - // decimal in C# must be initialized with 'm' at the end, like Decimal dec = 3.00m - defaultValue = defaultValue.EndsWith("m", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "m"; - } - else - { - // decimal in VB must be initialized with 'D' at the end, like Decimal dec = 3.00D - defaultValue = defaultValue.ToLower().Replace("m", "D"); - defaultValue = defaultValue.EndsWith("D", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "D"; - } - } - else if (valueClrType.Equals(clientTemplate.GuidTypeName) - | valueClrType.Equals(clientTemplate.DateTimeOffsetTypeName) - | valueClrType.Equals(clientTemplate.DateTypeName) - | valueClrType.Equals(clientTemplate.TimeOfDayTypeName)) - { - defaultValue = valueClrType + ".Parse(\"" + defaultValue + "\")"; - } - else if (valueClrType.Equals(clientTemplate.DurationTypeName)) - { - defaultValue = clientTemplate.XmlConvertClassName + ".ToTimeSpan(\"" + defaultValue + "\")"; - } - else if (valueClrType.Contains("Microsoft.Spatial")) - { - defaultValue = string.Format(clientTemplate.GeoTypeInitializePattern, valueClrType, defaultValue); - } - - return defaultValue; - } - else - { - // doesn't have a default value - return null; - } - } - else - { - // only structured property has default value - return null; - } - } - else - { - string constructorParameters; - if (edmCollectionTypeReference.ElementType().IsEntity() && useDataServiceCollection) - { - constructorParameters = clientTemplate.DataServiceCollectionConstructorParameters; - } - else - { - constructorParameters = "()"; - } - - string clrTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); - return clientTemplate.NewModifier + clrTypeName + constructorParameters; - } - } - - /// - /// Gets the clr type name from the give Edm primitive type. - /// - /// The Edm primitive type in question. - /// ODataClientTemplate instance that call this method. - /// The clr type name of the Edm primitive type. - internal static string GetClrTypeName(IEdmPrimitiveType edmPrimitiveType, ODataClientTemplate clientTemplate) - { - EdmPrimitiveTypeKind kind = edmPrimitiveType.PrimitiveKind; - - string type="UNKNOWN"; - if (kind==EdmPrimitiveTypeKind.Int32) - { - type= clientTemplate.Int32TypeName; - } - else if (kind== EdmPrimitiveTypeKind.String) - { - type= clientTemplate.StringTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Binary) - { - type= clientTemplate.BinaryTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Decimal) - { - type= clientTemplate.DecimalTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Int16) - { - type= clientTemplate.Int16TypeName; - } - else if(kind==EdmPrimitiveTypeKind.Single) - { - type= clientTemplate.SingleTypeName; - } - else if (kind==EdmPrimitiveTypeKind.Boolean) - { - type= clientTemplate.BooleanTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Double) - { - type= clientTemplate.DoubleTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Guid) - { - type= clientTemplate.GuidTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Byte) - { - type= clientTemplate.ByteTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Int64) - { - type= clientTemplate.Int64TypeName; - } - else if (kind== EdmPrimitiveTypeKind.SByte) - { - type= clientTemplate.SByteTypeName; - } - else if (kind == EdmPrimitiveTypeKind.Stream) - { - type= clientTemplate.DataServiceStreamLinkTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Geography) - { - type= clientTemplate.GeographyTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyPoint) - { - type= clientTemplate.GeographyPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyLineString) - { - type= clientTemplate.GeographyLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyPolygon) - { - type= clientTemplate.GeographyPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyCollection) - { - type= clientTemplate.GeographyCollectionTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiPolygon) - { - type= clientTemplate.GeographyMultiPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiLineString) - { - type= clientTemplate.GeographyMultiLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeographyMultiPoint) - { - type= clientTemplate.GeographyMultiPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Geometry) - { - type= clientTemplate.GeometryTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryPoint) - { - type= clientTemplate.GeometryPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryLineString) - { - type= clientTemplate.GeometryLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryPolygon) - { - type= clientTemplate.GeometryPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryCollection) - { - type= clientTemplate.GeometryCollectionTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiPolygon) - { - type= clientTemplate.GeometryMultiPolygonTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiLineString) - { - type= clientTemplate.GeometryMultiLineStringTypeName; - } - else if (kind== EdmPrimitiveTypeKind.GeometryMultiPoint) - { - type= clientTemplate.GeometryMultiPointTypeName; - } - else if (kind== EdmPrimitiveTypeKind.DateTimeOffset) - { - type= clientTemplate.DateTimeOffsetTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Duration) - { - type= clientTemplate.DurationTypeName; - } - else if (kind== EdmPrimitiveTypeKind.Date) - { - type= clientTemplate.DateTypeName; - } - else if (kind== EdmPrimitiveTypeKind.TimeOfDay) - { - type= clientTemplate.TimeOfDayTypeName; - } - else - { - throw new Exception("Type "+kind.ToString()+" is unrecognized"); - } - - return type; - } -} - -public sealed class ODataClientCSharpTemplate : ODataClientTemplate -{ - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The code generation context. - public ODataClientCSharpTemplate(CodeGenerationContext context) - : base(context) - { - } - - internal override string GlobalPrefix { get {return "global::"; } } - internal override string SystemTypeTypeName { get { return "global::System.Type"; } } - internal override string AbstractModifier { get { return " abstract"; } } - internal override string DataServiceActionQueryTypeName { get { return "global::Microsoft.OData.Client.DataServiceActionQuery"; } } - internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuerySingle<{0}>"; } } - internal override string DataServiceActionQueryOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuery<{0}>"; } } - internal override string NotifyPropertyChangedModifier { get { return "global::System.ComponentModel.INotifyPropertyChanged"; } } - internal override string ClassInheritMarker { get { return " : "; } } - internal override string ParameterSeparator { get { return ", \r\n "; } } - internal override string KeyParameterSeparator { get { return ", \r\n "; } } - internal override string KeyDictionaryItemSeparator { get { return ", \r\n "; } } - internal override string SystemNullableStructureTemplate { get { return "global::System.Nullable<{0}>"; } } - internal override string ICollectionOfTStructureTemplate { get { return "global::System.Collections.Generic.ICollection<{0}>"; } } - internal override string DataServiceCollectionStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceCollection<{0}>"; } } - internal override string DataServiceQueryStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuery<{0}>"; } } - internal override string DataServiceQuerySingleStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuerySingle<{0}>"; } } - internal override string ObservableCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.ObservableCollection<{0}>"; } } - internal override string ObjectModelCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.Collection<{0}>"; } } - internal override string DataServiceCollectionConstructorParameters { get { return "(null, global::Microsoft.OData.Client.TrackingMode.None)"; } } - internal override string NewModifier { get { return "new "; } } - internal override string GeoTypeInitializePattern { get { return "global::Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(false).Read<{0}>(new global::System.IO.StringReader(\"{1}\"))"; } } - internal override string Int32TypeName { get { return "int"; } } - internal override string ObjectTypeName { get { return "object"; } } - internal override string StringTypeName { get { return "string"; } } - internal override string BinaryTypeName { get { return "byte[]"; } } - internal override string DecimalTypeName { get { return "decimal"; } } - internal override string Int16TypeName { get { return "short"; } } - internal override string SingleTypeName { get { return "float"; } } - internal override string BooleanTypeName { get { return "bool"; } } - internal override string DoubleTypeName { get { return "double"; } } - internal override string GuidTypeName { get { return "global::System.Guid"; } } - internal override string ByteTypeName { get { return "byte"; } } - internal override string Int64TypeName { get { return "long"; } } - internal override string SByteTypeName { get { return "sbyte"; } } - internal override string DataServiceStreamLinkTypeName { get { return "global::Microsoft.OData.Client.DataServiceStreamLink"; } } - internal override string GeographyTypeName { get { return "global::Microsoft.Spatial.Geography"; } } - internal override string GeographyPointTypeName { get { return "global::Microsoft.Spatial.GeographyPoint"; } } - internal override string GeographyLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyLineString"; } } - internal override string GeographyPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyPolygon"; } } - internal override string GeographyCollectionTypeName { get { return "global::Microsoft.Spatial.GeographyCollection"; } } - internal override string GeographyMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPolygon"; } } - internal override string GeographyMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyMultiLineString"; } } - internal override string GeographyMultiPointTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPoint"; } } - internal override string GeometryTypeName { get { return "global::Microsoft.Spatial.Geometry"; } } - internal override string GeometryPointTypeName { get { return "global::Microsoft.Spatial.GeometryPoint"; } } - internal override string GeometryLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryLineString"; } } - internal override string GeometryPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryPolygon"; } } - internal override string GeometryCollectionTypeName { get { return "global::Microsoft.Spatial.GeometryCollection"; } } - internal override string GeometryMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPolygon"; } } - internal override string GeometryMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryMultiLineString"; } } - internal override string GeometryMultiPointTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPoint"; } } - internal override string DateTypeName { get { return "global::Microsoft.OData.Edm.Date"; } } - internal override string DateTimeOffsetTypeName { get { return "global::System.DateTimeOffset"; } } - internal override string DurationTypeName { get { return "global::System.TimeSpan"; } } - internal override string TimeOfDayTypeName { get { return "global::Microsoft.OData.Edm.TimeOfDay"; } } - internal override string XmlConvertClassName { get { return "global::System.Xml.XmlConvert"; } } - internal override string EnumTypeName { get { return "global::System.Enum"; } } - internal override string DictionaryTypeName { get { return "global::System.Collections.Generic.Dictionary<{0}, {1}>"; } } - internal override string FixPattern { get { return "@{0}"; } } - internal override string EnumUnderlyingTypeMarker { get { return " : "; } } - internal override string ConstantExpressionConstructorWithType { get { return "global::System.Linq.Expressions.Expression.Constant({0}, typeof({1}))"; } } - internal override string TypeofFormatter { get { return "typeof({0})"; } } - internal override string UriOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } - internal override string UriEntityOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } - internal override string BodyOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } - internal override string DictionaryConstructor { get { return $"new {DictionaryTypeName}()"; } } - internal override string BaseEntityType { get { return " : global::Microsoft.OData.Client.BaseEntityType"; } } - internal override string OverloadsModifier { get { return "new "; } } - internal override string ODataVersion { get { return "global::Microsoft.OData.ODataVersion.V4"; } } - internal override string ParameterDeclarationTemplate { get { return "{0} {1}"; } } - internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } - internal override HashSet LanguageKeywords { get { - if (CSharpKeywords == null) - { - CSharpKeywords = new HashSet(StringComparer.Ordinal) - { - "abstract", "as", "base", "byte", "bool", "break", "case", "catch", "char", "checked", "class", "const", "continue", - "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "for", - "foreach", "finally", "fixed", "float", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", - "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", - "readonly", "ref", "return", "sbyte", "sealed", "string", "short", "sizeof", "stackalloc", "static", "struct", "switch", - "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "volatile", - "void", "while" - }; - } - return CSharpKeywords; - } } - private HashSet CSharpKeywords; - - internal override void WriteFileHeader() - { -#>//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:<#= Environment.Version #> -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -// Generation date: <#= DateTime.Now.ToString(global::System.Globalization.CultureInfo.CurrentCulture) #> -<#+ - } - - internal override void WriteNamespaceStart(string fullNamespace) - { -#> -namespace <#= fullNamespace #> -{ -<#+ - } - - internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) - { -#> - /// - /// There are no comments for <#= containerName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalContainerName #>")] -<#+ - } -#> - public partial class <#= fixedContainerName #> : global::Microsoft.OData.Client.DataServiceContext - { -<#+ - } - - internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) - { -#> - /// - /// Initialize a new <#= containerName #> object. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public <#= fixedContainerName #>(global::System.Uri serviceRoot) : - base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4) - { -<#+ - } - - internal override void WriteKeyAsSegmentUrlConvention() - { -#> - this.UrlKeyDelimiter = global::Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash; -<#+ - } - - internal override void WriteInitializeResolveName() - { -#> - this.ResolveName = new global::System.Func(this.ResolveNameFromType); -<#+ - } - - internal override void WriteInitializeResolveType() - { -#> - this.ResolveType = new global::System.Func(this.ResolveTypeFromName); -<#+ - } - - internal override void WriteClassEndForEntityContainerConstructor() - { -#> - this.OnContextCreated(); - this.Format.LoadServiceModel = GeneratedEdmModel.GetInstance; - this.Format.UseJson(); - } - partial void OnContextCreated(); -<#+ - } - - internal override void WriteMethodStartForResolveTypeFromName() - { -#> - /// - /// Since the namespace configured for this service reference - /// in Visual Studio is different from the one indicated in the - /// server schema, use type-mappers to map between the two. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected global::System.Type ResolveTypeFromName(string typeName) - { -<#+ - } - - internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) - { -#> - <#= typeName #>resolvedType = this.DefaultResolveType(typeName, "<#= fullNamespace #>", "<#= languageDependentNamespace #>"); - if ((resolvedType != null)) - { - return resolvedType; - } -<#+ - } - - internal override void WriteMethodEndForResolveTypeFromName() - { -#> - return null; - } -<#+ - } - - internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) - { - - } - - internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) - { -#> - /// - /// Since the namespace configured for this service reference - /// in Visual Studio is different from the one indicated in the - /// server schema, use type-mappers to map between the two. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected string ResolveNameFromType(global::System.Type clientType) - { -<#+ - if (this.context.EnableNamingAlias) - { -#> - global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true)); -<#+ - } - } - - internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) - { -#> - if (clientType.Namespace.Equals("<#= languageDependentNamespace #>", global::System.StringComparison.Ordinal)) - { -<#+ - if (this.context.EnableNamingAlias) - { -#> - if (originalNameAttribute != null) - { - return string.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName); - } -<#+ - } -#> - return string.Concat("<#= fullNamespace #>.", clientType.Name); - } -<#+ - } - - internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) - { - if (this.context.EnableNamingAlias && modelHasInheritance) - { -#> - if (originalNameAttribute != null) - { - return clientType.Namespace + "." + originalNameAttribute.OriginalName; - } -<#+ - } -#> - return <#= modelHasInheritance ? "clientType.FullName" : "null" #>; - } -<#+ - } - - internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) - { -#> - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path) - : base(context, path) {} - - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path, bool isComposable) - : base(context, path, isComposable) {} - - /// - /// Initialize a new <#= singleTypeName #> object. - /// - public <#= singleTypeName #>(<#= baseTypeName #> query) - : base(query) {} - -<#+ - } - - internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) - { -#> - /// - /// There are no comments for <#= entitySetName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEntitySetName #>")] -<#+ - } -#> - public global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> <#= entitySetFixedName #> - { - get - { -<#+ - if (!inContext) - { -#> - if (!this.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } -<#+ - } -#> - if ((this._<#= entitySetName #> == null)) - { - this._<#= entitySetName #> = <#= inContext ? "base" : "Context" #>.CreateQuery<<#= entitySetElementTypeName #>>(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>); - } - return this._<#= entitySetName #>; - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> _<#= entitySetName #>; -<#+ - } - - internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) - { -#> - /// - /// There are no comments for <#= singletonName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalSingletonName #>")] -<#+ - } -#> - public <#= singletonElementTypeName #> <#= singletonFixedName #> - { - get - { -<#+ - if (!inContext) - { -#> - if (!this.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } -<#+ - } -#> - if ((this._<#= singletonName #> == null)) - { - this._<#= singletonName #> = new <#= singletonElementTypeName #>(<#= inContext ? "this" : "this.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>); - } - return this._<#= singletonName #>; - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private <#= singletonElementTypeName #> _<#= singletonName #>; -<#+ - } - - internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) - { -#> - /// - /// There are no comments for <#= entitySetName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public void AddTo<#= entitySetName #>(<#= typeName #> <#= parameterName #>) - { - base.AddObject("<#= originalEntitySetName #>", <#= parameterName #>); - } -<#+ - } - - internal override void WriteGeneratedEdmModel(string escapedEdmxString) - { - - string path = this.context.TempFilePath; - - if (!String.IsNullOrEmpty(path)) - { - using (StreamWriter writer = new StreamWriter(path, true)) - { - writer.WriteLine(escapedEdmxString); - } - } - - bool useTempFile = !String.IsNullOrEmpty(path) && System.IO.File.Exists(path); -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private abstract class GeneratedEdmModel - { -<#+ - if (this.context.ReferencesMap != null) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Collections.Generic.Dictionary ReferencesMap = new global::System.Collections.Generic.Dictionary() - { -<#+ - foreach(var reference in this.context.ReferencesMap) - { -#> - {@"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", @"<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"") #>"}, -<#+ - } -#> - }; -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString(); -<#+ - if (useTempFile) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private const string filePath = @"<#= path #>"; -<#+ - } - else - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private const string Edmx = @"<#= escapedEdmxString #>"; -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public static global::Microsoft.OData.Edm.IEdmModel GetInstance() - { - return ParsedModel; - } -<#+ - if (this.context.ReferencesMap != null) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader getReferencedModelFromMap(global::System.Uri uri) - { - string referencedEdmx; - if (ReferencesMap.TryGetValue(uri.OriginalString, out referencedEdmx)) - { - return CreateXmlReader(referencedEdmx); - } - - return null; - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() - { -<#+ - if (useTempFile) - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(); -<#+ - } - else - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); -<#+ - } -#> - try - { - return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, getReferencedModelFromMap); - } - finally - { - ((global::System.IDisposable)(reader)).Dispose(); - } - } -<#+ - } - else - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() - { -<#+ - if (useTempFile) - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(); -<#+ - } - else - { -#> - global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); -<#+ - } -#> - try - { - global::System.Collections.Generic.IEnumerable errors; - global::Microsoft.OData.Edm.IEdmModel edmModel; - - if (!global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, <#= this.context.IgnoreUnexpectedElementsAndAttributes ? "true" : "false" #>, out edmModel, out errors)) - { - global::System.Text.StringBuilder errorMessages = new System.Text.StringBuilder(); - foreach (var error in errors) - { - errorMessages.Append(error.ErrorMessage); - errorMessages.Append("; "); - } - throw new global::System.InvalidOperationException(errorMessages.ToString()); - } - - return edmModel; - } - finally - { - ((global::System.IDisposable)(reader)).Dispose(); - } - } -<#+ - } -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse) - { - return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse)); - } -<#+ - if (useTempFile) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private static global::System.Xml.XmlReader CreateXmlReader() - { - return global::System.Xml.XmlReader.Create(new global::System.IO.StreamReader(filePath)); - } -<#+ - } -#> - } -<#+ - } - - internal override void WriteClassEndForEntityContainer() - { -#> - } -<#+ - } - - internal override void WriteSummaryCommentForStructuredType(string typeName) - { -#> - /// - /// There are no comments for <#= typeName #> in the schema. - /// -<#+ - } - - internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) - { -#> - /// -<#+ - foreach (string key in keyProperties) - { -#> - /// <#= key #> -<#+ - } -#> - /// - [global::Microsoft.OData.Client.Key("<#= keyString #>")] -<#+ - } - - internal override void WriteEntityTypeAttribute() - { -#> - [global::Microsoft.OData.Client.EntityType()] -<#+ - } - - internal override void WriteEntitySetAttribute(string entitySetName) - { -#> - [global::Microsoft.OData.Client.EntitySet("<#= entitySetName #>")] -<#+ - } - - internal override void WriteEntityHasStreamAttribute() - { -#> - [global::Microsoft.OData.Client.HasStream()] -<#+ - } - - internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalTypeName #>")] -<#+ - } -#> - public<#= abstractModifier #> partial class <#= typeName #><#= baseTypeName #> - { -<#+ - } - - internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) - { -#> - /// - /// Create a new <#= typeName #> object. - /// -<#+ - } - - internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) - { -#> - /// Initial value of <#= propertyName #>. -<#+ - } - - internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) - { -#> - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public static <#= fixedTypeName #> Create<#= typeName #>(<#+ - } - - internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) - { -#><#= parameterTypeName #> <#= parameterName #><#= parameterSeparater #><#+ - } - - internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) - { - #>) - { - <#= typeName #> <#= instanceName #> = new <#= typeName #>(); -<#+ - } - - internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) - { -#> - if ((<#= parameterName #> == null)) - { - throw new global::System.ArgumentNullException("<#= parameterName #>"); - } -<#+ - } - - internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) - { -#> - <#= instanceName #>.<#= propertyName #> = <#= parameterName #>; -<#+ - } - - internal override void WriteMethodEndForStaticCreateMethod(string instanceName) - { -#> - return <#= instanceName #>; - } -<#+ - } - - internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) - { -#> - /// - /// There are no comments for Property <#= propertyName #> in the schema. - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] -<#+ - if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalPropertyName #>")] -<#+ - } -#> - public <#= propertyType #> <#= fixedPropertyName #> - { - get - { - return this.<#= privatePropertyName #>; - } - set - { - this.On<#= propertyName #>Changing(value); - this.<#= privatePropertyName #> = value; - this.On<#= propertyName #>Changed(); -<#+ - if (writeOnPropertyChanged) - { -#> - this.OnPropertyChanged("<#= originalPropertyName #>"); -<#+ - } -#> - } - } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - private <#= propertyType #> <#= privatePropertyName #><#= propertyInitializationValue != null ? " = " + propertyInitializationValue : string.Empty #>; - partial void On<#= propertyName #>Changing(<#= propertyType #> value); - partial void On<#= propertyName #>Changed(); -<#+ - } - - internal override void WriteINotifyPropertyChangedImplementation() - { -#> - /// - /// This event is raised when the value of the property is changed - /// - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - /// - /// The value of the property is changed - /// - /// property name - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] - protected virtual void OnPropertyChanged(string property) - { - if ((this.PropertyChanged != null)) - { - this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property)); - } - } -<#+ - } - - internal override void WriteClassEndForStructuredType() - { -#> - } -<#+ - } - - internal override void WriteEnumFlags() - { -#> - [global::System.Flags] -<#+ - } - - internal override void WriteSummaryCommentForEnumType(string enumName) - { -#> - /// - /// There are no comments for <#= enumName #> in the schema. - /// -<#+ - } - - internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEnumName #>")] -<#+ - } -#> - public enum <#= enumName #><#= underlyingType #> - { -<#+ - } - - internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) - { - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalMemberName #>")] -<#+ - } -#> - <#= member #><#= last ? string.Empty : "," #> -<#+ - } - - internal override void WriteEnumEnd() - { -#> - } -<#+ - } - - internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - return this.CreateFunctionQuery<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.CreateFunctionQuerySingle<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - global::System.Uri requestUri; - Context.TryGetUri(this, out requestUri); - return this.Context.CreateFunctionQuery<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>); - } -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - global::System.Uri requestUri; - Context.TryGetUri(this, out requestUri); - - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.Context.CreateFunctionQuerySingle<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public <#= returnTypeName #> <#= actionName #>(<#= parameters #>) - { - return new <#= returnTypeName #>(this, this.BaseUri.OriginalString.Trim('/') + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= returnTypeName #> <#= actionName #>(<#= parameters #>) - { - global::Microsoft.OData.Client.EntityDescriptor resource = Context.EntityTracker.TryGetEntityDescriptor(this); - if (resource == null) - { - throw new global::System.Exception("cannot find entity"); - } - - return new <#= returnTypeName #>(this.Context, resource.EditLink.OriginalString.Trim('/') + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteExtensionMethodsStart() - { -#> - /// - /// Class containing all extension methods - /// - public static class ExtensionMethods - { -<#+ - } - - internal override void WriteExtensionMethodsEnd() - { -#> - } -<#+ - } - - internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) - { -#> - /// - /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - /// - /// source entity set - /// dictionary with the names and values of keys - public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, global::System.Collections.Generic.Dictionary keys) - { - return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); - } - /// - /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - /// - /// source entity set -<#+ - foreach (var key in keys) - { -#> - /// The value of <#= key #> -<#+ - } -#> - public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, - <#= keyParameters #>) - { - global::System.Collections.Generic.Dictionary keys = new global::System.Collections.Generic.Dictionary - { - <#= keyDictionaryItems #> - }; - return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); - } -<#+ - } - - internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) - { -#> - /// - /// Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> - /// - /// source entity - public static <#= returnTypeName #> CastTo<#= derivedTypeName #>(this global::Microsoft.OData.Client.DataServiceQuerySingle<<#= baseTypeName #>> source) - { - global::Microsoft.OData.Client.DataServiceQuerySingle<<#= derivedTypeFullName #>> query = source.CastTo<<#= derivedTypeFullName #>>(); - return new <#= returnTypeName #>(source.Context, query.GetPath(null)); - } -<#+ - } - - internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public static <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; - } -<#+ - } - - internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - /// - /// There are no comments for <#= functionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] -<#+ - } -#> - public static global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = true" : string.Empty #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return source.CreateFunctionQuery<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - /// - /// There are no comments for <#= actionName #> in the schema. - /// -<#+ - if (this.context.EnableNamingAlias) - { -#> - [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] -<#+ - } -#> - public static <#= returnTypeName #> <#= actionName #>(this <#= boundSourceType #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) - { - if (!source.IsComposable) - { - throw new global::System.NotSupportedException("The previous function is not composable."); - } - - return new <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); - } -<#+ - } - - internal override void WriteNamespaceEnd() - { -#> -} -<#+ - } -} - -public sealed class ODataClientVBTemplate : ODataClientTemplate -{ - /// - /// Creates an instance of the ODataClientTemplate. - /// - /// The cotion context. - public ODataClientVBTemplate(CodeGenerationContext context) - : base(context) - { - } - - internal override string GlobalPrefix { get { return string.Empty; } } - internal override string SystemTypeTypeName { get { return "Global.System.Type"; } } - internal override string AbstractModifier { get { return " MustInherit"; } } - internal override string DataServiceActionQueryTypeName { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery"; } } - internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuerySingle(Of {0})"; } } - internal override string DataServiceActionQueryOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery(Of {0})"; } } - internal override string NotifyPropertyChangedModifier { get { return "\r\n Implements Global.System.ComponentModel.INotifyPropertyChanged"; } } - internal override string ClassInheritMarker { get { return "\r\n Inherits "; } } - internal override string ParameterSeparator { get { return ", _\r\n "; } } - internal override string KeyParameterSeparator { get { return ", _\r\n "; } } - internal override string KeyDictionaryItemSeparator { get { return ", _\r\n "; } } - internal override string SystemNullableStructureTemplate { get { return "Global.System.Nullable(Of {0})"; } } - internal override string ICollectionOfTStructureTemplate { get { return "Global.System.Collections.Generic.ICollection(Of {0})"; } } - internal override string DataServiceCollectionStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceCollection(Of {0})"; } } - internal override string DataServiceQueryStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuery(Of {0})"; } } - internal override string DataServiceQuerySingleStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuerySingle(Of {0})"; } } - internal override string ObservableCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.ObservableCollection(Of {0})"; } } - internal override string ObjectModelCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.Collection(Of {0})"; } } - internal override string DataServiceCollectionConstructorParameters { get { return "(Nothing, Global.Microsoft.OData.Client.TrackingMode.None)"; } } - internal override string NewModifier { get { return "New "; } } - internal override string GeoTypeInitializePattern { get { return "Global.Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(False).Read(Of {0})(New Global.System.IO.StringReader(\"{1}\"))"; } } - internal override string Int32TypeName { get { return "Integer"; } } - internal override string ObjectTypeName { get { return "Object"; } } - internal override string StringTypeName { get { return "String"; } } - internal override string BinaryTypeName { get { return "Byte()"; } } - internal override string DecimalTypeName { get { return "Decimal"; } } - internal override string Int16TypeName { get { return "Short"; } } - internal override string SingleTypeName { get { return "Single"; } } - internal override string BooleanTypeName { get { return "Boolean"; } } - internal override string DoubleTypeName { get { return "Double"; } } - internal override string GuidTypeName { get { return "Global.System.Guid"; } } - internal override string ByteTypeName { get { return "Byte"; } } - internal override string Int64TypeName { get { return "Long"; } } - internal override string SByteTypeName { get { return "SByte"; } } - internal override string DataServiceStreamLinkTypeName { get { return "Global.Microsoft.OData.Client.DataServiceStreamLink"; } } - internal override string GeographyTypeName { get { return "Global.Microsoft.Spatial.Geography"; } } - internal override string GeographyPointTypeName { get { return "Global.Microsoft.Spatial.GeographyPoint"; } } - internal override string GeographyLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyLineString"; } } - internal override string GeographyPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyPolygon"; } } - internal override string GeographyCollectionTypeName { get { return "Global.Microsoft.Spatial.GeographyCollection"; } } - internal override string GeographyMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPolygon"; } } - internal override string GeographyMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiLineString"; } } - internal override string GeographyMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPoint"; } } - internal override string GeometryTypeName { get { return "Global.Microsoft.Spatial.Geometry"; } } - internal override string GeometryPointTypeName { get { return "Global.Microsoft.Spatial.GeometryPoint"; } } - internal override string GeometryLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryLineString"; } } - internal override string GeometryPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryPolygon"; } } - internal override string GeometryCollectionTypeName { get { return "Global.Microsoft.Spatial.GeometryCollection"; } } - internal override string GeometryMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPolygon"; } } - internal override string GeometryMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiLineString"; } } - internal override string GeometryMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPoint"; } } - internal override string DateTypeName { get { return "Global.Microsoft.OData.Edm.Date"; } } - internal override string DateTimeOffsetTypeName { get { return "Global.System.DateTimeOffset"; } } - internal override string DurationTypeName { get { return "Global.System.TimeSpan"; } } - internal override string TimeOfDayTypeName { get { return "Global.Microsoft.OData.Edm.TimeOfDay"; } } - internal override string XmlConvertClassName { get { return "Global.System.Xml.XmlConvert"; } } - internal override string EnumTypeName { get { return "Global.System.Enum"; } } - internal override string DictionaryTypeName { get { return "Global.System.Collections.Generic.Dictionary(Of {0}, {1})"; } } - internal override string FixPattern { get { return "[{0}]"; } } - internal override string EnumUnderlyingTypeMarker { get { return " As "; } } - internal override string ConstantExpressionConstructorWithType { get { return "Global.System.Linq.Expressions.Expression.Constant({0}, GetType({1}))"; } } - internal override string TypeofFormatter { get { return "GetType({0})"; } } - internal override string UriOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } - internal override string UriEntityOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } - internal override string BodyOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } - internal override string DictionaryConstructor { get { return $"New {DictionaryTypeName}"; } } - internal override string BaseEntityType { get { return "\r\n Inherits Global.Microsoft.OData.Client.BaseEntityType"; } } - internal override string OverloadsModifier { get { return "Overloads "; } } - internal override string ODataVersion { get { return "Global.Microsoft.OData.ODataVersion.V4"; } } - internal override string ParameterDeclarationTemplate { get { return "{1} As {0}"; } } - internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } - internal override HashSet LanguageKeywords { get { - if (VBKeywords == null) - { - VBKeywords = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte", "ByVal", - "Call", "Case", "Catch", "CBool", "", "CByte", "CChar", "CDate", "CDbl", "CDec", "Char", - "CInt", "Class", "CLng", "CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", - "CType", "CUInt", "CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", - "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", - "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", - "GetXMLNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In", "Inherits", - "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like", "Long", "Loop", "Me", - "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", "Namespace", "Narrowing", "New", "Next", - "Not", "Nothing", "NotInheritable", "NotOverridable", "Object", "Of", "On", "Operator", "Option", "Optional", - "Or", "OrElse", "Out", "Overloads", "Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", - "Protected", "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "SByte", - "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", - "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast", "TypeOf", - "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While", "Widening", "With", - "WithEvents", "WriteOnly", "Xor" - }; - } - return VBKeywords; - } } - private HashSet VBKeywords; - - internal override void WriteFileHeader() - { -#>'------------------------------------------------------------------------------ -' -' This code was generated by a tool. -' Runtime Version:<#= Environment.Version #> -' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. -' -'------------------------------------------------------------------------------ - -Option Strict Off -Option Explicit On - - -'Generation date: <#= DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture) #> -<#+ - } - - internal override void WriteNamespaceStart(string fullNamespace) - { -#> -Namespace <#= fullNamespace #> -<#+ - } - - internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) - { -#> - ''' - '''There are no comments for <#= containerName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Partial Public Class <#= fixedContainerName #> - Inherits Global.Microsoft.OData.Client.DataServiceContext -<#+ - } - - internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) - { -#> - ''' - '''Initialize a new <#= containerName #> object. - ''' - ")> _ - Public Sub New(ByVal serviceRoot As Global.System.Uri) - MyBase.New(serviceRoot, Global.Microsoft.OData.Client.ODataProtocolVersion.V4) -<#+ - } - - internal override void WriteKeyAsSegmentUrlConvention() - { -#> - Me.UrlKeyDelimiter = Global.Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash -<#+ - } - - internal override void WriteInitializeResolveName() - { -#> - Me.ResolveName = AddressOf Me.ResolveNameFromType -<#+ - } - - internal override void WriteInitializeResolveType() - { -#> - Me.ResolveType = AddressOf Me.ResolveTypeFromName -<#+ - } - - internal override void WriteClassEndForEntityContainerConstructor() - { -#> - Me.OnContextCreated - Me.Format.LoadServiceModel = AddressOf GeneratedEdmModel.GetInstance - Me.Format.UseJson() - End Sub - Partial Private Sub OnContextCreated() - End Sub -<#+ - } - - internal override void WriteMethodStartForResolveTypeFromName() - { -#> - ''' - '''Since the namespace configured for this service reference - '''in Visual Studio is different from the one indicated in the - '''server schema, use type-mappers to map between the two. - ''' - ")> _ - Protected Function ResolveTypeFromName(ByVal typeName As String) As Global.System.Type -<#+ - } - - internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) - { - if (!string.IsNullOrEmpty(typeName)) - { -#> - Dim resolvedType As <#= typeName #>= Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) -<#+ - } - else - { -#> - resolvedType = Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) -<#+ - } -#> - If (Not (resolvedType) Is Nothing) Then - Return resolvedType - End If -<#+ - } - - internal override void WriteMethodEndForResolveTypeFromName() - { -#> - Return Nothing - End Function -<#+ - } - - internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) - { -#> - ")> _ - Private Shared ROOTNAMESPACE As String = GetType(<#= containerName #>).Namespace.Remove(GetType(<#= containerName #>).Namespace.LastIndexOf("<#= fullNamespace #>")) -<#+ - } - - internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) - { -#> - ''' - '''Since the namespace configured for this service reference - '''in Visual Studio is different from the one indicated in the - '''server schema, use type-mappers to map between the two. - ''' - ")> _ - Protected Function ResolveNameFromType(ByVal clientType As Global.System.Type) As String -<#+ - if (this.context.EnableNamingAlias) - { -#> - Dim originalNameAttribute As Global.Microsoft.OData.Client.OriginalNameAttribute = - CType(Global.System.Linq.Enumerable.SingleOrDefault(Global.Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, GetType(Global.Microsoft.OData.Client.OriginalNameAttribute), true)), Global.Microsoft.OData.Client.OriginalNameAttribute) -<#+ - } - } - - internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) - { -#> - If clientType.Namespace.Equals(String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>"), Global.System.StringComparison.OrdinalIgnoreCase) Then -<#+ - if (this.context.EnableNamingAlias) - { -#> - If (Not (originalNameAttribute) Is Nothing) Then - Return String.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName) - End If -<#+ - } -#> - Return String.Concat("<#= fullNamespace #>.", clientType.Name) - End If -<#+ - } - - internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) - { - if (this.context.EnableNamingAlias && modelHasInheritance) - { -#> - If (Not (originalNameAttribute) Is Nothing) Then - Dim fullName As String = clientType.FullName.Substring(ROOTNAMESPACE.Length) - Return fullName.Remove(fullName.LastIndexOf(clientType.Name)) + originalNameAttribute.OriginalName - End If -<#+ - } -#> - Return <#= modelHasInheritance ? "clientType.FullName.Substring(ROOTNAMESPACE.Length)" : "Nothing" #> - End Function -<#+ - } - - internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) - { -#> - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String) - MyBase.New(context, path) - End Sub - - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String, ByVal isComposable As Boolean) - MyBase.New(context, path, isComposable) - End Sub - - ''' - ''' Initialize a new <#= singleTypeName #> object. - ''' - Public Sub New(ByVal query As <#= baseTypeName #>) - MyBase.New(query) - End Sub -<#+ - } - - internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) - { -#> - ''' - '''There are no comments for <#= entitySetName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public ReadOnly Property <#= entitySetFixedName #>() As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) - Get -<#+ - if (!inContext) - { -#> - If Not Me.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If -<#+ - } -#> - If (Me._<#= entitySetName #> Is Nothing) Then - Me._<#= entitySetName #> = <#= inContext ? "MyBase" : "Context"#>.CreateQuery(Of <#= entitySetElementTypeName #>)(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>) - End If - Return Me._<#= entitySetName #> - End Get - End Property - ")> _ - Private _<#= entitySetName #> As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) -<#+ - } - - internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) - { -#> - ''' - '''There are no comments for <#= singletonName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public ReadOnly Property <#= singletonFixedName #>() As <#= singletonElementTypeName #> - Get -<#+ - if (!inContext) - { -#> - If Not Me.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If -<#+ - } -#> - If (Me._<#= singletonName #> Is Nothing) Then - Me._<#= singletonName #> = New <#= singletonElementTypeName #>(<#= inContext ? "Me" : "Me.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>) - End If - Return Me._<#= singletonName #> - End Get - End Property - ")> _ - Private _<#= singletonName #> As <#= singletonElementTypeName #> -<#+ - } - - internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) - { -#> - ''' - '''There are no comments for <#= entitySetName #> in the schema. - ''' - ")> _ - Public Sub AddTo<#= entitySetName #>(ByVal <#= parameterName #> As <#= typeName #>) - MyBase.AddObject("<#= originalEntitySetName #>", <#= parameterName #>) - End Sub -<#+ - } - - internal override void WriteGeneratedEdmModel(string escapedEdmxString) - { - escapedEdmxString = escapedEdmxString.Replace("\r\n", "\" & _\r\n \""); -#> - ")> _ - Private MustInherit Class GeneratedEdmModel -<#+ - if (this.context.ReferencesMap != null) - { -#> - ")> _ - Private Shared ReferencesMap As Global.System.Collections.Generic.Dictionary(Of String, String) = New Global.System.Collections.Generic.Dictionary(Of String, String) From - { -<#+ - int count = this.context.ReferencesMap.Count(); - foreach(var reference in this.context.ReferencesMap) - { -#> - {"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", "<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"").Replace("\r\n", "\" & _\r\n \"") #>"}<#= (--count>0?",":"")#> -<#+ - } -#> - } -<#+ - } -#> - ")> _ - Private Shared ParsedModel As Global.Microsoft.OData.Edm.IEdmModel = LoadModelFromString - ")> _ - Private Const Edmx As String = "<#= escapedEdmxString #>" - ")> _ - Public Shared Function GetInstance() As Global.Microsoft.OData.Edm.IEdmModel - Return ParsedModel - End Function -<#+ - if (this.context.ReferencesMap != null) - { -#> - ")> _ - Private Shared Function getReferencedModelFromMap(ByVal uri As Global.System.Uri) As Global.System.Xml.XmlReader - Dim referencedEdmx As String = Nothing - If (ReferencesMap.TryGetValue(uri.OriginalString, referencedEdmx)) Then - Return CreateXmlReader(referencedEdmx) - End If - Return Nothing - End Function - ")> _ - Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel - Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) - Try - Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, AddressOf getReferencedModelFromMap) - Finally - CType(reader,Global.System.IDisposable).Dispose - End Try - End Function -<#+ - } - else - { -#> - ")> _ - Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel - Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) - Try - Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader) - Finally - CType(reader,Global.System.IDisposable).Dispose - End Try - End Function -<#+ - } -#> - ")> _ - Private Shared Function CreateXmlReader(ByVal edmxToParse As String) As Global.System.Xml.XmlReader - Return Global.System.Xml.XmlReader.Create(New Global.System.IO.StringReader(edmxToParse)) - End Function - End Class -<#+ - } - - internal override void WriteClassEndForEntityContainer() - { -#> - End Class -<#+ - } - - internal override void WriteSummaryCommentForStructuredType(string typeName) - { -#> - ''' - '''There are no comments for <#= typeName #> in the schema. - ''' -<#+ - } - - internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) - { -#> - ''' -<#+ - foreach (string key in keyProperties) - { -#> - '''<#= key #> -<#+ - } -#> - ''' - ")> _ -<#+ - } - - internal override void WriteEntityTypeAttribute() - { -#> - _ -<#+ - } - - internal override void WriteEntitySetAttribute(string entitySetName) - { -#> - ")> _ -<#+ - } - - internal override void WriteEntityHasStreamAttribute() - { -#> - _ -<#+ - } - - internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Partial Public<#= abstractModifier #> Class <#= typeName #><#= baseTypeName #> -<#+ - } - - internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) - { -#> - ''' - '''Create a new <#= typeName #> object. - ''' -<#+ - } - - internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) - { -#> - '''Initial value of <#= propertyName #>. -<#+ - } - - internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) - { -#> - ")> _ - Public Shared Function Create<#= typeName #>(<#+ - - } - - internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) - { -#>ByVal <#= parameterName #> As <#= parameterTypeName #><#= parameterSeparater #><#+ - } - - internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) - { - #>) As <#= typeName #> - Dim <#= instanceName #> As <#= typeName #> = New <#= typeName #>() -<#+ - } - - internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) - { -#> - If (<#= parameterName #> Is Nothing) Then - Throw New Global.System.ArgumentNullException("<#= parameterName #>") - End If -<#+ - } - - internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) - { -#> - <#= instanceName #>.<#= propertyName #> = <#= parameterName #> -<#+ - } - - internal override void WriteMethodEndForStaticCreateMethod(string instanceName) - { -#> - Return <#= instanceName #> - End Function -<#+ - } - - internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) - { -#> - ''' - '''There are no comments for Property <#= propertyName #> in the schema. - ''' - ")> _ -<#+ - if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) - { -#> - ")> _ -<#+ - } -#> - Public Property <#= fixedPropertyName #>() As <#= propertyType #> - Get - Return Me.<#= privatePropertyName #> - End Get - Set - Me.On<#= propertyName #>Changing(value) - Me.<#= privatePropertyName #> = value - Me.On<#= propertyName #>Changed -<#+ - if (writeOnPropertyChanged) - { -#> - Me.OnPropertyChanged("<#= originalPropertyName #>") -<#+ - } -#> - End Set - End Property - ")> _ -<#+ - string constructorString = string.Empty; - if (!string.IsNullOrEmpty(propertyInitializationValue)) - { - constructorString = " = " + propertyInitializationValue; - } -#> - Private <#= privatePropertyName #> As <#= propertyType #><#= constructorString #> - Partial Private Sub On<#= propertyName #>Changing(ByVal value As <#= propertyType #>) - End Sub - Partial Private Sub On<#= propertyName #>Changed() - End Sub -<#+ - } - - internal override void WriteINotifyPropertyChangedImplementation() - { -#> - ''' - ''' This event is raised when the value of the property is changed - ''' - ")> _ - Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements Global.System.ComponentModel.INotifyPropertyChanged.PropertyChanged - ''' - ''' The value of the property is changed - ''' - ''' property name - ")> _ - Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) - If (Not (Me.PropertyChangedEvent) Is Nothing) Then - RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property])) - End If - End Sub -<#+ - } - - internal override void WriteClassEndForStructuredType() - { -#> - End Class -<#+ - } - - internal override void WriteEnumFlags() - { -#> - -<#+ - } - - internal override void WriteSummaryCommentForEnumType(string enumName) - { -#> - ''' - '''There are no comments for <#= enumName #> in the schema. - ''' -<#+ - } - - internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Enum <#= enumName #><#= underlyingType #> -<#+ - } - - internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) - { - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - <#= member #> -<#+ - } - - internal override void WriteEnumEnd() - { -#> - End Enum -<#+ - } - - internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - Return Me.CreateFunctionQuery(Of <#= returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #> <#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - Dim requestUri As Global.System.Uri = Nothing - Context.TryGetUri(Me, requestUri) - Return Me.Context.CreateFunctionQuery(Of <#= returnTypeName #>)("", String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))) + "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - Dim requestUri As Global.System.Uri = Nothing - Context.TryGetUri(Me, requestUri) - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.Context.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)(String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))), "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> - Return New <#= returnTypeName #>(Me, Me.BaseUri.OriginalString.Trim("/"C) + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> - Dim resource As Global.Microsoft.OData.Client.EntityDescriptor = Context.EntityTracker.TryGetEntityDescriptor(Me) - If resource Is Nothing Then - Throw New Global.System.Exception("cannot find entity") - End If - - Return New <#= returnTypeName #>(Me.Context, resource.EditLink.OriginalString.Trim("/"C) + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteExtensionMethodsStart() - { -#> - ''' - ''' Class containing all extension methods - ''' - Public Module ExtensionMethods -<#+ - } - - internal override void WriteExtensionMethodsEnd() - { -#> - End Module -<#+ - } - - internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) - { -#> - ''' - ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - ''' - ''' source entity set - ''' dictionary with the names and values of keys - - Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), ByVal keys As Global.System.Collections.Generic.Dictionary(Of String, Object)) As <#= returnTypeName #> - Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) - End Function - ''' - ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set - ''' - ''' source entity set -<#+ - foreach (var key in keys) - { -#> - ''' The value of <#= key #> -<#+ - } -#> - - Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), - <#= keyParameters #>) As <#= returnTypeName #> - Dim keys As Global.System.Collections.Generic.Dictionary(Of String, Object) = New Global.System.Collections.Generic.Dictionary(Of String, Object)() From - { - <#= keyDictionaryItems #> - } - Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) - End Function -<#+ - } - - internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) - { -#> - ''' - ''' Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> - ''' - ''' source entity - - Public Function CastTo<#= derivedTypeName #>(ByVal source As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= baseTypeName #>)) As <#= returnTypeName #> - Dim query As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= derivedTypeFullName #>) = source.CastTo(Of <#= derivedTypeFullName #>)() - Return New <#= returnTypeName #>(source.Context, query.GetPath(Nothing)) - End Function -<#+ - } - - internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - - Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> - End Function -<#+ - } - - internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) - { -#> - ''' - ''' There are no comments for <#= functionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - - Return source.CreateFunctionQuery(Of <#= returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) - { -#> - ''' - ''' There are no comments for <#= actionName #> in the schema. - ''' - -<#+ - if (this.context.EnableNamingAlias) - { -#> - ")> _ -<#+ - } -#> - Public Function <#= actionName #>(ByVal source As <#= boundSourceType #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) As <#= returnTypeName #> - If Not source.IsComposable Then - Throw New Global.System.NotSupportedException("The previous function is not composable.") - End If - Return New <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) - End Function -<#+ - } - - internal override void WriteNamespaceEnd() - { -#> -End Namespace -<#+ - } -} +<# +/* +OData Client T4 Template ver. #VersionNumber# +Copyright (c) Microsoft Corporation +All rights reserved. +MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#> +<#@ template debug="true" hostSpecific="true" visibility="internal" linePragmas="false"#> +<#@ output extension=".cs" #> +<#@ Assembly Name="System.Core.dll" #> +<#@ Assembly Name="System.IO.dll" #> +<#@ Assembly Name="System.Runtime.dll" #> +<#@ Assembly Name="System.Xml.dll" #> +<#@ Assembly Name="System.Xml.Linq.dll" #> +<#@ Assembly Name="System.Xml.ReaderWriter.dll" #> +<#@ Assembly Name="System.Windows.Forms.dll" #> +<#@ Assembly Name="Microsoft.OData.Client.dll" #> +<#@ Assembly Name="Microsoft.OData.Core.dll" #> +<#@ Assembly Name="Microsoft.OData.Edm.dll" #> +<#@ Assembly Name="Microsoft.Spatial.dll" #> +<#@ Import Namespace="System" #> +<#@ Import Namespace="System.IO" #> +<#@ Import Namespace="System.Diagnostics" #> +<#@ Import Namespace="System.Globalization" #> +<#@ Import Namespace="System.Linq" #> +<#@ Import Namespace="System.Xml"#> +<#@ Import Namespace="System.Xml.Linq" #> +<#@ Import Namespace="System.Collections.Generic" #> +<#@ Import Namespace="Microsoft.OData.Edm.Csdl" #> +<#@ Import Namespace="Microsoft.OData.Edm" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.V1" #> +<#@ Import Namespace="Microsoft.OData.Edm.Vocabularies.Community.V1" #> +<#@ Import Namespace="System.Text"#> +<#@ Import Namespace="System.Net"#> +<# + CodeGenerationContext context; + if (!string.IsNullOrWhiteSpace(this.Edmx)) + { + context = new CodeGenerationContext(this.Edmx, this.NamespacePrefix) + { + UseDataServiceCollection = this.UseDataServiceCollection, + TargetLanguage = this.TargetLanguage, + EnableNamingAlias = this.EnableNamingAlias, + TempFilePath = this.TempFilePath, + IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, + GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, + DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName + }; + } + else + { + this.ApplyParametersFromCommandLine(); + if (string.IsNullOrEmpty(metadataDocumentUri)) + { + this.ApplyParametersFromConfigurationClass(); + } + + context = new CodeGenerationContext(new Uri(this.MetadataDocumentUri, UriKind.Absolute), this.NamespacePrefix) + { + UseDataServiceCollection = this.UseDataServiceCollection, + TargetLanguage = this.TargetLanguage, + EnableNamingAlias = this.EnableNamingAlias, + TempFilePath = this.TempFilePath, + IgnoreUnexpectedElementsAndAttributes = this.IgnoreUnexpectedElementsAndAttributes, + GenerateDynamicPropertiesCollection = this.GenerateDynamicPropertiesCollection, + DynamicPropertiesCollectionName = this.DynamicPropertiesCollectionName + }; + } + + if (this.GetReferencedModelReaderFunc != null) + { + context.GetReferencedModelReaderFunc = this.GetReferencedModelReaderFunc; + } + + ODataClientTemplate template; + switch(this.TargetLanguage) + { + case LanguageOption.CSharp: + template = new ODataClientCSharpTemplate(context); + break; + case LanguageOption.VB: + template = new ODataClientVBTemplate(context); + break; + + default: + throw new NotSupportedException(string.Format("Code gen for the target language '{0}' is not supported.", this.TargetLanguage.ToString())); + } + +#><#=template.TransformText()#><# + foreach (string warning in context.Warnings) + { + this.Warning(warning); + } +#><#+ +/// +/// The string for the edmx content. +/// +public string Edmx +{ + get; + set; +} + +/// +/// The Uri string to the metadata document. +/// +public string MetadataDocumentUri +{ + get + { + return this.metadataDocumentUri; + } + + set + { + value = Uri.UnescapeDataString(value); + Uri uri; + if (!Uri.TryCreate(value, UriKind.Absolute, out uri)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" is not a valid MetadataDocumentUri because is it not a valid absolute Uri. The MetadataDocumentUri must be set to an absolute Uri referencing the $metadata endpoint of an OData service.", value)); + } + + if (uri.Scheme == "http" || uri.Scheme == "https") + { + value = uri.Scheme + "://" + uri.Authority + uri.AbsolutePath; + value = value.TrimEnd('/'); + if (!value.EndsWith("$metadata")) + { + value += "/$metadata"; + } + } + + this.metadataDocumentUri = value; + } +} + +private string metadataDocumentUri; + +/// +/// The Func to get referenced model's XmlReader. Must have value when the this.Edmx xml or this.metadataDocumentUri's model has referneced model. +/// +public Func GetReferencedModelReaderFunc +{ + get; + set; +} + +/// +/// The NamespacePrefix is used as the only namespace for types in the same namespace as the default container, +/// and as a prefix for the namespace from the model for everything else. If this argument is null, the +/// namespaces from the model are used for all types. +/// +public string NamespacePrefix +{ + get + { + return this.namespacePrefix; + } + + set + { + if (string.IsNullOrWhiteSpace(value)) + { + this.namespacePrefix = null; + } + else + { + this.namespacePrefix = value; + } + } +} + +private string namespacePrefix; + +/// +/// true to use DataServiceCollection in the generated code, false otherwise. +/// +public bool UseDataServiceCollection +{ + get; + set; +} + +/// +/// Specifies which specific .Net Framework language the generated code will target. +/// +public LanguageOption TargetLanguage +{ + get; + set; +} + +/// +/// true to use Upper camel case for all class and property names, false otherwise. +/// +public bool EnableNamingAlias +{ + get; + set; +} + +/// +/// The path for the temporary file where the metadata xml document can be stored. +/// +public string TempFilePath +{ + get; + set; +} + +/// +/// true to ignore unknown elements or attributes in metadata, false otherwise. +/// +public bool IgnoreUnexpectedElementsAndAttributes +{ + get; + set; +} + + /// + /// true to generate open type property dirctionary, false otherwise. + /// + public bool GenerateDynamicPropertiesCollection + { + get; + set; + } + + /// + /// Name of the OpenType dictionary property + /// + public string DynamicPropertiesCollectionName + { + get; + set; + } + +/// +/// Generate code targeting a specific .Net Framework language. +/// +public enum LanguageOption +{ + /// Generate code for C# language. + CSharp = 0, + + /// Generate code for Visual Basic language. + VB = 1, +} + +/// +/// Set the UseDataServiceCollection property with the given value. +/// +/// The value to set. +public void ValidateAndSetUseDataServiceCollectionFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the UseDataServiceCollection parameter because it is not a valid boolean value.", stringValue)); + } + + this.UseDataServiceCollection = boolValue; +} + +/// +/// Tries to set the TargetLanguage property with the given value. +/// +/// The value to set. +public void ValidateAndSetTargetLanguageFromString(string stringValue) +{ + LanguageOption option; + if (!Enum.TryParse(stringValue, true, out option)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the TargetLanguage parameter because it is not a valid LanguageOption. The supported LanguageOptions are \"CSharp\" and \"VB\".", stringValue)); + } + + this.TargetLanguage = option; +} + +/// +/// Set the EnableNamingAlias property with the given value. +/// +/// The value to set. +public void ValidateAndSetEnableNamingAliasFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the EnableNamingAlias parameter because it is not a valid boolean value.", stringValue)); + } + + this.EnableNamingAlias = boolValue; +} + +/// +/// Set the IgnoreUnexpectedElementsAndAttributes property with the given value. +/// +/// The value to set. +public void ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the IgnoreUnexpectedElementsAndAttributes parameter because it is not a valid boolean value.", stringValue)); + } + + this.IgnoreUnexpectedElementsAndAttributes = boolValue; +} + +/// +/// Set the GenerateDynamicPropertiesCollection property with the given value. +/// +/// The value to set. +public void ValidateAndSetGenerateDynamicPropertiesCollectionFromString(string stringValue) +{ + bool boolValue; + if (!bool.TryParse(stringValue, out boolValue)) + { + // ******************************************************************************************************** + // To fix this error, if the current text transformation is run by the TextTemplatingFileGenerator + // custom tool inside Visual Studio, update the .odata.config file in the project with a valid parameter + // value then hit Ctrl-S to save the .tt file to refresh the code generation. + // ******************************************************************************************************** + throw new ArgumentException(string.Format("The value \"{0}\" cannot be assigned to the GenerateDynamicPropertiesCollection parameter because it is not a valid boolean value.", stringValue)); + } + + this.GenerateDynamicPropertiesCollection = boolValue; +} + +/// +/// Reads the parameter values from the Configuration class and applies them. +/// +private void ApplyParametersFromConfigurationClass() +{ + this.MetadataDocumentUri = Configuration.MetadataDocumentUri; + this.NamespacePrefix = Configuration.NamespacePrefix; + this.UseDataServiceCollection = Configuration.UseDataServiceCollection; + this.ValidateAndSetTargetLanguageFromString(Configuration.TargetLanguage); + this.EnableNamingAlias = Configuration.EnableNamingAlias; + this.TempFilePath = Configuration.TempFilePath; + this.IgnoreUnexpectedElementsAndAttributes = Configuration.IgnoreUnexpectedElementsAndAttributes; + this.GenerateDynamicPropertiesCollection = Configuration.GenerateDynamicPropertiesCollection; + this.DynamicPropertiesCollectionName = Configuration.DynamicPropertiesCollectionName; +} + +/// +/// Reads the parameter values from the command line (TextTransform.exe) and applies them. +/// +private void ApplyParametersFromCommandLine() +{ + if (this.Host == null) + { + return; + } + + string metadataDocumentUri = this.Host.ResolveParameterValue("notempty", "notempty", "MetadataDocumentUri"); + if (!string.IsNullOrEmpty(metadataDocumentUri)) + { + this.MetadataDocumentUri = metadataDocumentUri; + } + + string namespacePrefix = this.Host.ResolveParameterValue("notempty", "notempty", "NamespacePrefix"); + if (!string.IsNullOrEmpty(namespacePrefix)) + { + this.NamespacePrefix = namespacePrefix; + } + + string useDataServiceCollection = this.Host.ResolveParameterValue("notempty", "notempty", "UseDataServiceCollection"); + if (!string.IsNullOrEmpty(useDataServiceCollection)) + { + this.ValidateAndSetUseDataServiceCollectionFromString(useDataServiceCollection); + } + + string targetLanguage = this.Host.ResolveParameterValue("notempty", "notempty", "TargetLanguage"); + if (!string.IsNullOrEmpty(targetLanguage)) + { + this.ValidateAndSetTargetLanguageFromString(targetLanguage); + } + + string enableNamingAlias = this.Host.ResolveParameterValue("notempty", "notempty", "EnableNamingAlias"); + if (!string.IsNullOrEmpty(enableNamingAlias)) + { + this.ValidateAndSetEnableNamingAliasFromString(enableNamingAlias); + } + + string ignoreUnexpectedElementsAndAttributes = this.Host.ResolveParameterValue("notempty", "notempty", "IgnoreUnexpectedElementsAndAttributes"); + if (!string.IsNullOrEmpty(ignoreUnexpectedElementsAndAttributes)) + { + this.ValidateAndSetIgnoreUnexpectedElementsAndAttributesFromString(ignoreUnexpectedElementsAndAttributes); + } + + string generateDynamicPropertiesCollection = this.Host.ResolveParameterValue("notempty", "notempty", "GenerateDynamicPropertiesCollection"); + if (!string.IsNullOrEmpty(generateDynamicPropertiesCollection)) + { + this.ValidateAndSetGenerateDynamicPropertiesCollectionFromString(generateDynamicPropertiesCollection); + } + + string dynamicPropertiesCollectionName = this.Host.ResolveParameterValue("notempty", "notempty", "DynamicPropertiesCollectionName"); + if (!string.IsNullOrEmpty(dynamicPropertiesCollectionName)) + { + this.DynamicPropertiesCollectionName = dynamicPropertiesCollectionName; + } +} + +/// +/// Context object to provide the model and configuration info to the code generator. +/// +public class CodeGenerationContext +{ + /// + /// The namespace of the term to use when building annotations for indicating the conventions used. + /// + private const string ConventionTermNamespace = "Com.Microsoft.OData.Service.Conventions.V1"; + + /// + /// The name of the term to use when building annotations for indicating the conventions used. + /// + private const string ConventionTermName = "UrlConventions"; + + /// + /// The string value for indicating that the key-as-segment convention is being used in annotations and headers. + /// + private const string KeyAsSegmentConventionName = "KeyAsSegment"; + + /// + /// The XElement for the edmx + /// + private readonly XElement edmx; + + /// + /// The namespacePrefix is used as the only namespace in generated code when there's only one schema in edm model, + /// and as a prefix for the namespace from the model with multiple schemas. If this argument is null, the + /// namespaces from the model are used for all types. + /// + private readonly string namespacePrefix; + + /// + /// The EdmModel to generate code for. + /// + private IEdmModel edmModel; + + /// + /// The array of namespaces in the current edm model. + /// + private string[] namespacesInModel; + + /// + /// The array of warnings occured when parsing edm model. + /// + private string[] warnings; + + /// + /// true if the model contains any structural type with inheritance, false otherwise. + /// + private bool? modelHasInheritance; + + /// + /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. + /// Otherwise this is an empty dictionary. + /// + private Dictionary namespaceMap; + + /// + /// Maps the element type of a navigation source to the navigation source. + /// + private Dictionary> elementTypeToNavigationSourceMap; + + /// + /// HashSet contains the pair of Names and Namespaces of EntityContainers using KeyAsSegment url convention + /// + private HashSet keyAsSegmentContainers; + + /// + /// Constructs an instance of . + /// + /// The Uri to the metadata document. The supported scheme are File, http and https. + public CodeGenerationContext(Uri metadataUri, string namespacePrefix) + : this(GetEdmxStringFromMetadataPath(metadataUri), namespacePrefix) + { + } + + /// + /// Constructs an instance of . + /// + /// The string for the edmx. + /// The namespacePrefix is used as the only namespace in generated code + /// when there's only one schema in edm model, and as a prefix for the namespace from the model with multiple + /// schemas. If this argument is null, the namespaces from the model are used for all types. + public CodeGenerationContext(string edmx, string namespacePrefix) + { + this.edmx = XElement.Parse(edmx); + this.namespacePrefix = namespacePrefix; + } + + /// + /// The EdmModel to generate code for. + /// + public XElement Edmx + { + get { return this.edmx; } + } + + /// + /// The EdmModel to generate code for. + /// + public IEdmModel EdmModel + { + get + { + if (this.edmModel == null) + { + Debug.Assert(this.edmx != null, "this.edmx != null"); + + IEnumerable errors; + CsdlReaderSettings edmxReaderSettings = new CsdlReaderSettings() + { + GetReferencedModelReaderFunc = this.GetReferencedModelReaderFuncWrapper, + IgnoreUnexpectedAttributesAndElements = this.IgnoreUnexpectedElementsAndAttributes + }; + if (!CsdlReader.TryParse(this.edmx.CreateReader(ReaderOptions.None), Enumerable.Empty(), edmxReaderSettings, out this.edmModel, out errors)) + { + Debug.Assert(errors != null, "errors != null"); + throw new InvalidOperationException(errors.FirstOrDefault().ErrorMessage); + } + else if (this.IgnoreUnexpectedElementsAndAttributes) + { + if (errors != null && errors.Any()) + { + this.warnings = errors.Select(e => e.ErrorMessage).ToArray(); + } + } + } + + return this.edmModel; + } + } + + /// + /// The func for user code to overwrite and provide referenced model's XmlReader. + /// + public Func GetReferencedModelReaderFunc + { + get { return getReferencedModelReaderFunc; } + set { this.getReferencedModelReaderFunc = value; } + } + + /// + /// Basic setting for XmlReader. + /// + private static readonly XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true }; + + /// + /// The func for user code to overwrite and provide referenced model's XmlReader. + /// + private Func getReferencedModelReaderFunc = uri => XmlReader.Create(GetEdmxStreamFromUri(uri), settings); + + /// + /// The Wrapper func for user code to overwrite and provide referenced model's stream. + /// + public Func GetReferencedModelReaderFuncWrapper + { + get + { + return (uri) => + { + using (XmlReader reader = GetReferencedModelReaderFunc(uri)) + { + if (reader == null) + { + return null; + } + + XElement element = XElement.Load(reader); + if (this.ReferencesMap == null) + { + this.ReferencesMap = new Dictionary(); + } + + this.ReferencesMap.Add(uri, element); + return element.CreateReader(ReaderOptions.None); + } + }; + } + } + + /// + /// Dictionary that stores uri and referenced xml mapping. + /// + public Dictionary ReferencesMap + { + get; + set; + } + + /// + /// The array of namespaces in the current edm model. + /// + public string[] NamespacesInModel + { + get + { + if (this.namespacesInModel == null) + { + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + this.namespacesInModel = GetElementsFromModelTree(this.EdmModel, (m) => m.SchemaElements.Select(e => e.Namespace)).Distinct().ToArray(); + } + + return this.namespacesInModel; + } + } + + /// + /// The array of warnings occured when parsing edm model. + /// + public string[] Warnings + { + get { return this.warnings ?? (this.warnings = new string[] {}); } + } + + /// + /// true if the model contains any structural type with inheritance, false otherwise. + /// + public bool ModelHasInheritance + { + get + { + if (!this.modelHasInheritance.HasValue) + { + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + this.modelHasInheritance = this.EdmModel.SchemaElementsAcrossModels() + .OfType().Any(t => !t.FullTypeName().StartsWith("Org.OData.Authorization.V1") && t.BaseType != null); + } + + return this.modelHasInheritance.Value; + } + } + + /// + /// true if we need to generate the ResolveNameFromType method, false otherwise. + /// + public bool NeedResolveNameFromType + { + get { return this.ModelHasInheritance || this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } + } + + /// + /// true if we need to generate the ResolveTypeFromName method, false otherwise. + /// + public bool NeedResolveTypeFromName + { + get { return this.NamespaceMap.Count > 0 || this.EnableNamingAlias; } + } + + /// + /// If the namespacePrefix is not null, this contains the mapping of namespaces in the model to the corresponding prefixed namespaces. + /// Otherwise this is an empty dictionary. + /// + public Dictionary NamespaceMap + { + get + { + if (this.namespaceMap == null) + { + if (!string.IsNullOrEmpty(this.namespacePrefix)) + { + if (this.NamespacesInModel.Count() == 1) + { + IEdmEntityContainer container = this.EdmModel.EntityContainer; + string containerNamespace = container == null ? null : container.Namespace; + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => ns == containerNamespace ? + this.namespacePrefix : + this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); + } + else + { + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => this.namespacePrefix + "." + (this.EnableNamingAlias ? Customization.CustomizeNamespace(ns) : ns)); + } + } + else if (this.EnableNamingAlias) + { + this.namespaceMap = this.NamespacesInModel + .Distinct() + .ToDictionary( + ns => ns, + ns => Customization.CustomizeNamespace(ns)); + } + else + { + this.namespaceMap = new Dictionary(); + } + } + + return this.namespaceMap; + } + } + + /// + /// true to use DataServiceCollection in the generated code, false otherwise. + /// + public bool UseDataServiceCollection + { + get; + set; + } + + /// + /// Specifies which specific .Net Framework language the generated code will target. + /// + public LanguageOption TargetLanguage + { + get; + set; + } + + /// + /// The path for the temporary file where the metadata xml document can be stored. + /// + public string TempFilePath + { + get; + set; + } + /// + /// true to use Upper camel case for all class and property names, false otherwise. + /// + public bool EnableNamingAlias + { + get; + set; + } + + /// + /// true to ignore unknown elements or attributes in metadata, false otherwise. + /// + public bool IgnoreUnexpectedElementsAndAttributes + { + get; + set; + } + + /// + /// true to generate open type property dirctionary, false otherwise. + /// + public bool GenerateDynamicPropertiesCollection + { + get; + set; + } + + /// + /// Name of the OpenType dictionary property + /// + public string DynamicPropertiesCollectionName + { + get; + set; + } + + /// + /// Maps the element type of an entity set to the entity set. + /// + public Dictionary> ElementTypeToNavigationSourceMap + { + get + { + return this.elementTypeToNavigationSourceMap ?? (this.elementTypeToNavigationSourceMap = new Dictionary>(EqualityComparer.Default)); + } + } + + /// + /// true if this EntityContainer need to set the UrlConvention to KeyAsSegment, false otherwise. + /// + public bool UseKeyAsSegmentUrlConvention(IEdmEntityContainer currentContainer) + { + if (this.keyAsSegmentContainers == null) + { + this.keyAsSegmentContainers = new HashSet(); + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + IEnumerable annotations = this.EdmModel.VocabularyAnnotations; + foreach(IEdmVocabularyAnnotation valueAnnotation in annotations) + { + IEdmEntityContainer container = valueAnnotation.Target as IEdmEntityContainer; + IEdmTerm valueTerm = valueAnnotation.Term; + IEdmStringConstantExpression expression = valueAnnotation.Value as IEdmStringConstantExpression; + if (container != null && valueTerm != null && expression != null) + { + if (valueTerm.Namespace == ConventionTermNamespace && + valueTerm.Name == ConventionTermName && + expression.Value == KeyAsSegmentConventionName) + { + this.keyAsSegmentContainers.Add(container.FullName()); + } + } + } + } + + return this.keyAsSegmentContainers.Contains(currentContainer.FullName()); + } + + /// + /// Gets the enumeration of schema elements with the given namespace. + /// + /// The namespace of the schema elements to get. + /// The enumeration of schema elements with the given namespace. + public IEnumerable GetSchemaElements(string ns) + { + Debug.Assert(ns != null, "ns != null"); + Debug.Assert(this.EdmModel != null, "this.EdmModel != null"); + return GetElementsFromModelTree(this.EdmModel, m => m.SchemaElements.Where(e => e.Namespace == ns)); + } + + /// + /// Gets the namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. + /// + /// The schema element to get the full name for. + /// The fixed name of this schemaElement. + /// The current code generate template. + /// The namespace qualified name for the given with the namespace prefix applied if this.NamespacePrefix is specified. + public string GetPrefixedFullName(IEdmSchemaElement schemaElement, string schemaElementFixedName, ODataClientTemplate template, bool needGlobalPrefix = true) + { + if (schemaElement == null) + { + return null; + } + + return this.GetPrefixedNamespace(schemaElement.Namespace, template, true, needGlobalPrefix) + "." + schemaElementFixedName; + } + + /// + /// Gets the prefixed namespace for the given . + /// + /// The namespace without the prefix. + /// The current code generate template. + /// The flag indicates whether the namespace need to be fixed now. + /// The flag indicates whether the namespace need to be added by gloabal prefix. + /// The prefixed namespace for the given . + public string GetPrefixedNamespace(string ns, ODataClientTemplate template, bool needFix, bool needGlobalPrefix) + { + if (ns == null) + { + return null; + } + + string prefixedNamespace; + if (!this.NamespaceMap.TryGetValue(ns, out prefixedNamespace)) + { + prefixedNamespace = ns; + } + + if (needFix) + { + string[] segments = prefixedNamespace.Split('.'); + prefixedNamespace = string.Empty; + int n = segments.Length; + for (int i = 0; i < n; ++i) + { + if (template.LanguageKeywords.Contains(segments[i])) + { + prefixedNamespace += string.Format(template.FixPattern, segments[i]); + } + else + { + prefixedNamespace += segments[i]; + } + + prefixedNamespace += (i == n - 1 ? string.Empty : "."); + } + } + + if (needGlobalPrefix) + { + prefixedNamespace = template.GlobalPrefix + prefixedNamespace; + } + + return prefixedNamespace; + } + + /// + /// Reads the edmx string from a file path or a http/https path. + /// + /// The Uri to the metadata document. The supported scheme are File, http and https. + private static string GetEdmxStringFromMetadataPath(Uri metadataUri) + { + string content = null; + using (StreamReader streamReader = new StreamReader(GetEdmxStreamFromUri(metadataUri))) + { + content = streamReader.ReadToEnd(); + } + + return content; + } + + /// + /// Get the metadata stream from a file path or a http/https path. + /// + /// The Uri to the stream. The supported scheme are File, http and https. + private static Stream GetEdmxStreamFromUri(Uri metadataUri) + { + Debug.Assert(metadataUri != null, "metadataUri != null"); + Stream metadataStream = null; + if (metadataUri.Scheme == "file") + { + metadataStream = new FileStream(Uri.UnescapeDataString(metadataUri.AbsolutePath), FileMode.Open, FileAccess.Read); + } + else if (metadataUri.Scheme == "http" || metadataUri.Scheme == "https") + { + try + { + HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(metadataUri); + WebResponse webResponse = webRequest.GetResponse(); + metadataStream = webResponse.GetResponseStream(); + } + catch (WebException e) + { + HttpWebResponse webResponse = e.Response as HttpWebResponse; + if (webResponse != null && webResponse.StatusCode == HttpStatusCode.Unauthorized) + { + throw new WebException("Failed to access the metadata document. The OData service requires authentication for accessing it. Please download the metadata, store it into a local file, and set the value of “MetadataDocumentUri” in the .odata.config file to the file path. After that, run custom tool again to generate the OData Client code."); + } + else + { + throw e; + } + } + } + else + { + throw new ArgumentException("Only file, http, https schemes are supported for paths to metadata source locations."); + } + + return metadataStream; + } + + private static IEnumerable GetElementsFromModelTree(IEdmModel mainModel, Func> getElementFromOneModelFunc) + { + List ret = new List(); + if(mainModel is EdmCoreModel || mainModel.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null) + { + return ret; + } + + ret.AddRange(getElementFromOneModelFunc(mainModel)); + foreach (var tmp in mainModel.ReferencedModels) + { + if (tmp is EdmCoreModel || + tmp.FindDeclaredTerm(CoreVocabularyConstants.OptimisticConcurrency) != null || + tmp.FindDeclaredTerm(CapabilitiesVocabularyConstants.ChangeTracking) != null || + tmp.FindDeclaredTerm(AlternateKeysVocabularyConstants.AlternateKeys) != null || + tmp.FindDeclaredTerm("Org.OData.Authorization.V1.Authorizations") != null) + { + continue; + } + + ret.AddRange(getElementFromOneModelFunc(tmp)); + } + + return ret; + } +} + +/// +/// The template class to generate the OData client code. +/// +public abstract class ODataClientTemplate : TemplateBase +{ + protected const string T4Version = "#VersionNumber#"; + + /// + /// The code generation context. + /// + protected readonly CodeGenerationContext context; + + /// + /// The Dictionary to store identifier mappings when there are duplicate names between properties and Entity/Complex types + /// + protected Dictionary IdentifierMappings = new Dictionary(StringComparer.Ordinal); + + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The code generation context. + public ODataClientTemplate(CodeGenerationContext context) + { + this.context = context; + } + + internal string SingleSuffix + { + get { return "Single"; } + } + + #region Get Language specific keyword names. + internal abstract string GlobalPrefix { get; } + internal abstract string SystemTypeTypeName { get; } + internal abstract string AbstractModifier { get; } + internal abstract string DataServiceActionQueryTypeName { get; } + internal abstract string DataServiceActionQuerySingleOfTStructureTemplate { get; } + internal abstract string DataServiceActionQueryOfTStructureTemplate { get; } + internal abstract string NotifyPropertyChangedModifier { get; } + internal abstract string ClassInheritMarker { get; } + internal abstract string ParameterSeparator { get; } + internal abstract string KeyParameterSeparator { get; } + internal abstract string KeyDictionaryItemSeparator { get; } + internal abstract string SystemNullableStructureTemplate { get; } + internal abstract string ICollectionOfTStructureTemplate { get; } + internal abstract string DataServiceCollectionStructureTemplate { get; } + internal abstract string DataServiceQueryStructureTemplate { get; } + internal abstract string DataServiceQuerySingleStructureTemplate { get; } + internal abstract string ObservableCollectionStructureTemplate { get; } + internal abstract string ObjectModelCollectionStructureTemplate { get; } + internal abstract string DataServiceCollectionConstructorParameters { get; } + internal abstract string NewModifier { get; } + internal abstract string GeoTypeInitializePattern { get; } + internal abstract string Int32TypeName { get; } + internal abstract string ObjectTypeName { get; } + internal abstract string StringTypeName { get; } + internal abstract string BinaryTypeName { get; } + internal abstract string DecimalTypeName { get; } + internal abstract string Int16TypeName { get; } + internal abstract string SingleTypeName { get; } + internal abstract string BooleanTypeName { get; } + internal abstract string DoubleTypeName { get; } + internal abstract string GuidTypeName { get; } + internal abstract string ByteTypeName { get; } + internal abstract string Int64TypeName { get; } + internal abstract string SByteTypeName { get; } + internal abstract string DataServiceStreamLinkTypeName { get; } + internal abstract string GeographyTypeName { get; } + internal abstract string GeographyPointTypeName { get; } + internal abstract string GeographyLineStringTypeName { get; } + internal abstract string GeographyPolygonTypeName { get; } + internal abstract string GeographyCollectionTypeName { get; } + internal abstract string GeographyMultiPolygonTypeName { get; } + internal abstract string GeographyMultiLineStringTypeName { get; } + internal abstract string GeographyMultiPointTypeName { get; } + internal abstract string GeometryTypeName { get; } + internal abstract string GeometryPointTypeName { get; } + internal abstract string GeometryLineStringTypeName { get; } + internal abstract string GeometryPolygonTypeName { get; } + internal abstract string GeometryCollectionTypeName { get; } + internal abstract string GeometryMultiPolygonTypeName { get; } + internal abstract string GeometryMultiLineStringTypeName { get; } + internal abstract string GeometryMultiPointTypeName { get; } + internal abstract string DateTypeName { get; } + internal abstract string DateTimeOffsetTypeName { get; } + internal abstract string DurationTypeName { get; } + internal abstract string TimeOfDayTypeName { get; } + internal abstract string XmlConvertClassName { get; } + internal abstract string EnumTypeName { get; } + internal abstract string DictionaryTypeName { get; } + internal abstract HashSet LanguageKeywords { get; } + internal abstract string FixPattern { get; } + internal abstract string EnumUnderlyingTypeMarker { get; } + internal abstract string ConstantExpressionConstructorWithType { get; } + internal abstract string TypeofFormatter { get; } + internal abstract string UriOperationParameterConstructor { get; } + internal abstract string UriEntityOperationParameterConstructor { get; } + internal abstract string BodyOperationParameterConstructor { get; } + internal abstract string DictionaryConstructor { get; } + internal abstract string BaseEntityType { get; } + internal abstract string OverloadsModifier { get; } + internal abstract string ODataVersion { get; } + internal abstract string ParameterDeclarationTemplate { get; } + internal abstract string DictionaryItemConstructor { get; } + #endregion Get Language specific keyword names. + + #region Language specific write methods. + internal abstract void WriteFileHeader(); + internal abstract void WriteNamespaceStart(string fullNamespace); + internal abstract void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName); + internal abstract void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName); + internal abstract void WriteKeyAsSegmentUrlConvention(); + internal abstract void WriteInitializeResolveName(); + internal abstract void WriteInitializeResolveType(); + internal abstract void WriteClassEndForEntityContainerConstructor(); + internal abstract void WriteMethodStartForResolveTypeFromName(); + internal abstract void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace); + internal abstract void WriteMethodEndForResolveTypeFromName(); + internal abstract void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace); + internal abstract void WriteResolveType(string fullNamespace, string languageDependentNamespace); + internal abstract void WriteMethodEndForResolveNameFromType(bool modelHasInheritance); + internal abstract void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext = true); + internal abstract void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext = true); + internal abstract void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName); + internal abstract void WriteGeneratedEdmModel(string escapedEdmxString); + internal abstract void WriteClassEndForEntityContainer(); + internal abstract void WriteSummaryCommentForStructuredType(string typeName); + internal abstract void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString); + internal abstract void WriteEntityTypeAttribute(); + internal abstract void WriteEntitySetAttribute(string entitySetName); + internal abstract void WriteEntityHasStreamAttribute(); + internal abstract void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName); + internal abstract void WriteSummaryCommentForStaticCreateMethod(string typeName); + internal abstract void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName); + internal abstract void WriteDeclarationStartForStaticCreateMethod(string typeName,string fixedTypeName ); + internal abstract void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater); + internal abstract void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName); + internal abstract void WriteParameterNullCheckForStaticCreateMethod(string parameterName); + internal abstract void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName); + internal abstract void WriteMethodEndForStaticCreateMethod(string instanceName); + internal abstract void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged); + internal abstract void WriteINotifyPropertyChangedImplementation(); + internal abstract void WriteClassEndForStructuredType(); + internal abstract void WriteNamespaceEnd(); + internal abstract void WriteEnumFlags(); + internal abstract void WriteSummaryCommentForEnumType(string enumName); + internal abstract void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType); + internal abstract void WriteMemberForEnumType(string member, string originalMemberName, bool last); + internal abstract void WriteEnumEnd(); + internal abstract void WritePropertyRootNamespace(string containerName, string fullNamespace); + internal abstract void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues); + internal abstract void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues); + internal abstract void WriteConstructorForSingleType(string singleTypeName, string baseTypeName); + internal abstract void WriteExtensionMethodsStart(); + internal abstract void WriteExtensionMethodsEnd(); + internal abstract void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems); + internal abstract void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName); + internal abstract void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference); + internal abstract void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference); + internal abstract void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues); + #endregion Language specific write methods. + + internal HashSet ClrReferenceTypes { get { + if (clrReferenceTypes == null) + { + clrReferenceTypes = new HashSet() + { + EdmPrimitiveTypeKind.String, EdmPrimitiveTypeKind.Binary, EdmPrimitiveTypeKind.Geography, EdmPrimitiveTypeKind.Stream, + EdmPrimitiveTypeKind.GeographyPoint, EdmPrimitiveTypeKind.GeographyLineString, EdmPrimitiveTypeKind.GeographyPolygon, + EdmPrimitiveTypeKind.GeographyCollection, EdmPrimitiveTypeKind.GeographyMultiPolygon, EdmPrimitiveTypeKind.GeographyMultiLineString, + EdmPrimitiveTypeKind.GeographyMultiPoint, EdmPrimitiveTypeKind.Geometry, EdmPrimitiveTypeKind.GeometryPoint, + EdmPrimitiveTypeKind.GeometryLineString, EdmPrimitiveTypeKind.GeometryPolygon, EdmPrimitiveTypeKind.GeometryCollection, + EdmPrimitiveTypeKind.GeometryMultiPolygon, EdmPrimitiveTypeKind.GeometryMultiLineString, EdmPrimitiveTypeKind.GeometryMultiPoint + }; + } + return clrReferenceTypes; + } } + private HashSet clrReferenceTypes; + + /// + /// Generates code for the OData client. + /// + /// The generated code for the OData client. + public override string TransformText() + { + this.WriteFileHeader(); + this.WriteNamespaces(); + return this.GenerationEnvironment.ToString(); + } + + internal void WriteNamespaces() + { + foreach(string fullNamespace in context.NamespacesInModel) + { + this.WriteNamespace(fullNamespace); + } + } + + internal void WriteNamespace(string fullNamespace) + { + this.WriteNamespaceStart(this.context.GetPrefixedNamespace(fullNamespace, this, true, false)); + + IEdmSchemaElement[] schemaElements = this.context.GetSchemaElements(fullNamespace).ToArray(); + if (schemaElements.OfType().Any()) { + IEdmEntityContainer container = schemaElements.OfType().Single(); + this.WriteEntityContainer(container, fullNamespace); + } + + Dictionary> boundOperationsMap = new Dictionary>(); + foreach (IEdmOperation operation in schemaElements.OfType()) + { + if (operation.IsBound) + { + IEdmType edmType = operation.Parameters.First().Type.Definition; + IEdmStructuredType edmStructuredType = edmType as IEdmStructuredType; + if (edmStructuredType != null) + { + List operationList; + if (!boundOperationsMap.TryGetValue(edmStructuredType, out operationList)) + { + operationList = new List(); + } + + operationList.Add(operation); + boundOperationsMap[edmStructuredType] = operationList; + } + } + } + + Dictionary> structuredBaseTypeMap = new Dictionary>(); + foreach(IEdmSchemaType type in schemaElements.OfType()) + { + IEdmEnumType enumType = type as IEdmEnumType; + if (enumType != null) + { + this.WriteEnumType(enumType); + } + else + { + IEdmComplexType complexType = type as IEdmComplexType; + if (complexType != null) + { + this.WriteComplexType(complexType, boundOperationsMap); + } + else + { + IEdmEntityType entityType = type as IEdmEntityType; + this.WriteEntityType(entityType, boundOperationsMap); + } + + IEdmStructuredType structuredType = type as IEdmStructuredType; + if (structuredType.BaseType != null) + { + List derivedTypes; + if (!structuredBaseTypeMap.TryGetValue(structuredType.BaseType, out derivedTypes)) + { + structuredBaseTypeMap[structuredType.BaseType] = new List(); + } + + structuredBaseTypeMap[structuredType.BaseType].Add(structuredType); + } + } + } + + if (schemaElements.OfType().Any() || + schemaElements.OfType().Any(o => o.IsBound)) + { + this.WriteExtensionMethodsStart(); + foreach (IEdmEntityType type in schemaElements.OfType()) + { + string entityTypeName = type.Name; + entityTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; + string entityTypeFullName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName), this); + string returnTypeName = context.GetPrefixedFullName(type, GetFixedName(entityTypeName + this.SingleSuffix), this); + + var keyProperties = type.Key(); + if(keyProperties != null && keyProperties.Any()) + { + List keyParameters = new List(); + List keyDictionaryItems = new List(); + List keyNames = new List(); + foreach (IEdmProperty key in keyProperties) + { + string typeName = Utils.GetClrTypeName(key.Type, this.context.UseDataServiceCollection, this, this.context); + string keyName = Utils.CamelCase(key.Name); + keyNames.Add(keyName); + keyParameters.Add(string.Format(this.ParameterDeclarationTemplate, typeName, this.GetFixedName(keyName))); + keyDictionaryItems.Add(string.Format(this.DictionaryItemConstructor, "\"" + key.Name + "\"", this.GetFixedName(keyName))); + } + + string keyParametersString = string.Join(this.KeyParameterSeparator, keyParameters); + string keyDictionaryItemsString = string.Join(this.KeyDictionaryItemSeparator, keyDictionaryItems); + this.WriteByKeyMethods(entityTypeFullName, returnTypeName, keyNames, keyParametersString, keyDictionaryItemsString); + } + + IEdmEntityType current = (IEdmEntityType)type.BaseType; + while (current != null) + { + string baseTypeName = current.Name; + baseTypeName = context.EnableNamingAlias ? Customization.CustomizeNaming(baseTypeName) : baseTypeName; + baseTypeName = context.GetPrefixedFullName(current, GetFixedName(baseTypeName), this); + this.WriteCastToMethods(baseTypeName, entityTypeName, entityTypeFullName, returnTypeName); + current = (IEdmEntityType)current.BaseType; + } + } + + HashSet boundOperations = new HashSet(StringComparer.Ordinal); + foreach (IEdmFunction function in schemaElements.OfType()) + { + if (function.IsBound) + { + IEdmTypeReference edmTypeReference = function.Parameters.First().Type; + string functionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(function.Name) : function.Name; + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); + string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); + string fixedFunctionName = GetFixedName(functionName); + string func = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); + + if (!boundOperations.Contains(func)) + { + boundOperations.Add(func); + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + + IEdmStructuredType structuredType; + if (edmTypeReference.IsCollection()) + { + IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; + structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; + } + else + { + structuredType = (IEdmStructuredType)edmTypeReference.Definition; + } + + List derivedTypes; + if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) + { + foreach (IEdmStructuredType type in derivedTypes) + { + IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); + List currentParameters = function.Parameters.Select(p => p.Type).ToList(); + currentParameters[0] = derivedTypeReference; + + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); + string currentFunc = string.Format("{0}({1},{2})", fixedFunctionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(currentFunc)) + { + boundOperations.Add(currentFunc); + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionReturnCollectionResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionReturnSingleResultAsExtension(fixedFunctionName, function.Name, sourceTypeName, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + } + } + } + } + + foreach (IEdmAction action in schemaElements.OfType()) + { + if (action.IsBound) + { + IEdmTypeReference edmTypeReference = action.Parameters.First().Type; + string actionName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(action.Name) : action.Name; + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string sourceTypeName = GetSourceOrReturnTypeName(edmTypeReference); + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, sourceTypeName); + string returnTypeName; + if (action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); + if (action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string fixedActionName = GetFixedName(actionName); + string ac = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(ac)) + { + boundOperations.Add(ac); + this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); + } + + IEdmStructuredType structuredType; + if (edmTypeReference.IsCollection()) + { + IEdmCollectionType collectionType = edmTypeReference.Definition as IEdmCollectionType; + structuredType = (IEdmStructuredType)collectionType.ElementType.Definition; + } + else + { + structuredType = (IEdmStructuredType)edmTypeReference.Definition; + } + + List derivedTypes; + if (structuredBaseTypeMap.TryGetValue(structuredType, out derivedTypes)) + { + foreach (IEdmStructuredType type in derivedTypes) + { + IEdmTypeReference derivedTypeReference = new EdmEntityTypeReference((IEdmEntityType)type, true); + List currentParameters = action.Parameters.Select(p => p.Type).ToList(); + currentParameters[0] = derivedTypeReference; + + sourceTypeName = string.Format(edmTypeReference.IsCollection() ? this.DataServiceQueryStructureTemplate : this.DataServiceQuerySingleStructureTemplate, GetSourceOrReturnTypeName(derivedTypeReference)); + string currentAc = string.Format("{0}({1},{2})", fixedActionName, sourceTypeName, parameterTypes ); + if (!boundOperations.Contains(currentAc)) + { + boundOperations.Add(currentAc); + this.WriteBoundActionAsExtension(fixedActionName, action.Name, sourceTypeName, returnTypeName, parameterString, action.Namespace, parameterValues); + } + } + } + } + } + + this.WriteExtensionMethodsEnd(); + } + + this.WriteNamespaceEnd(); + } + + internal bool HasBoundOperations(IEnumerable operations) + { + foreach (IEdmOperation opeartion in operations) + { + if (opeartion.IsBound) + { + return true; + } + } + + return false; + } + + internal void WriteEntityContainer(IEdmEntityContainer container, string fullNamespace) + { + string camelCaseContainerName = container.Name; + if (this.context.EnableNamingAlias) + { + camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); + } + + this.WriteClassStartForEntityContainer(container.Name, camelCaseContainerName, GetFixedName(camelCaseContainerName)); + this.WriteEntityContainerConstructor(container); + + if (this.context.NeedResolveNameFromType) + { + this.WritePropertyRootNamespace(GetFixedName(camelCaseContainerName), this.context.GetPrefixedNamespace(fullNamespace, this, false, false)); + } + + this.WriteResolveTypeFromName(); + this.WriteResolveNameFromType(camelCaseContainerName, fullNamespace); + + foreach (IEdmEntitySet entitySet in container.EntitySets()) + { + IEdmEntityType entitySetElementType = entitySet.EntityType(); + string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); + + string camelCaseEntitySetName = entitySet.Name; + if (this.context.EnableNamingAlias) + { + camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); + } + + this.WriteContextEntitySetProperty(camelCaseEntitySetName, GetFixedName(camelCaseEntitySetName), entitySet.Name, GetFixedName(entitySetElementTypeName)); + List edmNavigationSourceList = null; + if (!this.context.ElementTypeToNavigationSourceMap.TryGetValue(entitySet.EntityType(), out edmNavigationSourceList)) + { + edmNavigationSourceList = new List(); + this.context.ElementTypeToNavigationSourceMap.Add(entitySet.EntityType(), edmNavigationSourceList); + } + + edmNavigationSourceList.Add(entitySet); + } + + foreach (IEdmEntitySet entitySet in container.EntitySets()) + { + IEdmEntityType entitySetElementType = entitySet.EntityType(); + + string entitySetElementTypeName = GetElementTypeName(entitySetElementType, container); + + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(/*IsLanguageCaseSensitive*/true); + string parameterName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(entitySetElementType.Name)); + + string camelCaseEntitySetName = entitySet.Name; + if (this.context.EnableNamingAlias) + { + camelCaseEntitySetName = Customization.CustomizeNaming(camelCaseEntitySetName); + } + + this.WriteContextAddToEntitySetMethod(camelCaseEntitySetName, entitySet.Name, GetFixedName(entitySetElementTypeName), parameterName); + } + + foreach (IEdmSingleton singleton in container.Singletons()) + { + IEdmEntityType singletonElementType = singleton.EntityType(); + string singletonElementTypeName = GetElementTypeName(singletonElementType, container); + string camelCaseSingletonName = singleton.Name; + if (this.context.EnableNamingAlias) + { + camelCaseSingletonName = Customization.CustomizeNaming(camelCaseSingletonName); + } + + this.WriteContextSingletonProperty(camelCaseSingletonName, GetFixedName(camelCaseSingletonName), singleton.Name, singletonElementTypeName + "Single"); + + List edmNavigationSourceList = null; + if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(singleton.EntityType(), out edmNavigationSourceList)) + { + edmNavigationSourceList.Add(singleton); + } + } + + this.WriteGeneratedEdmModel(Utils.SerializeToString(this.context.Edmx).Replace("\"", "\"\"")); + + bool hasOperationImport = container.OperationImports().OfType().Any(); + foreach (IEdmFunctionImport functionImport in container.OperationImports().OfType()) + { + string parameterString, parameterTypes, parameterExpressionString, parameterValues; + bool useEntityReference; + this.GetParameterStrings(false, false, functionImport.Function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = GetSourceOrReturnTypeName(functionImport.Function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(functionImport.Function.ReturnType, true); + string fixedContainerName = this.GetFixedName(functionImport.Container.Name); + bool isCollectionResult = functionImport.Function.ReturnType.IsCollection(); + string functionImportName = functionImport.Name; + if (this.context.EnableNamingAlias) + { + functionImportName = Customization.CustomizeNaming(functionImportName); + fixedContainerName = Customization.CustomizeNaming(fixedContainerName); + } + + if (functionImport.Function.ReturnType.IsCollection()) + { + this.WriteFunctionImportReturnCollectionResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, parameterString, parameterValues, functionImport.Function.IsComposable, useEntityReference); + } + else + { + this.WriteFunctionImportReturnSingleResult(this.GetFixedName(functionImportName), functionImport.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, parameterValues, functionImport.Function.IsComposable, functionImport.Function.ReturnType.IsEntity(), useEntityReference); + } + } + + foreach (IEdmActionImport actionImport in container.OperationImports().OfType()) + { + string parameterString, parameterTypes, parameterExpressionString, parameterValues; + bool useEntityReference; + this.GetParameterStrings(false, true, actionImport.Action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = null; + string fixedContainerName = this.GetFixedName(actionImport.Container.Name); + + if (actionImport.Action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(actionImport.Action.ReturnType); + if (actionImport.Action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string actionImportName = actionImport.Name; + if (this.context.EnableNamingAlias) + { + actionImportName = Customization.CustomizeNaming(actionImportName); + fixedContainerName = Customization.CustomizeNaming(fixedContainerName); + } + + this.WriteActionImport(this.GetFixedName(actionImportName), actionImport.Name, returnTypeName, parameterString, parameterValues); + } + + this.WriteClassEndForEntityContainer(); + } + + internal void WriteEntityContainerConstructor(IEdmEntityContainer container) + { + string camelCaseContainerName = container.Name; + if (this.context.EnableNamingAlias) + { + camelCaseContainerName = Customization.CustomizeNaming(camelCaseContainerName); + } + + this.WriteMethodStartForEntityContainerConstructor(camelCaseContainerName, GetFixedName(camelCaseContainerName)); + + if (this.context.UseKeyAsSegmentUrlConvention(container)) + { + this.WriteKeyAsSegmentUrlConvention(); + } + + if (this.context.NeedResolveNameFromType) + { + this.WriteInitializeResolveName(); + } + + if (this.context.NeedResolveTypeFromName) + { + this.WriteInitializeResolveType(); + } + + this.WriteClassEndForEntityContainerConstructor(); + } + + internal void WriteResolveTypeFromName() + { + if (!this.context.NeedResolveTypeFromName) + { + return; + } + + this.WriteMethodStartForResolveTypeFromName(); + + // NOTE: since multiple namespaces can have the same prefix and match the namespace + // prefix condition, it's important that the prefix check is done is prefix-length + // order, starting with the longest prefix. + IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Key.Length).ThenBy(p => p.Key); + + string typeName = this.SystemTypeTypeName + " "; + foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) + { + this.WriteResolveNamespace(typeName, namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); + typeName = string.Empty; + } + + this.WriteMethodEndForResolveTypeFromName(); + } + + internal void WriteResolveNameFromType(string containerName, string fullNamespace) + { + if (!this.context.NeedResolveNameFromType) + { + return; + } + + this.WriteMethodStartForResolveNameFromType(GetFixedName(containerName), fullNamespace); + + // NOTE: in this case order also matters, but the length of the CLR + // namespace is what needs to be considered. + IEnumerable> namespaceToPrefixedNamespacePairs = this.context.NamespaceMap.OrderByDescending(p => p.Value.Length).ThenBy(p => p.Key); + + foreach(KeyValuePair namespaceToPrefixedNamespacePair in namespaceToPrefixedNamespacePairs) + { + this.WriteResolveType(namespaceToPrefixedNamespacePair.Key, namespaceToPrefixedNamespacePair.Value); + } + + this.WriteMethodEndForResolveNameFromType(this.context.ModelHasInheritance); + } + + internal void WritePropertiesForSingleType(IEnumerable properties) + { + foreach (IEdmProperty property in properties.Where(i => i.PropertyKind == EdmPropertyKind.Navigation)) + { + string propertyType; + string propertyName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name; + if (property.Type is Microsoft.OData.Edm.EdmCollectionTypeReference) + { + propertyType = GetSourceOrReturnTypeName(property.Type); + WriteContextEntitySetProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); + } + else + { + propertyType = Utils.GetClrTypeName(property.Type, true, this, this.context, true, isEntitySingleType : true); + WriteContextSingletonProperty(propertyName, GetFixedName(propertyName), property.Name, propertyType, false); + } + } + } + + internal void WriteEntityType(IEdmEntityType entityType, Dictionary> boundOperationsMap) + { + string entityTypeName = ((IEdmSchemaElement)entityType).Name; + entityTypeName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityTypeName) : entityTypeName; + this.WriteSummaryCommentForStructuredType(entityTypeName + this.SingleSuffix); + this.WriteStructurdTypeDeclaration(entityType, + this.ClassInheritMarker + string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName)), + this.SingleSuffix); + string singleTypeName = (this.context.EnableNamingAlias ? + Customization.CustomizeNaming(((IEdmSchemaElement)entityType).Name) : ((IEdmSchemaElement)entityType).Name) + this.SingleSuffix; + this.WriteConstructorForSingleType(GetFixedName(singleTypeName), string.Format(this.DataServiceQuerySingleStructureTemplate, GetFixedName(entityTypeName))); + IEdmEntityType current = entityType; + while (current != null) + { + this.WritePropertiesForSingleType(current.DeclaredProperties); + current = (IEdmEntityType)current.BaseType; + } + + this.WriteClassEndForStructuredType(); + + this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(entityType.Name) : entityType.Name); + + if (entityType.Key().Any()) + { + IEnumerable keyProperties = entityType.Key().Select(k => k.Name); + this.WriteKeyPropertiesCommentAndAttribute( + this.context.EnableNamingAlias ? keyProperties.Select(k => Customization.CustomizeNaming(k)) : keyProperties, + string.Join("\", \"", keyProperties)); + } + else + { + this.WriteEntityTypeAttribute(); + } + + if (this.context.UseDataServiceCollection) + { + List navigationSourceList; + if (this.context.ElementTypeToNavigationSourceMap.TryGetValue(entityType, out navigationSourceList)) + { + if(navigationSourceList.Count == 1) + { + this.WriteEntitySetAttribute(navigationSourceList[0].Name); + } + } + } + + if (entityType.HasStream) + { + this.WriteEntityHasStreamAttribute(); + } + + this.WriteStructurdTypeDeclaration(entityType, this.BaseEntityType); + this.SetPropertyIdentifierMappingsIfNameConflicts(entityType.Name, entityType); + this.WriteTypeStaticCreateMethod(entityType.Name, entityType); + this.WritePropertiesForStructuredType(entityType.DeclaredProperties, entityType.IsOpen); + + if (entityType.BaseType == null && this.context.UseDataServiceCollection) + { + this.WriteINotifyPropertyChangedImplementation(); + } + + this.WriteBoundOperations(entityType, boundOperationsMap); + + this.WriteClassEndForStructuredType(); + } + + internal void WriteComplexType(IEdmComplexType complexType, Dictionary> boundOperationsMap) + { + this.WriteSummaryCommentForStructuredType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(complexType.Name) : complexType.Name); + this.WriteStructurdTypeDeclaration(complexType, string.Empty); + this.SetPropertyIdentifierMappingsIfNameConflicts(complexType.Name, complexType); + this.WriteTypeStaticCreateMethod(complexType.Name, complexType); + this.WritePropertiesForStructuredType(complexType.DeclaredProperties, complexType.IsOpen); + + if (complexType.BaseType == null && this.context.UseDataServiceCollection) + { + this.WriteINotifyPropertyChangedImplementation(); + } + + this.WriteClassEndForStructuredType(); + } + + internal void WriteBoundOperations(IEdmStructuredType structuredType, Dictionary> boundOperationsMap) + { + List operations; + if (boundOperationsMap.TryGetValue(structuredType, out operations)) + { + foreach (IEdmFunction function in operations.OfType()) + { + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, function, boundOperationsMap); + this.GetParameterStrings(function.IsBound, false, function.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName = GetSourceOrReturnTypeName(function.ReturnType); + string returnTypeNameWithSingleSuffix = GetSourceOrReturnTypeName(function.ReturnType, true); + string functionName = function.Name; + if (this.context.EnableNamingAlias) + { + functionName = Customization.CustomizeNaming(functionName); + } + + if (function.ReturnType.IsCollection()) + { + this.WriteBoundFunctionInEntityTypeReturnCollectionResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, parameterString, function.Namespace, parameterValues, function.IsComposable, useEntityReference); + } + else + { + this.WriteBoundFunctionInEntityTypeReturnSingleResult(hideBaseMethod, GetFixedName(functionName), function.Name, returnTypeName, returnTypeNameWithSingleSuffix, parameterString, function.Namespace, parameterValues, function.IsComposable, function.ReturnType.IsEntity(), useEntityReference); + } + } + + foreach (IEdmAction action in operations.OfType()) + { + string parameterString, parameterExpressionString, parameterTypes, parameterValues; + bool useEntityReference; + bool hideBaseMethod = this.CheckMethodsInBaseClass(structuredType.BaseType, action, boundOperationsMap); + this.GetParameterStrings(action.IsBound, true, action.Parameters.ToArray(), out parameterString, out parameterTypes, out parameterExpressionString, out parameterValues, out useEntityReference); + string returnTypeName; + if (action.ReturnType != null) + { + returnTypeName = GetSourceOrReturnTypeName(action.ReturnType); + if (action.ReturnType.IsCollection()) + { + returnTypeName = string.Format(this.DataServiceActionQueryOfTStructureTemplate, returnTypeName); + } + else + { + returnTypeName = string.Format(this.DataServiceActionQuerySingleOfTStructureTemplate, returnTypeName); + } + } + else + { + returnTypeName = this.DataServiceActionQueryTypeName; + } + + string actionName = action.Name; + if (this.context.EnableNamingAlias) + { + actionName = Customization.CustomizeNaming(actionName); + } + + this.WriteBoundActionInEntityType(hideBaseMethod, GetFixedName(actionName), action.Name, returnTypeName, parameterString, action.Namespace, parameterValues); + } + } + } + + internal bool CheckMethodsInBaseClass(IEdmStructuredType structuredType, IEdmOperation operation, Dictionary> boundOperationsMap) + { + if (structuredType != null) + { + List operations; + if (boundOperationsMap.TryGetValue(structuredType, out operations)) + { + foreach (IEdmOperation op in operations) + { + if (this.context.TargetLanguage == LanguageOption.VB) + { + if (operation.Name == op.Name) + { + return true; + } + } + + List targetParameter = operation.Parameters.ToList(); + List checkParameter = op.Parameters.ToList(); + if (operation.Name == op.Name && targetParameter.Count == checkParameter.Count) + { + bool areSame = true; + for (int i = 1; i < targetParameter.Count; ++i) + { + var targetParameterType = targetParameter[i].Type; + var checkParameterType = checkParameter[i].Type; + if (!targetParameterType.Definition.Equals(checkParameterType.Definition) + || targetParameterType.IsNullable != checkParameterType.IsNullable) + { + areSame = false; + break; + } + } + + if (areSame) + { + return true; + } + } + } + } + + return CheckMethodsInBaseClass(structuredType.BaseType, operation, boundOperationsMap); + } + + return false; + } + + internal void WriteEnumType(IEdmEnumType enumType) + { + this.WriteSummaryCommentForEnumType(this.context.EnableNamingAlias ? Customization.CustomizeNaming(enumType.Name) : enumType.Name); + if (enumType.IsFlags) + { + this.WriteEnumFlags(); + } + + string underlyingType = string.Empty; + if (enumType.UnderlyingType != null && enumType.UnderlyingType.PrimitiveKind != EdmPrimitiveTypeKind.Int32) + { + underlyingType = Utils.GetClrTypeName(enumType.UnderlyingType, this); + underlyingType = this.EnumUnderlyingTypeMarker + underlyingType; + } + + this.WriteEnumDeclaration(this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(enumType.Name)) : GetFixedName(enumType.Name), enumType.Name, underlyingType); + this.WriteMembersForEnumType(enumType.Members); + this.WriteEnumEnd(); + } + + internal void WriteStructurdTypeDeclaration(IEdmStructuredType structuredType, string baseEntityType, string typeNameSuffix = null) + { + string abstractModifier = structuredType.IsAbstract && typeNameSuffix == null ? this.AbstractModifier : string.Empty; + string baseTypeName = baseEntityType; + + if (typeNameSuffix == null) + { + if (structuredType.BaseType == null) + { + if (this.context.UseDataServiceCollection) + { + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + baseTypeName += string.IsNullOrEmpty(baseTypeName) ? this.ClassInheritMarker : ", "; + } + + baseTypeName += this.NotifyPropertyChangedModifier; + } + } + else + { + IEdmSchemaElement baseType = (IEdmSchemaElement)structuredType.BaseType; + string baseTypeFixedName = this.context.EnableNamingAlias ? GetFixedName(Customization.CustomizeNaming(baseType.Name)) : GetFixedName(baseType.Name); + baseTypeName = ((IEdmSchemaElement)structuredType).Namespace == baseType.Namespace ? baseTypeFixedName : this.context.GetPrefixedFullName(baseType, baseTypeFixedName, this); + baseTypeName = this.ClassInheritMarker + baseTypeName; + } + } + + string structuredTypeName = this.context.EnableNamingAlias ? + Customization.CustomizeNaming(((IEdmSchemaElement)structuredType).Name) : ((IEdmSchemaElement)structuredType).Name; + this.WriteClassStartForStructuredType(abstractModifier, GetFixedName(structuredTypeName + typeNameSuffix), ((IEdmSchemaElement)structuredType).Name + typeNameSuffix, baseTypeName); + } + + internal string GetSourceOrReturnTypeName(IEdmTypeReference typeReference, bool isEntitySingleType = false) + { + IEdmCollectionType edmCollectionType = typeReference.Definition as IEdmCollectionType; + bool addNullableTemplate = true; + if (edmCollectionType != null) + { + typeReference = edmCollectionType.ElementType; + addNullableTemplate = false; + } + + return Utils.GetClrTypeName(typeReference, this.context.UseDataServiceCollection, this, this.context, addNullableTemplate, isEntitySingleType:isEntitySingleType); + } + + internal void GetParameterStrings(bool isBound, bool isAction, IEdmOperationParameter[] parameters, out string parameterString, out string parameterTypes, out string parameterExpressionString, out string parameterValues, out bool useEntityReference) + { + parameterString = string.Empty; + parameterExpressionString = string.Empty; + parameterTypes = string.Empty; + parameterValues = string.Empty; + useEntityReference = false; + + int n = parameters.Count(); + for (int i = isBound ? 1 : 0; i < n; ++i) + { + IEdmOperationParameter param = parameters[i]; + if (i == (isBound ? 1 : 0)) + { + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + parameterExpressionString += "\r\n "; + } + else + { + parameterExpressionString += "\r\n "; + } + } + + string typeName = Utils.GetClrTypeName(param.Type, this.context.UseDataServiceCollection, this, this.context, true, true, true); + if (this.context.TargetLanguage == LanguageOption.CSharp) + { + parameterString += typeName; + parameterString += (" " + GetFixedName(param.Name)); + } + else if (this.context.TargetLanguage == LanguageOption.VB) + { + parameterString += GetFixedName(param.Name); + parameterString += (this.EnumUnderlyingTypeMarker + typeName); + } + + parameterString += i == n - 1 ? string.Empty : ", "; + parameterTypes += string.Format(this.TypeofFormatter, typeName) + ", "; + parameterExpressionString += this.GetParameterExpressionString(param, typeName) + ", "; + + if (i != (isBound ? 1 : 0)) + { + parameterValues += ",\r\n "; + } + + if (isAction) + { + parameterValues += string.Format(this.BodyOperationParameterConstructor, param.Name, GetFixedName(param.Name)); + } + else if (param.Type.IsEntity() || (param.Type.IsCollection() && param.Type.AsCollection().ElementType().IsEntity())) + { + useEntityReference = true; + parameterValues += string.Format(this.UriEntityOperationParameterConstructor, param.Name, GetFixedName(param.Name),"useEntityReference"); + } + else + { + parameterValues += string.Format(this.UriOperationParameterConstructor, param.Name, GetFixedName(param.Name)); + } + } + } + + internal string GetParameterExpressionString(IEdmOperationParameter param, string typeName) + { + string clrTypeName; + IEdmType edmType = param.Type.Definition; + IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; + if (edmPrimitiveType != null) + { + clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, this); + if (param.Type.IsNullable && !this.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind)) + { + clrTypeName += "?"; + } + + return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), clrTypeName); + } + + return string.Format(this.ConstantExpressionConstructorWithType, GetFixedName(param.Name), typeName); + } + + // This is to solve duplicate names between property and type + internal void SetPropertyIdentifierMappingsIfNameConflicts(string typeName, IEdmStructuredType structuredType) + { + if (this.context.EnableNamingAlias) + { + typeName = Customization.CustomizeNaming(typeName); + } + + // PropertyName in VB is case-insensitive. + bool isLanguageCaseSensitive = this.context.TargetLanguage == LanguageOption.CSharp; + + // In VB, it is allowed that a type has a property whose name is same with the type's name + bool allowPropertyNameSameWithTypeName = this.context.TargetLanguage == LanguageOption.VB; + + Func customizePropertyName = (name) => { return this.context.EnableNamingAlias ? Customization.CustomizeNaming(name) : name; }; + + var propertyGroups = structuredType.Properties() + .GroupBy(p => isLanguageCaseSensitive ? customizePropertyName(p.Name) : customizePropertyName(p.Name).ToUpperInvariant()); + + // If the group contains more than one property, or the property in the group has the same name with the type (only for C#), we need to rename the property + var propertyToBeRenamedGroups = propertyGroups.Where(g => g.Count() > 1 || !allowPropertyNameSameWithTypeName && g.Key == typeName); + + var knownIdentifiers = propertyGroups.Select(g => customizePropertyName(g.First().Name)).ToList(); + if(!allowPropertyNameSameWithTypeName && !knownIdentifiers.Contains(typeName)) + { + knownIdentifiers.Add(typeName); + } + UniqueIdentifierService uniqueIdentifierService = + new UniqueIdentifierService(knownIdentifiers, isLanguageCaseSensitive); + + IdentifierMappings.Clear(); + foreach (IGrouping g in propertyToBeRenamedGroups) + { + bool hasPropertyNameSameWithCustomizedPropertyName = false; + int itemCount = g.Count(); + for (int i = 0; i < itemCount; i++) + { + var property = g.ElementAt(i); + var customizedPropertyName = customizePropertyName(property.Name); + + if(this.context.EnableNamingAlias && customizedPropertyName == property.Name) + { + hasPropertyNameSameWithCustomizedPropertyName = true; + } + + if(isLanguageCaseSensitive) + { + // If a property name is same as its customized property name, then we don't rename it. + // Or we don't rename the last property in the group + if(customizedPropertyName != typeName + && (customizedPropertyName == property.Name + || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1))) + { + continue; + } + } + else + { + // When EnableNamingAlias = true, If a property name is same as its customized property name, then we don't rename it. + // Or we don't rename the last property in the group. + if((this.context.EnableNamingAlias && customizedPropertyName == property.Name) + || (!hasPropertyNameSameWithCustomizedPropertyName && i == itemCount-1)) + { + continue; + } + } + var renamedPropertyName = uniqueIdentifierService.GetUniqueIdentifier(customizedPropertyName); + IdentifierMappings.Add(property.Name, renamedPropertyName); + } + } + } + + internal void WriteTypeStaticCreateMethod(string typeName, IEdmStructuredType structuredType) + { + Debug.Assert(structuredType != null, "structuredType != null"); + if (structuredType.IsAbstract) + { + return; + } + + Func hasDefault = p => p.PropertyKind == EdmPropertyKind.Structural && ((IEdmStructuralProperty)p).DefaultValueString != null; + + if (this.context.EnableNamingAlias) + { + typeName = Customization.CustomizeNaming(typeName); + } + + IEnumerable parameters = structuredType.Properties() + .Where(p => !p.Type.IsNullable && !p.Type.IsCollection() && !hasDefault(p)); + if (!parameters.Any()) + { + return; + } + + this.WriteSummaryCommentForStaticCreateMethod(typeName); + + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService( /*IsLanguageCaseSensitive*/true); + string instanceName = GetFixedName(uniqueIdentifierService.GetUniqueParameterName(typeName)); + KeyValuePair[] propertyToParameterNamePairs = parameters + .Select(p => + new KeyValuePair(p, + uniqueIdentifierService.GetUniqueParameterName( + IdentifierMappings.ContainsKey(p.Name) ? IdentifierMappings[p.Name] : p.Name))) + .ToArray(); + + foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) + { + string propertyName = propertyToParameterNamePair.Key.Name; + propertyName = IdentifierMappings.ContainsKey(propertyName) ? + IdentifierMappings[propertyName] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(propertyName) : propertyName); + this.WriteParameterCommentForStaticCreateMethod(propertyToParameterNamePair.Value, propertyName); + } + + propertyToParameterNamePairs = propertyToParameterNamePairs + .Select(p => p = new KeyValuePair(p.Key, GetFixedName(p.Value))) + .ToArray(); + + this.WriteDeclarationStartForStaticCreateMethod(typeName, GetFixedName(typeName)); + this.WriteStaticCreateMethodParameters(propertyToParameterNamePairs); + this.WriteDeclarationEndForStaticCreateMethod(GetFixedName(typeName), instanceName); + + foreach (var propertyToParameterNamePair in propertyToParameterNamePairs) + { + IEdmProperty property = propertyToParameterNamePair.Key; + string parameterName = propertyToParameterNamePair.Value; + + Debug.Assert(!property.Type.IsCollection(), "!property.Type.IsCollection()"); + Debug.Assert(!property.Type.IsNullable, "!property.Type.IsNullable"); + + // The static create method only sets non-nullable properties. We should add the null check if the type of the property is not a clr ValueType. + // For now we add the null check if the property type is non-primitive. We should add the null check for non-ValueType primitives in the future. + if (!property.Type.IsPrimitive() && !property.Type.IsEnum()) + { + this.WriteParameterNullCheckForStaticCreateMethod(parameterName); + } + + var uniqIdentifier = IdentifierMappings.ContainsKey(property.Name) ? + IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); + this.WritePropertyValueAssignmentForStaticCreateMethod(instanceName, + GetFixedName(uniqIdentifier), + parameterName); + } + + this.WriteMethodEndForStaticCreateMethod(instanceName); + } + + internal void WriteStaticCreateMethodParameters(KeyValuePair[] propertyToParameterPairs) + { + if (propertyToParameterPairs.Length == 0) + { + return; + } + + // If the number of parameters are greater than 5, we put them in separate lines. + string parameterSeparator = propertyToParameterPairs.Length > 5 ? this.ParameterSeparator : ", "; + for (int idx = 0; idx < propertyToParameterPairs.Length; idx++) + { + KeyValuePair propertyToParameterPair = propertyToParameterPairs[idx]; + + string parameterType = Utils.GetClrTypeName(propertyToParameterPair.Key.Type, this.context.UseDataServiceCollection, this, this.context); + string parameterName = propertyToParameterPair.Value; + if (idx == propertyToParameterPairs.Length - 1) + { + // No separator after the last parameter. + parameterSeparator = string.Empty; + } + + this.WriteParameterForStaticCreateMethod(parameterType, GetFixedName(parameterName), parameterSeparator); + } + } + + internal void WritePropertiesForStructuredType(IEnumerable properties, bool isOpen) + { + bool useDataServiceCollection = this.context.UseDataServiceCollection; + + var propertyInfos = properties.Select(property => + { + string propertyName = IdentifierMappings.ContainsKey(property.Name) ? + IdentifierMappings[property.Name] : (this.context.EnableNamingAlias ? Customization.CustomizeNaming(property.Name) : property.Name); + + return new + { + PropertyType = Utils.GetClrTypeName(property.Type, useDataServiceCollection, this, this.context), + PropertyVanillaName = property.Name, + PropertyName = propertyName, + FixedPropertyName = GetFixedName(propertyName), + PrivatePropertyName = "_" + propertyName, + PropertyInitializationValue = Utils.GetPropertyInitializationValue(property, useDataServiceCollection, this, this.context) + }; + }).ToList(); + + if(isOpen && this.context.GenerateDynamicPropertiesCollection) + { + propertyInfos.Add(new + { + PropertyType = string.Format(this.DictionaryTypeName, this.StringTypeName, this.ObjectTypeName), + PropertyVanillaName = string.Empty, // No such property in metadata + PropertyName = this.context.DynamicPropertiesCollectionName, + FixedPropertyName = GetFixedName(this.context.DynamicPropertiesCollectionName), + PrivatePropertyName = "_" + Utils.CamelCase(this.context.DynamicPropertiesCollectionName), + PropertyInitializationValue = string.Format(this.DictionaryConstructor, this.StringTypeName, this.ObjectTypeName) + }); + } + + // Private name should not confict with field name + UniqueIdentifierService uniqueIdentifierService = new UniqueIdentifierService(propertyInfos.Select(_ => _.FixedPropertyName), + this.context.TargetLanguage == LanguageOption.CSharp); + + foreach (var propertyInfo in propertyInfos) + { + string privatePropertyName = uniqueIdentifierService.GetUniqueIdentifier("_" + propertyInfo.PropertyName); + + this.WritePropertyForStructuredType( + propertyInfo.PropertyType, + propertyInfo.PropertyVanillaName, + propertyInfo.PropertyName, + propertyInfo.FixedPropertyName, + privatePropertyName, + propertyInfo.PropertyInitializationValue, + useDataServiceCollection); + } + } + + internal void WriteMembersForEnumType(IEnumerable members) + { + int n = members.Count(); + for (int idx = 0; idx < n; ++idx) + { + IEdmEnumMember member = members.ElementAt(idx); + string value = string.Empty; + if (member.Value != null) + { + IEdmEnumMemberValue integerValue = member.Value as IEdmEnumMemberValue; + if (integerValue != null) + { + value = " = " + integerValue.Value.ToString(CultureInfo.InvariantCulture); + } + } + + string memberName = this.context.EnableNamingAlias ? Customization.CustomizeNaming(member.Name) : member.Name; + this.WriteMemberForEnumType(GetFixedName(memberName) + value, member.Name, idx == n - 1); + } + } + + internal string GetFixedName(string originalName) + { + string fixedName = originalName; + + if (this.LanguageKeywords.Contains(fixedName)) + { + fixedName = string.Format(this.FixPattern, fixedName); + } + + return fixedName; + } + + internal string GetElementTypeName(IEdmEntityType elementType, IEdmEntityContainer container) + { + string elementTypeName = elementType.Name; + + if (this.context.EnableNamingAlias) + { + elementTypeName = Customization.CustomizeNaming(elementTypeName); + } + + if (elementType.Namespace != container.Namespace) + { + elementTypeName = this.context.GetPrefixedFullName(elementType, GetFixedName(elementTypeName), this); + } + + return elementTypeName; + } +} + +/// +/// Base class for text transformation +/// +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "11.0.0.0")] +public abstract class TemplateBase +{ + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + protected System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); + } + return this.generationEnvironmentField; + } + set + { + this.generationEnvironmentField = value; + } + } + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + } + return this.errorsField; + } + } + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); + } + return this.indentLengthsField; + } + } + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; + } + } + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; + } + } + #endregion + + /// + /// Create the template output + /// + public abstract string TransformText(); + + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } + } + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); + this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; + } + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); + } + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; + } + } + } + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { + throw new global::System.ArgumentNullException("objectToConvert"); + } + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); + } + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); + } + } + } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion +} + +/// +/// Service making names within a scope unique. Initialize a new instance for every scope. +/// +internal sealed class UniqueIdentifierService +{ + // This is the list of keywords we check against when creating parameter names from propert. + // If a name matches this keyword we prefix it. + private static readonly string[] Keywords = new string[] {"class", "event"}; + + /// + /// Hash set to detect identifier collision. + /// + private readonly HashSet knownIdentifiers; + + /// + /// Constructs a . + /// + /// true if the language we are generating the code for is case sensitive, false otherwise. + internal UniqueIdentifierService(bool caseSensitive) + { + this.knownIdentifiers = new HashSet(caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); + } + + /// + /// Constructs a . + /// + /// identifiers used to detect collision. + /// true if the language we are generating the code for is case sensitive, false otherwise. + internal UniqueIdentifierService(IEnumerable identifiers, bool caseSensitive) + { + this.knownIdentifiers = new HashSet(identifiers ?? Enumerable.Empty(), caseSensitive ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase); + } + + /// + /// Given an identifier, makes it unique within the scope by adding + /// a suffix (1, 2, 3, ...), and returns the adjusted identifier. + /// + /// Identifier. Must not be null or empty. + /// Identifier adjusted to be unique within the scope. + internal string GetUniqueIdentifier(string identifier) + { + Debug.Assert(!string.IsNullOrEmpty(identifier), "identifier is null or empty"); + + // find a unique name by adding suffix as necessary + int numberOfConflicts = 0; + string uniqueIdentifier = identifier; + while (this.knownIdentifiers.Contains(uniqueIdentifier)) + { + ++numberOfConflicts; + uniqueIdentifier = identifier + numberOfConflicts.ToString(CultureInfo.InvariantCulture); + } + + // remember the identifier in this scope + Debug.Assert(!this.knownIdentifiers.Contains(uniqueIdentifier), "we just made it unique"); + this.knownIdentifiers.Add(uniqueIdentifier); + + return uniqueIdentifier; + } + + /// + /// Fix up the given parameter name and make it unique. + /// + /// Parameter name. + /// Fixed parameter name. + internal string GetUniqueParameterName(string name) + { + name = Utils.CamelCase(name); + + // FxCop consider 'iD' as violation, we will change any property that is 'id'(case insensitive) to 'ID' + if (StringComparer.OrdinalIgnoreCase.Equals(name, "id")) + { + name = "ID"; + } + + return this.GetUniqueIdentifier(name); + } +} + +/// +/// Utility class. +/// +internal static class Utils +{ + /// + /// Serializes the xml element to a string. + /// + /// The xml element to serialize. + /// The string representation of the xml. + internal static string SerializeToString(XElement xml) + { + // because comment nodes can contain special characters that are hard to embed in VisualBasic, remove them here + xml.DescendantNodes().OfType().Remove(); + + var stringBuilder = new StringBuilder(); + using (var writer = XmlWriter.Create( + stringBuilder, + new XmlWriterSettings + { + OmitXmlDeclaration = true, + NewLineHandling = NewLineHandling.Replace, + Indent = true, + })) + { + xml.WriteTo(writer); + } + + return stringBuilder.ToString(); + } + + /// + /// Changes the text to use camel case, which lower case for the first character. + /// + /// Text to convert. + /// The converted text in camel case + internal static string CamelCase(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant(); + } + + return text[0].ToString(CultureInfo.InvariantCulture).ToLowerInvariant() + text.Substring(1); + } + + /// + /// Changes the text to use pascal case, which upper case for the first character. + /// + /// Text to convert. + /// The converted text in pascal case + internal static string PascalCase(string text) + { + if (string.IsNullOrEmpty(text)) + { + return text; + } + + if (text.Length == 1) + { + return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant(); + } + + return text[0].ToString(CultureInfo.InvariantCulture).ToUpperInvariant() + text.Substring(1); + } + + /// + /// Gets the clr type name from the give type reference. + /// + /// The type reference in question. + /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, + /// false to use Collection for collections. + /// ODataClientTemplate instance that call this method. + /// CodeGenerationContext instance in the clientTemplate. + /// This flag indicates whether to return the type name in nullable format + /// The flag indicates whether the namespace need to be added by global prefix + /// This flag indicates whether the edmTypeReference is for an operation parameter + /// The clr type name of the type reference. + internal static string GetClrTypeName(IEdmTypeReference edmTypeReference, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context, bool addNullableTemplate = true, bool needGlobalPrefix = true, bool isOperationParameter = false, bool isEntitySingleType = false) + { + string clrTypeName; + IEdmType edmType = edmTypeReference.Definition; + IEdmPrimitiveType edmPrimitiveType = edmType as IEdmPrimitiveType; + if (edmPrimitiveType != null) + { + clrTypeName = Utils.GetClrTypeName(edmPrimitiveType, clientTemplate); + if (edmTypeReference.IsNullable && !clientTemplate.ClrReferenceTypes.Contains(edmPrimitiveType.PrimitiveKind) && addNullableTemplate) + { + clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); + } + } + else + { + IEdmComplexType edmComplexType = edmType as IEdmComplexType; + if (edmComplexType != null) + { + clrTypeName = context.GetPrefixedFullName(edmComplexType, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmComplexType.Name)) : clientTemplate.GetFixedName(edmComplexType.Name), clientTemplate); + } + else + { + IEdmEnumType edmEnumType = edmType as IEdmEnumType; + if (edmEnumType != null) + { + clrTypeName = context.GetPrefixedFullName(edmEnumType, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEnumType.Name)) : clientTemplate.GetFixedName(edmEnumType.Name), clientTemplate, needGlobalPrefix); + if (edmTypeReference.IsNullable && addNullableTemplate) + { + clrTypeName = string.Format(clientTemplate.SystemNullableStructureTemplate, clrTypeName); + } + } + else + { + IEdmEntityType edmEntityType = edmType as IEdmEntityType; + if (edmEntityType != null) + { + clrTypeName = context.GetPrefixedFullName(edmEntityType, + context.EnableNamingAlias + ? clientTemplate.GetFixedName(Customization.CustomizeNaming(edmEntityType.Name) + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)) + : clientTemplate.GetFixedName(edmEntityType.Name + (isEntitySingleType ? clientTemplate.SingleSuffix : string.Empty)), + clientTemplate); + } + else + { + IEdmCollectionType edmCollectionType = (IEdmCollectionType)edmType; + IEdmTypeReference elementTypeReference = edmCollectionType.ElementType; + IEdmPrimitiveType primitiveElementType = elementTypeReference.Definition as IEdmPrimitiveType; + if (primitiveElementType != null) + { + clrTypeName = Utils.GetClrTypeName(primitiveElementType, clientTemplate); + } + else + { + IEdmSchemaElement schemaElement = (IEdmSchemaElement)elementTypeReference.Definition; + clrTypeName = context.GetPrefixedFullName(schemaElement, + context.EnableNamingAlias ? clientTemplate.GetFixedName(Customization.CustomizeNaming(schemaElement.Name)) : clientTemplate.GetFixedName(schemaElement.Name), clientTemplate); + } + + string collectionTypeName = isOperationParameter + ? clientTemplate.ICollectionOfTStructureTemplate + : (useDataServiceCollection + ? (elementTypeReference.TypeKind() == EdmTypeKind.Entity + ? clientTemplate.DataServiceCollectionStructureTemplate + : clientTemplate.ObservableCollectionStructureTemplate) + : clientTemplate.ObjectModelCollectionStructureTemplate); + + clrTypeName = string.Format(collectionTypeName, clrTypeName); + } + } + } + } + + return clrTypeName; + } + + /// + /// Gets the value expression to initualize the property with. + /// + /// The property in question. + /// true to use the DataServicCollection type for entity collections and the ObservableCollection type for non-entity collections, + /// false to use Collection for collections. + /// ODataClientTemplate instance that call this method. + /// CodeGenerationContext instance in the clientTemplate. + /// The value expression to initualize the property with. + internal static string GetPropertyInitializationValue(IEdmProperty property, bool useDataServiceCollection, ODataClientTemplate clientTemplate, CodeGenerationContext context) + { + IEdmTypeReference edmTypeReference = property.Type; + IEdmCollectionTypeReference edmCollectionTypeReference = edmTypeReference as IEdmCollectionTypeReference; + if (edmCollectionTypeReference == null) + { + IEdmStructuralProperty structuredProperty = property as IEdmStructuralProperty; + if (structuredProperty != null) + { + if (!string.IsNullOrEmpty(structuredProperty.DefaultValueString)) + { + string valueClrType = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + string defaultValue = structuredProperty.DefaultValueString; + bool isCSharpTemplate = clientTemplate is ODataClientCSharpTemplate; + if (edmTypeReference.Definition.TypeKind == EdmTypeKind.Enum) + { + var enumValues = defaultValue.Split(','); + string fullenumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + string enumTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context, false, false); + List customizedEnumValues = new List(); + foreach(var enumValue in enumValues) + { + string currentEnumValue = enumValue.Trim(); + int indexFirst = currentEnumValue.IndexOf('\'') + 1; + int indexLast = currentEnumValue.LastIndexOf('\''); + if (indexFirst > 0 && indexLast > indexFirst) + { + currentEnumValue = currentEnumValue.Substring(indexFirst, indexLast - indexFirst); + } + + var customizedEnumValue = context.EnableNamingAlias ? Customization.CustomizeNaming(currentEnumValue) : currentEnumValue; + if (isCSharpTemplate) + { + currentEnumValue = "(" + fullenumTypeName + ")" + clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + customizedEnumValue + "\")"; + } + else + { + currentEnumValue = clientTemplate.EnumTypeName + ".Parse(" + clientTemplate.SystemTypeTypeName + ".GetType(\"" + enumTypeName + "\"), \"" + currentEnumValue + "\")"; + } + customizedEnumValues.Add(currentEnumValue); + } + if (isCSharpTemplate) + { + return string.Join(" | ", customizedEnumValues); + } + else + { + return string.Join(" Or ", customizedEnumValues); + } + } + + if (valueClrType.Equals(clientTemplate.StringTypeName)) + { + defaultValue = "\"" + defaultValue + "\""; + } + else if (valueClrType.Equals(clientTemplate.BinaryTypeName)) + { + defaultValue = "System.Text.Encoding.UTF8.GetBytes(\"" + defaultValue + "\")"; + } + else if (valueClrType.Equals(clientTemplate.SingleTypeName)) + { + if (isCSharpTemplate) + { + defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "f"; + } + else + { + defaultValue = defaultValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "F"; + } + } + else if (valueClrType.Equals(clientTemplate.DecimalTypeName)) + { + if (isCSharpTemplate) + { + // decimal in C# must be initialized with 'm' at the end, like Decimal dec = 3.00m + defaultValue = defaultValue.EndsWith("m", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "m"; + } + else + { + // decimal in VB must be initialized with 'D' at the end, like Decimal dec = 3.00D + defaultValue = defaultValue.ToLower().Replace("m", "D"); + defaultValue = defaultValue.EndsWith("D", StringComparison.OrdinalIgnoreCase) ? defaultValue : defaultValue + "D"; + } + } + else if (valueClrType.Equals(clientTemplate.GuidTypeName) + | valueClrType.Equals(clientTemplate.DateTimeOffsetTypeName) + | valueClrType.Equals(clientTemplate.DateTypeName) + | valueClrType.Equals(clientTemplate.TimeOfDayTypeName)) + { + defaultValue = valueClrType + ".Parse(\"" + defaultValue + "\")"; + } + else if (valueClrType.Equals(clientTemplate.DurationTypeName)) + { + defaultValue = clientTemplate.XmlConvertClassName + ".ToTimeSpan(\"" + defaultValue + "\")"; + } + else if (valueClrType.Contains("Microsoft.Spatial")) + { + defaultValue = string.Format(clientTemplate.GeoTypeInitializePattern, valueClrType, defaultValue); + } + + return defaultValue; + } + else + { + // doesn't have a default value + return null; + } + } + else + { + // only structured property has default value + return null; + } + } + else + { + string constructorParameters; + if (edmCollectionTypeReference.ElementType().IsEntity() && useDataServiceCollection) + { + constructorParameters = clientTemplate.DataServiceCollectionConstructorParameters; + } + else + { + constructorParameters = "()"; + } + + string clrTypeName = GetClrTypeName(edmTypeReference, useDataServiceCollection, clientTemplate, context); + return clientTemplate.NewModifier + clrTypeName + constructorParameters; + } + } + + /// + /// Gets the clr type name from the give Edm primitive type. + /// + /// The Edm primitive type in question. + /// ODataClientTemplate instance that call this method. + /// The clr type name of the Edm primitive type. + internal static string GetClrTypeName(IEdmPrimitiveType edmPrimitiveType, ODataClientTemplate clientTemplate) + { + EdmPrimitiveTypeKind kind = edmPrimitiveType.PrimitiveKind; + + string type="UNKNOWN"; + if (kind==EdmPrimitiveTypeKind.Int32) + { + type= clientTemplate.Int32TypeName; + } + else if (kind== EdmPrimitiveTypeKind.String) + { + type= clientTemplate.StringTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Binary) + { + type= clientTemplate.BinaryTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Decimal) + { + type= clientTemplate.DecimalTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Int16) + { + type= clientTemplate.Int16TypeName; + } + else if(kind==EdmPrimitiveTypeKind.Single) + { + type= clientTemplate.SingleTypeName; + } + else if (kind==EdmPrimitiveTypeKind.Boolean) + { + type= clientTemplate.BooleanTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Double) + { + type= clientTemplate.DoubleTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Guid) + { + type= clientTemplate.GuidTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Byte) + { + type= clientTemplate.ByteTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Int64) + { + type= clientTemplate.Int64TypeName; + } + else if (kind== EdmPrimitiveTypeKind.SByte) + { + type= clientTemplate.SByteTypeName; + } + else if (kind == EdmPrimitiveTypeKind.Stream) + { + type= clientTemplate.DataServiceStreamLinkTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Geography) + { + type= clientTemplate.GeographyTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyPoint) + { + type= clientTemplate.GeographyPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyLineString) + { + type= clientTemplate.GeographyLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyPolygon) + { + type= clientTemplate.GeographyPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyCollection) + { + type= clientTemplate.GeographyCollectionTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiPolygon) + { + type= clientTemplate.GeographyMultiPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiLineString) + { + type= clientTemplate.GeographyMultiLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeographyMultiPoint) + { + type= clientTemplate.GeographyMultiPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Geometry) + { + type= clientTemplate.GeometryTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryPoint) + { + type= clientTemplate.GeometryPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryLineString) + { + type= clientTemplate.GeometryLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryPolygon) + { + type= clientTemplate.GeometryPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryCollection) + { + type= clientTemplate.GeometryCollectionTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiPolygon) + { + type= clientTemplate.GeometryMultiPolygonTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiLineString) + { + type= clientTemplate.GeometryMultiLineStringTypeName; + } + else if (kind== EdmPrimitiveTypeKind.GeometryMultiPoint) + { + type= clientTemplate.GeometryMultiPointTypeName; + } + else if (kind== EdmPrimitiveTypeKind.DateTimeOffset) + { + type= clientTemplate.DateTimeOffsetTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Duration) + { + type= clientTemplate.DurationTypeName; + } + else if (kind== EdmPrimitiveTypeKind.Date) + { + type= clientTemplate.DateTypeName; + } + else if (kind== EdmPrimitiveTypeKind.TimeOfDay) + { + type= clientTemplate.TimeOfDayTypeName; + } + else + { + throw new Exception("Type "+kind.ToString()+" is unrecognized"); + } + + return type; + } +} + +public sealed class ODataClientCSharpTemplate : ODataClientTemplate +{ + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The code generation context. + public ODataClientCSharpTemplate(CodeGenerationContext context) + : base(context) + { + } + + internal override string GlobalPrefix { get {return "global::"; } } + internal override string SystemTypeTypeName { get { return "global::System.Type"; } } + internal override string AbstractModifier { get { return " abstract"; } } + internal override string DataServiceActionQueryTypeName { get { return "global::Microsoft.OData.Client.DataServiceActionQuery"; } } + internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuerySingle<{0}>"; } } + internal override string DataServiceActionQueryOfTStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceActionQuery<{0}>"; } } + internal override string NotifyPropertyChangedModifier { get { return "global::System.ComponentModel.INotifyPropertyChanged"; } } + internal override string ClassInheritMarker { get { return " : "; } } + internal override string ParameterSeparator { get { return ", \r\n "; } } + internal override string KeyParameterSeparator { get { return ", \r\n "; } } + internal override string KeyDictionaryItemSeparator { get { return ", \r\n "; } } + internal override string SystemNullableStructureTemplate { get { return "global::System.Nullable<{0}>"; } } + internal override string ICollectionOfTStructureTemplate { get { return "global::System.Collections.Generic.ICollection<{0}>"; } } + internal override string DataServiceCollectionStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceCollection<{0}>"; } } + internal override string DataServiceQueryStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuery<{0}>"; } } + internal override string DataServiceQuerySingleStructureTemplate { get { return "global::Microsoft.OData.Client.DataServiceQuerySingle<{0}>"; } } + internal override string ObservableCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.ObservableCollection<{0}>"; } } + internal override string ObjectModelCollectionStructureTemplate { get { return "global::System.Collections.ObjectModel.Collection<{0}>"; } } + internal override string DataServiceCollectionConstructorParameters { get { return "(null, global::Microsoft.OData.Client.TrackingMode.None)"; } } + internal override string NewModifier { get { return "new "; } } + internal override string GeoTypeInitializePattern { get { return "global::Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(false).Read<{0}>(new global::System.IO.StringReader(\"{1}\"))"; } } + internal override string Int32TypeName { get { return "int"; } } + internal override string ObjectTypeName { get { return "object"; } } + internal override string StringTypeName { get { return "string"; } } + internal override string BinaryTypeName { get { return "byte[]"; } } + internal override string DecimalTypeName { get { return "decimal"; } } + internal override string Int16TypeName { get { return "short"; } } + internal override string SingleTypeName { get { return "float"; } } + internal override string BooleanTypeName { get { return "bool"; } } + internal override string DoubleTypeName { get { return "double"; } } + internal override string GuidTypeName { get { return "global::System.Guid"; } } + internal override string ByteTypeName { get { return "byte"; } } + internal override string Int64TypeName { get { return "long"; } } + internal override string SByteTypeName { get { return "sbyte"; } } + internal override string DataServiceStreamLinkTypeName { get { return "global::Microsoft.OData.Client.DataServiceStreamLink"; } } + internal override string GeographyTypeName { get { return "global::Microsoft.Spatial.Geography"; } } + internal override string GeographyPointTypeName { get { return "global::Microsoft.Spatial.GeographyPoint"; } } + internal override string GeographyLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyLineString"; } } + internal override string GeographyPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyPolygon"; } } + internal override string GeographyCollectionTypeName { get { return "global::Microsoft.Spatial.GeographyCollection"; } } + internal override string GeographyMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPolygon"; } } + internal override string GeographyMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeographyMultiLineString"; } } + internal override string GeographyMultiPointTypeName { get { return "global::Microsoft.Spatial.GeographyMultiPoint"; } } + internal override string GeometryTypeName { get { return "global::Microsoft.Spatial.Geometry"; } } + internal override string GeometryPointTypeName { get { return "global::Microsoft.Spatial.GeometryPoint"; } } + internal override string GeometryLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryLineString"; } } + internal override string GeometryPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryPolygon"; } } + internal override string GeometryCollectionTypeName { get { return "global::Microsoft.Spatial.GeometryCollection"; } } + internal override string GeometryMultiPolygonTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPolygon"; } } + internal override string GeometryMultiLineStringTypeName { get { return "global::Microsoft.Spatial.GeometryMultiLineString"; } } + internal override string GeometryMultiPointTypeName { get { return "global::Microsoft.Spatial.GeometryMultiPoint"; } } + internal override string DateTypeName { get { return "global::Microsoft.OData.Edm.Date"; } } + internal override string DateTimeOffsetTypeName { get { return "global::System.DateTimeOffset"; } } + internal override string DurationTypeName { get { return "global::System.TimeSpan"; } } + internal override string TimeOfDayTypeName { get { return "global::Microsoft.OData.Edm.TimeOfDay"; } } + internal override string XmlConvertClassName { get { return "global::System.Xml.XmlConvert"; } } + internal override string EnumTypeName { get { return "global::System.Enum"; } } + internal override string DictionaryTypeName { get { return "global::System.Collections.Generic.Dictionary<{0}, {1}>"; } } + internal override string FixPattern { get { return "@{0}"; } } + internal override string EnumUnderlyingTypeMarker { get { return " : "; } } + internal override string ConstantExpressionConstructorWithType { get { return "global::System.Linq.Expressions.Expression.Constant({0}, typeof({1}))"; } } + internal override string TypeofFormatter { get { return "typeof({0})"; } } + internal override string UriOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } + internal override string UriEntityOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } + internal override string BodyOperationParameterConstructor { get { return "new global::Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } + internal override string DictionaryConstructor { get { return $"new {DictionaryTypeName}()"; } } + internal override string BaseEntityType { get { return " : global::Microsoft.OData.Client.BaseEntityType"; } } + internal override string OverloadsModifier { get { return "new "; } } + internal override string ODataVersion { get { return "global::Microsoft.OData.ODataVersion.V4"; } } + internal override string ParameterDeclarationTemplate { get { return "{0} {1}"; } } + internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } + internal override HashSet LanguageKeywords { get { + if (CSharpKeywords == null) + { + CSharpKeywords = new HashSet(StringComparer.Ordinal) + { + "abstract", "as", "base", "byte", "bool", "break", "case", "catch", "char", "checked", "class", "const", "continue", + "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "for", + "foreach", "finally", "fixed", "float", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", + "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", + "readonly", "ref", "return", "sbyte", "sealed", "string", "short", "sizeof", "stackalloc", "static", "struct", "switch", + "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "volatile", + "void", "while" + }; + } + return CSharpKeywords; + } } + private HashSet CSharpKeywords; + + internal override void WriteFileHeader() + { +#>//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:<#= Environment.Version #> +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// Generation date: <#= DateTime.Now.ToString(global::System.Globalization.CultureInfo.CurrentCulture) #> +<#+ + } + + internal override void WriteNamespaceStart(string fullNamespace) + { +#> +namespace <#= fullNamespace #> +{ +<#+ + } + + internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) + { +#> + /// + /// There are no comments for <#= containerName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalContainerName #>")] +<#+ + } +#> + public partial class <#= fixedContainerName #> : global::Microsoft.OData.Client.DataServiceContext + { +<#+ + } + + internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) + { +#> + /// + /// Initialize a new <#= containerName #> object. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public <#= fixedContainerName #>(global::System.Uri serviceRoot) : + base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4) + { +<#+ + } + + internal override void WriteKeyAsSegmentUrlConvention() + { +#> + this.UrlKeyDelimiter = global::Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash; +<#+ + } + + internal override void WriteInitializeResolveName() + { +#> + this.ResolveName = new global::System.Func(this.ResolveNameFromType); +<#+ + } + + internal override void WriteInitializeResolveType() + { +#> + this.ResolveType = new global::System.Func(this.ResolveTypeFromName); +<#+ + } + + internal override void WriteClassEndForEntityContainerConstructor() + { +#> + this.OnContextCreated(); + this.Format.LoadServiceModel = GeneratedEdmModel.GetInstance; + this.Format.UseJson(); + } + partial void OnContextCreated(); +<#+ + } + + internal override void WriteMethodStartForResolveTypeFromName() + { +#> + /// + /// Since the namespace configured for this service reference + /// in Visual Studio is different from the one indicated in the + /// server schema, use type-mappers to map between the two. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected global::System.Type ResolveTypeFromName(string typeName) + { +<#+ + } + + internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) + { +#> + <#= typeName #>resolvedType = this.DefaultResolveType(typeName, "<#= fullNamespace #>", "<#= languageDependentNamespace #>"); + if ((resolvedType != null)) + { + return resolvedType; + } +<#+ + } + + internal override void WriteMethodEndForResolveTypeFromName() + { +#> + return null; + } +<#+ + } + + internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) + { + + } + + internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) + { +#> + /// + /// Since the namespace configured for this service reference + /// in Visual Studio is different from the one indicated in the + /// server schema, use type-mappers to map between the two. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected string ResolveNameFromType(global::System.Type clientType) + { +<#+ + if (this.context.EnableNamingAlias) + { +#> + global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true)); +<#+ + } + } + + internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) + { +#> + if (clientType.Namespace.Equals("<#= languageDependentNamespace #>", global::System.StringComparison.Ordinal)) + { +<#+ + if (this.context.EnableNamingAlias) + { +#> + if (originalNameAttribute != null) + { + return string.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName); + } +<#+ + } +#> + return string.Concat("<#= fullNamespace #>.", clientType.Name); + } +<#+ + } + + internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) + { + if (this.context.EnableNamingAlias && modelHasInheritance) + { +#> + if (originalNameAttribute != null) + { + return clientType.Namespace + "." + originalNameAttribute.OriginalName; + } +<#+ + } +#> + return <#= modelHasInheritance ? "clientType.FullName" : "null" #>; + } +<#+ + } + + internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) + { +#> + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path) + : base(context, path) {} + + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(global::Microsoft.OData.Client.DataServiceContext context, string path, bool isComposable) + : base(context, path, isComposable) {} + + /// + /// Initialize a new <#= singleTypeName #> object. + /// + public <#= singleTypeName #>(<#= baseTypeName #> query) + : base(query) {} + +<#+ + } + + internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) + { +#> + /// + /// There are no comments for <#= entitySetName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEntitySetName #>")] +<#+ + } +#> + public global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> <#= entitySetFixedName #> + { + get + { +<#+ + if (!inContext) + { +#> + if (!this.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } +<#+ + } +#> + if ((this._<#= entitySetName #> == null)) + { + this._<#= entitySetName #> = <#= inContext ? "base" : "Context" #>.CreateQuery<<#= entitySetElementTypeName #>>(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>); + } + return this._<#= entitySetName #>; + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private global::Microsoft.OData.Client.DataServiceQuery<<#= entitySetElementTypeName #>> _<#= entitySetName #>; +<#+ + } + + internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) + { +#> + /// + /// There are no comments for <#= singletonName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalSingletonName #>")] +<#+ + } +#> + public <#= singletonElementTypeName #> <#= singletonFixedName #> + { + get + { +<#+ + if (!inContext) + { +#> + if (!this.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } +<#+ + } +#> + if ((this._<#= singletonName #> == null)) + { + this._<#= singletonName #> = new <#= singletonElementTypeName #>(<#= inContext ? "this" : "this.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>); + } + return this._<#= singletonName #>; + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private <#= singletonElementTypeName #> _<#= singletonName #>; +<#+ + } + + internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) + { +#> + /// + /// There are no comments for <#= entitySetName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public void AddTo<#= entitySetName #>(<#= typeName #> <#= parameterName #>) + { + base.AddObject("<#= originalEntitySetName #>", <#= parameterName #>); + } +<#+ + } + + internal override void WriteGeneratedEdmModel(string escapedEdmxString) + { + + string path = this.context.TempFilePath; + + if (!String.IsNullOrEmpty(path)) + { + using (StreamWriter writer = new StreamWriter(path, true)) + { + writer.WriteLine(escapedEdmxString); + } + } + + bool useTempFile = !String.IsNullOrEmpty(path) && System.IO.File.Exists(path); +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private abstract class GeneratedEdmModel + { +<#+ + if (this.context.ReferencesMap != null) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Collections.Generic.Dictionary ReferencesMap = new global::System.Collections.Generic.Dictionary() + { +<#+ + foreach(var reference in this.context.ReferencesMap) + { +#> + {@"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", @"<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"") #>"}, +<#+ + } +#> + }; +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString(); +<#+ + if (useTempFile) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private const string filePath = @"<#= path #>"; +<#+ + } + else + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private const string Edmx = @"<#= escapedEdmxString #>"; +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public static global::Microsoft.OData.Edm.IEdmModel GetInstance() + { + return ParsedModel; + } +<#+ + if (this.context.ReferencesMap != null) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader getReferencedModelFromMap(global::System.Uri uri) + { + string referencedEdmx; + if (ReferencesMap.TryGetValue(uri.OriginalString, out referencedEdmx)) + { + return CreateXmlReader(referencedEdmx); + } + + return null; + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() + { +<#+ + if (useTempFile) + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(); +<#+ + } + else + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); +<#+ + } +#> + try + { + return global::Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, getReferencedModelFromMap); + } + finally + { + ((global::System.IDisposable)(reader)).Dispose(); + } + } +<#+ + } + else + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString() + { +<#+ + if (useTempFile) + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(); +<#+ + } + else + { +#> + global::System.Xml.XmlReader reader = CreateXmlReader(Edmx); +<#+ + } +#> + try + { + global::System.Collections.Generic.IEnumerable errors; + global::Microsoft.OData.Edm.IEdmModel edmModel; + + if (!global::Microsoft.OData.Edm.Csdl.CsdlReader.TryParse(reader, <#= this.context.IgnoreUnexpectedElementsAndAttributes ? "true" : "false" #>, out edmModel, out errors)) + { + global::System.Text.StringBuilder errorMessages = new System.Text.StringBuilder(); + foreach (var error in errors) + { + errorMessages.Append(error.ErrorMessage); + errorMessages.Append("; "); + } + throw new global::System.InvalidOperationException(errorMessages.ToString()); + } + + return edmModel; + } + finally + { + ((global::System.IDisposable)(reader)).Dispose(); + } + } +<#+ + } +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse) + { + return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse)); + } +<#+ + if (useTempFile) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private static global::System.Xml.XmlReader CreateXmlReader() + { + return global::System.Xml.XmlReader.Create(new global::System.IO.StreamReader(filePath)); + } +<#+ + } +#> + } +<#+ + } + + internal override void WriteClassEndForEntityContainer() + { +#> + } +<#+ + } + + internal override void WriteSummaryCommentForStructuredType(string typeName) + { +#> + /// + /// There are no comments for <#= typeName #> in the schema. + /// +<#+ + } + + internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) + { +#> + /// +<#+ + foreach (string key in keyProperties) + { +#> + /// <#= key #> +<#+ + } +#> + /// + [global::Microsoft.OData.Client.Key("<#= keyString #>")] +<#+ + } + + internal override void WriteEntityTypeAttribute() + { +#> + [global::Microsoft.OData.Client.EntityType()] +<#+ + } + + internal override void WriteEntitySetAttribute(string entitySetName) + { +#> + [global::Microsoft.OData.Client.EntitySet("<#= entitySetName #>")] +<#+ + } + + internal override void WriteEntityHasStreamAttribute() + { +#> + [global::Microsoft.OData.Client.HasStream()] +<#+ + } + + internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalTypeName #>")] +<#+ + } +#> + public<#= abstractModifier #> partial class <#= typeName #><#= baseTypeName #> + { +<#+ + } + + internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) + { +#> + /// + /// Create a new <#= typeName #> object. + /// +<#+ + } + + internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) + { +#> + /// Initial value of <#= propertyName #>. +<#+ + } + + internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) + { +#> + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public static <#= fixedTypeName #> Create<#= typeName #>(<#+ + } + + internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) + { +#><#= parameterTypeName #> <#= parameterName #><#= parameterSeparater #><#+ + } + + internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) + { + #>) + { + <#= typeName #> <#= instanceName #> = new <#= typeName #>(); +<#+ + } + + internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) + { +#> + if ((<#= parameterName #> == null)) + { + throw new global::System.ArgumentNullException("<#= parameterName #>"); + } +<#+ + } + + internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) + { +#> + <#= instanceName #>.<#= propertyName #> = <#= parameterName #>; +<#+ + } + + internal override void WriteMethodEndForStaticCreateMethod(string instanceName) + { +#> + return <#= instanceName #>; + } +<#+ + } + + internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) + { +#> + /// + /// There are no comments for Property <#= propertyName #> in the schema. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] +<#+ + if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalPropertyName #>")] +<#+ + } +#> + public <#= propertyType #> <#= fixedPropertyName #> + { + get + { + return this.<#= privatePropertyName #>; + } + set + { + this.On<#= propertyName #>Changing(value); + this.<#= privatePropertyName #> = value; + this.On<#= propertyName #>Changed(); +<#+ + if (writeOnPropertyChanged) + { +#> + this.OnPropertyChanged("<#= originalPropertyName #>"); +<#+ + } +#> + } + } + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + private <#= propertyType #> <#= privatePropertyName #><#= propertyInitializationValue != null ? " = " + propertyInitializationValue : string.Empty #>; + partial void On<#= propertyName #>Changing(<#= propertyType #> value); + partial void On<#= propertyName #>Changed(); +<#+ + } + + internal override void WriteINotifyPropertyChangedImplementation() + { +#> + /// + /// This event is raised when the value of the property is changed + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; + /// + /// The value of the property is changed + /// + /// property name + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "<#=T4Version#>")] + protected virtual void OnPropertyChanged(string property) + { + if ((this.PropertyChanged != null)) + { + this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property)); + } + } +<#+ + } + + internal override void WriteClassEndForStructuredType() + { +#> + } +<#+ + } + + internal override void WriteEnumFlags() + { +#> + [global::System.Flags] +<#+ + } + + internal override void WriteSummaryCommentForEnumType(string enumName) + { +#> + /// + /// There are no comments for <#= enumName #> in the schema. + /// +<#+ + } + + internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalEnumName #>")] +<#+ + } +#> + public enum <#= enumName #><#= underlyingType #> + { +<#+ + } + + internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) + { + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalMemberName #>")] +<#+ + } +#> + <#= member #><#= last ? string.Empty : "," #> +<#+ + } + + internal override void WriteEnumEnd() + { +#> + } +<#+ + } + + internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + return this.CreateFunctionQuery<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.CreateFunctionQuerySingle<<#= returnTypeName #>>("", "<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + global::System.Uri requestUri; + Context.TryGetUri(this, out requestUri); + return this.Context.CreateFunctionQuery<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>); + } +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(<#= parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + global::System.Uri requestUri; + Context.TryGetUri(this, out requestUri); + + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>this.Context.CreateFunctionQuerySingle<<#= returnTypeName #>>(string.Join("/", global::System.Linq.Enumerable.Select(global::System.Linq.Enumerable.Skip(requestUri.Segments, this.Context.BaseUri.Segments.Length), s => s.Trim('/'))), "<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public <#= returnTypeName #> <#= actionName #>(<#= parameters #>) + { + return new <#= returnTypeName #>(this, this.BaseUri.OriginalString.Trim('/') + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #><#= returnTypeName #> <#= actionName #>(<#= parameters #>) + { + global::Microsoft.OData.Client.EntityDescriptor resource = Context.EntityTracker.TryGetEntityDescriptor(this); + if (resource == null) + { + throw new global::System.Exception("cannot find entity"); + } + + return new <#= returnTypeName #>(this.Context, resource.EditLink.OriginalString.Trim('/') + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteExtensionMethodsStart() + { +#> + /// + /// Class containing all extension methods + /// + public static class ExtensionMethods + { +<#+ + } + + internal override void WriteExtensionMethodsEnd() + { +#> + } +<#+ + } + + internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) + { +#> + /// + /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + /// + /// source entity set + /// dictionary with the names and values of keys + public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, global::System.Collections.Generic.Dictionary keys) + { + return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); + } + /// + /// Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + /// + /// source entity set +<#+ + foreach (var key in keys) + { +#> + /// The value of <#= key #> +<#+ + } +#> + public static <#= returnTypeName #> ByKey(this global::Microsoft.OData.Client.DataServiceQuery<<#= entityTypeName #>> source, + <#= keyParameters #>) + { + global::System.Collections.Generic.Dictionary keys = new global::System.Collections.Generic.Dictionary + { + <#= keyDictionaryItems #> + }; + return new <#= returnTypeName #>(source.Context, source.GetKeyPath(global::Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))); + } +<#+ + } + + internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) + { +#> + /// + /// Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> + /// + /// source entity + public static <#= returnTypeName #> CastTo<#= derivedTypeName #>(this global::Microsoft.OData.Client.DataServiceQuerySingle<<#= baseTypeName #>> source) + { + global::Microsoft.OData.Client.DataServiceQuerySingle<<#= derivedTypeFullName #>> query = source.CastTo<<#= derivedTypeFullName #>>(); + return new <#= returnTypeName #>(source.Context, query.GetPath(null)); + } +<#+ + } + + internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public static <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = false" : string.Empty #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return <#= isReturnEntity ? "new " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #>; + } +<#+ + } + + internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + /// + /// There are no comments for <#= functionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalFunctionName #>")] +<#+ + } +#> + public static global::Microsoft.OData.Client.DataServiceQuery<<#= returnTypeName #>> <#= functionName #>(this <#= boundTypeName #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", bool useEntityReference = true" : string.Empty #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return source.CreateFunctionQuery<<#= returnTypeName #>>("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable.ToString().ToLower() #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + /// + /// There are no comments for <#= actionName #> in the schema. + /// +<#+ + if (this.context.EnableNamingAlias) + { +#> + [global::Microsoft.OData.Client.OriginalNameAttribute("<#= originalActionName #>")] +<#+ + } +#> + public static <#= returnTypeName #> <#= actionName #>(this <#= boundSourceType #> source<#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) + { + if (!source.IsComposable) + { + throw new global::System.NotSupportedException("The previous function is not composable."); + } + + return new <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>); + } +<#+ + } + + internal override void WriteNamespaceEnd() + { +#> +} +<#+ + } +} + +public sealed class ODataClientVBTemplate : ODataClientTemplate +{ + /// + /// Creates an instance of the ODataClientTemplate. + /// + /// The cotion context. + public ODataClientVBTemplate(CodeGenerationContext context) + : base(context) + { + } + + internal override string GlobalPrefix { get { return string.Empty; } } + internal override string SystemTypeTypeName { get { return "Global.System.Type"; } } + internal override string AbstractModifier { get { return " MustInherit"; } } + internal override string DataServiceActionQueryTypeName { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery"; } } + internal override string DataServiceActionQuerySingleOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuerySingle(Of {0})"; } } + internal override string DataServiceActionQueryOfTStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceActionQuery(Of {0})"; } } + internal override string NotifyPropertyChangedModifier { get { return "\r\n Implements Global.System.ComponentModel.INotifyPropertyChanged"; } } + internal override string ClassInheritMarker { get { return "\r\n Inherits "; } } + internal override string ParameterSeparator { get { return ", _\r\n "; } } + internal override string KeyParameterSeparator { get { return ", _\r\n "; } } + internal override string KeyDictionaryItemSeparator { get { return ", _\r\n "; } } + internal override string SystemNullableStructureTemplate { get { return "Global.System.Nullable(Of {0})"; } } + internal override string ICollectionOfTStructureTemplate { get { return "Global.System.Collections.Generic.ICollection(Of {0})"; } } + internal override string DataServiceCollectionStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceCollection(Of {0})"; } } + internal override string DataServiceQueryStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuery(Of {0})"; } } + internal override string DataServiceQuerySingleStructureTemplate { get { return "Global.Microsoft.OData.Client.DataServiceQuerySingle(Of {0})"; } } + internal override string ObservableCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.ObservableCollection(Of {0})"; } } + internal override string ObjectModelCollectionStructureTemplate { get { return "Global.System.Collections.ObjectModel.Collection(Of {0})"; } } + internal override string DataServiceCollectionConstructorParameters { get { return "(Nothing, Global.Microsoft.OData.Client.TrackingMode.None)"; } } + internal override string NewModifier { get { return "New "; } } + internal override string GeoTypeInitializePattern { get { return "Global.Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateWellKnownTextSqlFormatter(False).Read(Of {0})(New Global.System.IO.StringReader(\"{1}\"))"; } } + internal override string Int32TypeName { get { return "Integer"; } } + internal override string ObjectTypeName { get { return "Object"; } } + internal override string StringTypeName { get { return "String"; } } + internal override string BinaryTypeName { get { return "Byte()"; } } + internal override string DecimalTypeName { get { return "Decimal"; } } + internal override string Int16TypeName { get { return "Short"; } } + internal override string SingleTypeName { get { return "Single"; } } + internal override string BooleanTypeName { get { return "Boolean"; } } + internal override string DoubleTypeName { get { return "Double"; } } + internal override string GuidTypeName { get { return "Global.System.Guid"; } } + internal override string ByteTypeName { get { return "Byte"; } } + internal override string Int64TypeName { get { return "Long"; } } + internal override string SByteTypeName { get { return "SByte"; } } + internal override string DataServiceStreamLinkTypeName { get { return "Global.Microsoft.OData.Client.DataServiceStreamLink"; } } + internal override string GeographyTypeName { get { return "Global.Microsoft.Spatial.Geography"; } } + internal override string GeographyPointTypeName { get { return "Global.Microsoft.Spatial.GeographyPoint"; } } + internal override string GeographyLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyLineString"; } } + internal override string GeographyPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyPolygon"; } } + internal override string GeographyCollectionTypeName { get { return "Global.Microsoft.Spatial.GeographyCollection"; } } + internal override string GeographyMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPolygon"; } } + internal override string GeographyMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiLineString"; } } + internal override string GeographyMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeographyMultiPoint"; } } + internal override string GeometryTypeName { get { return "Global.Microsoft.Spatial.Geometry"; } } + internal override string GeometryPointTypeName { get { return "Global.Microsoft.Spatial.GeometryPoint"; } } + internal override string GeometryLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryLineString"; } } + internal override string GeometryPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryPolygon"; } } + internal override string GeometryCollectionTypeName { get { return "Global.Microsoft.Spatial.GeometryCollection"; } } + internal override string GeometryMultiPolygonTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPolygon"; } } + internal override string GeometryMultiLineStringTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiLineString"; } } + internal override string GeometryMultiPointTypeName { get { return "Global.Microsoft.Spatial.GeometryMultiPoint"; } } + internal override string DateTypeName { get { return "Global.Microsoft.OData.Edm.Date"; } } + internal override string DateTimeOffsetTypeName { get { return "Global.System.DateTimeOffset"; } } + internal override string DurationTypeName { get { return "Global.System.TimeSpan"; } } + internal override string TimeOfDayTypeName { get { return "Global.Microsoft.OData.Edm.TimeOfDay"; } } + internal override string XmlConvertClassName { get { return "Global.System.Xml.XmlConvert"; } } + internal override string EnumTypeName { get { return "Global.System.Enum"; } } + internal override string DictionaryTypeName { get { return "Global.System.Collections.Generic.Dictionary(Of {0}, {1})"; } } + internal override string FixPattern { get { return "[{0}]"; } } + internal override string EnumUnderlyingTypeMarker { get { return " As "; } } + internal override string ConstantExpressionConstructorWithType { get { return "Global.System.Linq.Expressions.Expression.Constant({0}, GetType({1}))"; } } + internal override string TypeofFormatter { get { return "GetType({0})"; } } + internal override string UriOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriOperationParameter(\"{0}\", {1})"; } } + internal override string UriEntityOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.UriEntityOperationParameter(\"{0}\", {1}, {2})"; } } + internal override string BodyOperationParameterConstructor { get { return "New Global.Microsoft.OData.Client.BodyOperationParameter(\"{0}\", {1})"; } } + internal override string DictionaryConstructor { get { return $"New {DictionaryTypeName}"; } } + internal override string BaseEntityType { get { return "\r\n Inherits Global.Microsoft.OData.Client.BaseEntityType"; } } + internal override string OverloadsModifier { get { return "Overloads "; } } + internal override string ODataVersion { get { return "Global.Microsoft.OData.ODataVersion.V4"; } } + internal override string ParameterDeclarationTemplate { get { return "{1} As {0}"; } } + internal override string DictionaryItemConstructor { get { return "{{ {0}, {1} }}"; } } + internal override HashSet LanguageKeywords { get { + if (VBKeywords == null) + { + VBKeywords = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte", "ByVal", + "Call", "Case", "Catch", "CBool", "", "CByte", "CChar", "CDate", "CDbl", "CDec", "Char", + "CInt", "Class", "CLng", "CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", + "CType", "CUInt", "CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", + "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", + "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", "GetType", + "GetXMLNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements", "Imports", "In", "Inherits", + "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like", "Long", "Loop", "Me", + "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", "Namespace", "Narrowing", "New", "Next", + "Not", "Nothing", "NotInheritable", "NotOverridable", "Object", "Of", "On", "Operator", "Option", "Optional", + "Or", "OrElse", "Out", "Overloads", "Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", + "Protected", "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", "SByte", + "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", "String", + "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast", "TypeOf", + "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While", "Widening", "With", + "WithEvents", "WriteOnly", "Xor" + }; + } + return VBKeywords; + } } + private HashSet VBKeywords; + + internal override void WriteFileHeader() + { +#>'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:<#= Environment.Version #> +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict Off +Option Explicit On + + +'Generation date: <#= DateTime.Now.ToString(System.Globalization.CultureInfo.CurrentCulture) #> +<#+ + } + + internal override void WriteNamespaceStart(string fullNamespace) + { +#> +Namespace <#= fullNamespace #> +<#+ + } + + internal override void WriteClassStartForEntityContainer(string originalContainerName, string containerName, string fixedContainerName) + { +#> + ''' + '''There are no comments for <#= containerName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Partial Public Class <#= fixedContainerName #> + Inherits Global.Microsoft.OData.Client.DataServiceContext +<#+ + } + + internal override void WriteMethodStartForEntityContainerConstructor(string containerName, string fixedContainerName) + { +#> + ''' + '''Initialize a new <#= containerName #> object. + ''' + ")> _ + Public Sub New(ByVal serviceRoot As Global.System.Uri) + MyBase.New(serviceRoot, Global.Microsoft.OData.Client.ODataProtocolVersion.V4) +<#+ + } + + internal override void WriteKeyAsSegmentUrlConvention() + { +#> + Me.UrlKeyDelimiter = Global.Microsoft.OData.Client.DataServiceUrlKeyDelimiter.Slash +<#+ + } + + internal override void WriteInitializeResolveName() + { +#> + Me.ResolveName = AddressOf Me.ResolveNameFromType +<#+ + } + + internal override void WriteInitializeResolveType() + { +#> + Me.ResolveType = AddressOf Me.ResolveTypeFromName +<#+ + } + + internal override void WriteClassEndForEntityContainerConstructor() + { +#> + Me.OnContextCreated + Me.Format.LoadServiceModel = AddressOf GeneratedEdmModel.GetInstance + Me.Format.UseJson() + End Sub + Partial Private Sub OnContextCreated() + End Sub +<#+ + } + + internal override void WriteMethodStartForResolveTypeFromName() + { +#> + ''' + '''Since the namespace configured for this service reference + '''in Visual Studio is different from the one indicated in the + '''server schema, use type-mappers to map between the two. + ''' + ")> _ + Protected Function ResolveTypeFromName(ByVal typeName As String) As Global.System.Type +<#+ + } + + internal override void WriteResolveNamespace(string typeName, string fullNamespace, string languageDependentNamespace) + { + if (!string.IsNullOrEmpty(typeName)) + { +#> + Dim resolvedType As <#= typeName #>= Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) +<#+ + } + else + { +#> + resolvedType = Me.DefaultResolveType(typeName, "<#= fullNamespace #>", String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>")) +<#+ + } +#> + If (Not (resolvedType) Is Nothing) Then + Return resolvedType + End If +<#+ + } + + internal override void WriteMethodEndForResolveTypeFromName() + { +#> + Return Nothing + End Function +<#+ + } + + internal override void WritePropertyRootNamespace(string containerName, string fullNamespace) + { +#> + ")> _ + Private Shared ROOTNAMESPACE As String = GetType(<#= containerName #>).Namespace.Remove(GetType(<#= containerName #>).Namespace.LastIndexOf("<#= fullNamespace #>")) +<#+ + } + + internal override void WriteMethodStartForResolveNameFromType(string containerName, string fullNamespace) + { +#> + ''' + '''Since the namespace configured for this service reference + '''in Visual Studio is different from the one indicated in the + '''server schema, use type-mappers to map between the two. + ''' + ")> _ + Protected Function ResolveNameFromType(ByVal clientType As Global.System.Type) As String +<#+ + if (this.context.EnableNamingAlias) + { +#> + Dim originalNameAttribute As Global.Microsoft.OData.Client.OriginalNameAttribute = + CType(Global.System.Linq.Enumerable.SingleOrDefault(Global.Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, GetType(Global.Microsoft.OData.Client.OriginalNameAttribute), true)), Global.Microsoft.OData.Client.OriginalNameAttribute) +<#+ + } + } + + internal override void WriteResolveType(string fullNamespace, string languageDependentNamespace) + { +#> + If clientType.Namespace.Equals(String.Concat(ROOTNAMESPACE, "<#= languageDependentNamespace #>"), Global.System.StringComparison.OrdinalIgnoreCase) Then +<#+ + if (this.context.EnableNamingAlias) + { +#> + If (Not (originalNameAttribute) Is Nothing) Then + Return String.Concat("<#= fullNamespace #>.", originalNameAttribute.OriginalName) + End If +<#+ + } +#> + Return String.Concat("<#= fullNamespace #>.", clientType.Name) + End If +<#+ + } + + internal override void WriteMethodEndForResolveNameFromType(bool modelHasInheritance) + { + if (this.context.EnableNamingAlias && modelHasInheritance) + { +#> + If (Not (originalNameAttribute) Is Nothing) Then + Dim fullName As String = clientType.FullName.Substring(ROOTNAMESPACE.Length) + Return fullName.Remove(fullName.LastIndexOf(clientType.Name)) + originalNameAttribute.OriginalName + End If +<#+ + } +#> + Return <#= modelHasInheritance ? "clientType.FullName.Substring(ROOTNAMESPACE.Length)" : "Nothing" #> + End Function +<#+ + } + + internal override void WriteConstructorForSingleType(string singleTypeName, string baseTypeName) + { +#> + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String) + MyBase.New(context, path) + End Sub + + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal context As Global.Microsoft.OData.Client.DataServiceContext, ByVal path As String, ByVal isComposable As Boolean) + MyBase.New(context, path, isComposable) + End Sub + + ''' + ''' Initialize a new <#= singleTypeName #> object. + ''' + Public Sub New(ByVal query As <#= baseTypeName #>) + MyBase.New(query) + End Sub +<#+ + } + + internal override void WriteContextEntitySetProperty(string entitySetName, string entitySetFixedName, string originalEntitySetName, string entitySetElementTypeName, bool inContext) + { +#> + ''' + '''There are no comments for <#= entitySetName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public ReadOnly Property <#= entitySetFixedName #>() As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) + Get +<#+ + if (!inContext) + { +#> + If Not Me.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If +<#+ + } +#> + If (Me._<#= entitySetName #> Is Nothing) Then + Me._<#= entitySetName #> = <#= inContext ? "MyBase" : "Context"#>.CreateQuery(Of <#= entitySetElementTypeName #>)(<#= inContext ? "\"" + originalEntitySetName + "\"" : "GetPath(\"" + originalEntitySetName + "\")" #>) + End If + Return Me._<#= entitySetName #> + End Get + End Property + ")> _ + Private _<#= entitySetName #> As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entitySetElementTypeName #>) +<#+ + } + + internal override void WriteContextSingletonProperty(string singletonName, string singletonFixedName, string originalSingletonName, string singletonElementTypeName, bool inContext) + { +#> + ''' + '''There are no comments for <#= singletonName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public ReadOnly Property <#= singletonFixedName #>() As <#= singletonElementTypeName #> + Get +<#+ + if (!inContext) + { +#> + If Not Me.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If +<#+ + } +#> + If (Me._<#= singletonName #> Is Nothing) Then + Me._<#= singletonName #> = New <#= singletonElementTypeName #>(<#= inContext ? "Me" : "Me.Context" #>, <#= inContext ? "\"" + originalSingletonName + "\"" : "GetPath(\"" + originalSingletonName + "\")" #>) + End If + Return Me._<#= singletonName #> + End Get + End Property + ")> _ + Private _<#= singletonName #> As <#= singletonElementTypeName #> +<#+ + } + + internal override void WriteContextAddToEntitySetMethod(string entitySetName, string originalEntitySetName, string typeName, string parameterName) + { +#> + ''' + '''There are no comments for <#= entitySetName #> in the schema. + ''' + ")> _ + Public Sub AddTo<#= entitySetName #>(ByVal <#= parameterName #> As <#= typeName #>) + MyBase.AddObject("<#= originalEntitySetName #>", <#= parameterName #>) + End Sub +<#+ + } + + internal override void WriteGeneratedEdmModel(string escapedEdmxString) + { + escapedEdmxString = escapedEdmxString.Replace("\r\n", "\" & _\r\n \""); +#> + ")> _ + Private MustInherit Class GeneratedEdmModel +<#+ + if (this.context.ReferencesMap != null) + { +#> + ")> _ + Private Shared ReferencesMap As Global.System.Collections.Generic.Dictionary(Of String, String) = New Global.System.Collections.Generic.Dictionary(Of String, String) From + { +<#+ + int count = this.context.ReferencesMap.Count(); + foreach(var reference in this.context.ReferencesMap) + { +#> + {"<#= reference.Key.OriginalString.Replace("\"", "\"\"") #>", "<#= Utils.SerializeToString(reference.Value).Replace("\"", "\"\"").Replace("\r\n", "\" & _\r\n \"") #>"}<#= (--count>0?",":"")#> +<#+ + } +#> + } +<#+ + } +#> + ")> _ + Private Shared ParsedModel As Global.Microsoft.OData.Edm.IEdmModel = LoadModelFromString + ")> _ + Private Const Edmx As String = "<#= escapedEdmxString #>" + ")> _ + Public Shared Function GetInstance() As Global.Microsoft.OData.Edm.IEdmModel + Return ParsedModel + End Function +<#+ + if (this.context.ReferencesMap != null) + { +#> + ")> _ + Private Shared Function getReferencedModelFromMap(ByVal uri As Global.System.Uri) As Global.System.Xml.XmlReader + Dim referencedEdmx As String = Nothing + If (ReferencesMap.TryGetValue(uri.OriginalString, referencedEdmx)) Then + Return CreateXmlReader(referencedEdmx) + End If + Return Nothing + End Function + ")> _ + Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel + Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) + Try + Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader, AddressOf getReferencedModelFromMap) + Finally + CType(reader,Global.System.IDisposable).Dispose + End Try + End Function +<#+ + } + else + { +#> + ")> _ + Private Shared Function LoadModelFromString() As Global.Microsoft.OData.Edm.IEdmModel + Dim reader As Global.System.Xml.XmlReader = CreateXmlReader(Edmx) + Try + Return Global.Microsoft.OData.Edm.Csdl.CsdlReader.Parse(reader) + Finally + CType(reader,Global.System.IDisposable).Dispose + End Try + End Function +<#+ + } +#> + ")> _ + Private Shared Function CreateXmlReader(ByVal edmxToParse As String) As Global.System.Xml.XmlReader + Return Global.System.Xml.XmlReader.Create(New Global.System.IO.StringReader(edmxToParse)) + End Function + End Class +<#+ + } + + internal override void WriteClassEndForEntityContainer() + { +#> + End Class +<#+ + } + + internal override void WriteSummaryCommentForStructuredType(string typeName) + { +#> + ''' + '''There are no comments for <#= typeName #> in the schema. + ''' +<#+ + } + + internal override void WriteKeyPropertiesCommentAndAttribute(IEnumerable keyProperties, string keyString) + { +#> + ''' +<#+ + foreach (string key in keyProperties) + { +#> + '''<#= key #> +<#+ + } +#> + ''' + ")> _ +<#+ + } + + internal override void WriteEntityTypeAttribute() + { +#> + _ +<#+ + } + + internal override void WriteEntitySetAttribute(string entitySetName) + { +#> + ")> _ +<#+ + } + + internal override void WriteEntityHasStreamAttribute() + { +#> + _ +<#+ + } + + internal override void WriteClassStartForStructuredType(string abstractModifier, string typeName, string originalTypeName, string baseTypeName) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Partial Public<#= abstractModifier #> Class <#= typeName #><#= baseTypeName #> +<#+ + } + + internal override void WriteSummaryCommentForStaticCreateMethod(string typeName) + { +#> + ''' + '''Create a new <#= typeName #> object. + ''' +<#+ + } + + internal override void WriteParameterCommentForStaticCreateMethod(string parameterName, string propertyName) + { +#> + '''Initial value of <#= propertyName #>. +<#+ + } + + internal override void WriteDeclarationStartForStaticCreateMethod(string typeName, string fixedTypeName) + { +#> + ")> _ + Public Shared Function Create<#= typeName #>(<#+ + + } + + internal override void WriteParameterForStaticCreateMethod(string parameterTypeName, string parameterName, string parameterSeparater) + { +#>ByVal <#= parameterName #> As <#= parameterTypeName #><#= parameterSeparater #><#+ + } + + internal override void WriteDeclarationEndForStaticCreateMethod(string typeName, string instanceName) + { + #>) As <#= typeName #> + Dim <#= instanceName #> As <#= typeName #> = New <#= typeName #>() +<#+ + } + + internal override void WriteParameterNullCheckForStaticCreateMethod(string parameterName) + { +#> + If (<#= parameterName #> Is Nothing) Then + Throw New Global.System.ArgumentNullException("<#= parameterName #>") + End If +<#+ + } + + internal override void WritePropertyValueAssignmentForStaticCreateMethod(string instanceName, string propertyName, string parameterName) + { +#> + <#= instanceName #>.<#= propertyName #> = <#= parameterName #> +<#+ + } + + internal override void WriteMethodEndForStaticCreateMethod(string instanceName) + { +#> + Return <#= instanceName #> + End Function +<#+ + } + + internal override void WritePropertyForStructuredType(string propertyType, string originalPropertyName, string propertyName, string fixedPropertyName, string privatePropertyName, string propertyInitializationValue, bool writeOnPropertyChanged) + { +#> + ''' + '''There are no comments for Property <#= propertyName #> in the schema. + ''' + ")> _ +<#+ + if (this.context.EnableNamingAlias || IdentifierMappings.ContainsKey(originalPropertyName)) + { +#> + ")> _ +<#+ + } +#> + Public Property <#= fixedPropertyName #>() As <#= propertyType #> + Get + Return Me.<#= privatePropertyName #> + End Get + Set + Me.On<#= propertyName #>Changing(value) + Me.<#= privatePropertyName #> = value + Me.On<#= propertyName #>Changed +<#+ + if (writeOnPropertyChanged) + { +#> + Me.OnPropertyChanged("<#= originalPropertyName #>") +<#+ + } +#> + End Set + End Property + ")> _ +<#+ + string constructorString = string.Empty; + if (!string.IsNullOrEmpty(propertyInitializationValue)) + { + constructorString = " = " + propertyInitializationValue; + } +#> + Private <#= privatePropertyName #> As <#= propertyType #><#= constructorString #> + Partial Private Sub On<#= propertyName #>Changing(ByVal value As <#= propertyType #>) + End Sub + Partial Private Sub On<#= propertyName #>Changed() + End Sub +<#+ + } + + internal override void WriteINotifyPropertyChangedImplementation() + { +#> + ''' + ''' This event is raised when the value of the property is changed + ''' + ")> _ + Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements Global.System.ComponentModel.INotifyPropertyChanged.PropertyChanged + ''' + ''' The value of the property is changed + ''' + ''' property name + ")> _ + Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) + If (Not (Me.PropertyChangedEvent) Is Nothing) Then + RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property])) + End If + End Sub +<#+ + } + + internal override void WriteClassEndForStructuredType() + { +#> + End Class +<#+ + } + + internal override void WriteEnumFlags() + { +#> + +<#+ + } + + internal override void WriteSummaryCommentForEnumType(string enumName) + { +#> + ''' + '''There are no comments for <#= enumName #> in the schema. + ''' +<#+ + } + + internal override void WriteEnumDeclaration(string enumName, string originalEnumName, string underlyingType) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Enum <#= enumName #><#= underlyingType #> +<#+ + } + + internal override void WriteMemberForEnumType(string member, string originalMemberName, bool last) + { + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + <#= member #> +<#+ + } + + internal override void WriteEnumEnd() + { +#> + End Enum +<#+ + } + + internal override void WriteFunctionImportReturnCollectionResult(string functionName, string originalFunctionName, string returnTypeName, string parameters, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + Return Me.CreateFunctionQuery(Of <#= returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #> <#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteFunctionImportReturnSingleResult(string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("", "/<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnCollectionResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + Dim requestUri As Global.System.Uri = Nothing + Context.TryGetUri(Me, requestUri) + Return Me.Context.CreateFunctionQuery(Of <#= returnTypeName #>)("", String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))) + "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundFunctionInEntityTypeReturnSingleResult(bool hideBaseMethod, string functionName, string originalFunctionName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= functionName #>(<#= parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + Dim requestUri As Global.System.Uri = Nothing + Context.TryGetUri(Me, requestUri) + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>Me.Context.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)(String.Join("/", Global.System.Linq.Enumerable.Select(Global.System.Linq.Enumerable.Skip(requestUri.Segments, Me.Context.BaseUri.Segments.Length), Function(s) s.Trim("/"C))), "/<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteActionImport(string actionName, string originalActionName, string returnTypeName, string parameters, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> + Return New <#= returnTypeName #>(Me, Me.BaseUri.OriginalString.Trim("/"C) + "/<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundActionInEntityType(bool hideBaseMethod, string actionName, string originalActionName, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public <#= hideBaseMethod ? this.OverloadsModifier : string.Empty #>Function <#= actionName #>(<#= parameters #>) As <#= returnTypeName #> + Dim resource As Global.Microsoft.OData.Client.EntityDescriptor = Context.EntityTracker.TryGetEntityDescriptor(Me) + If resource Is Nothing Then + Throw New Global.System.Exception("cannot find entity") + End If + + Return New <#= returnTypeName #>(Me.Context, resource.EditLink.OriginalString.Trim("/"C) + "/<#= fullNamespace #>.<#= originalActionName #>"<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteExtensionMethodsStart() + { +#> + ''' + ''' Class containing all extension methods + ''' + Public Module ExtensionMethods +<#+ + } + + internal override void WriteExtensionMethodsEnd() + { +#> + End Module +<#+ + } + + internal override void WriteByKeyMethods(string entityTypeName, string returnTypeName, IEnumerable keys, string keyParameters, string keyDictionaryItems) + { +#> + ''' + ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + ''' + ''' source entity set + ''' dictionary with the names and values of keys + + Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), ByVal keys As Global.System.Collections.Generic.Dictionary(Of String, Object)) As <#= returnTypeName #> + Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) + End Function + ''' + ''' Get an entity of type <#= entityTypeName #> as <#= returnTypeName #> specified by key from an entity set + ''' + ''' source entity set +<#+ + foreach (var key in keys) + { +#> + ''' The value of <#= key #> +<#+ + } +#> + + Public Function ByKey(ByVal source As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= entityTypeName #>), + <#= keyParameters #>) As <#= returnTypeName #> + Dim keys As Global.System.Collections.Generic.Dictionary(Of String, Object) = New Global.System.Collections.Generic.Dictionary(Of String, Object)() From + { + <#= keyDictionaryItems #> + } + Return New <#= returnTypeName #>(source.Context, source.GetKeyPath(Global.Microsoft.OData.Client.Serializer.GetKeyString(source.Context, keys))) + End Function +<#+ + } + + internal override void WriteCastToMethods(string baseTypeName, string derivedTypeName, string derivedTypeFullName, string returnTypeName) + { +#> + ''' + ''' Cast an entity of type <#= baseTypeName #> to its derived type <#= derivedTypeFullName #> + ''' + ''' source entity + + Public Function CastTo<#= derivedTypeName #>(ByVal source As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= baseTypeName #>)) As <#= returnTypeName #> + Dim query As Global.Microsoft.OData.Client.DataServiceQuerySingle(Of <#= derivedTypeFullName #>) = source.CastTo(Of <#= derivedTypeFullName #>)() + Return New <#= returnTypeName #>(source.Context, query.GetPath(Nothing)) + End Function +<#+ + } + + internal override void WriteBoundFunctionReturnSingleResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string returnTypeNameWithSingleSuffix, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool isReturnEntity, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As <#= isReturnEntity ? returnTypeNameWithSingleSuffix : string.Format(this.DataServiceQuerySingleStructureTemplate, returnTypeName) #> + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + + Return <#= isReturnEntity ? "New " + returnTypeNameWithSingleSuffix + "(" : string.Empty #>source.CreateFunctionQuerySingle(<#= "Of " + returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>)<#= isReturnEntity ? ")" : string.Empty #> + End Function +<#+ + } + + internal override void WriteBoundFunctionReturnCollectionResultAsExtension(string functionName, string originalFunctionName, string boundTypeName, string returnTypeName, string parameters, string fullNamespace, string parameterValues, bool isComposable, bool useEntityReference) + { +#> + ''' + ''' There are no comments for <#= functionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= functionName #>(ByVal source As <#= boundTypeName #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #><#= useEntityReference ? ", Optional ByVal useEntityReference As Boolean = False" : string.Empty #>) As Global.Microsoft.OData.Client.DataServiceQuery(Of <#= returnTypeName #>) + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + + Return source.CreateFunctionQuery(Of <#= returnTypeName #>)("<#= fullNamespace #>.<#= originalFunctionName #>", <#= isComposable #><#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteBoundActionAsExtension(string actionName, string originalActionName, string boundSourceType, string returnTypeName, string parameters, string fullNamespace, string parameterValues) + { +#> + ''' + ''' There are no comments for <#= actionName #> in the schema. + ''' + +<#+ + if (this.context.EnableNamingAlias) + { +#> + ")> _ +<#+ + } +#> + Public Function <#= actionName #>(ByVal source As <#= boundSourceType #><#= string.IsNullOrEmpty(parameters) ? string.Empty : ", " + parameters #>) As <#= returnTypeName #> + If Not source.IsComposable Then + Throw New Global.System.NotSupportedException("The previous function is not composable.") + End If + Return New <#= returnTypeName #>(source.Context, source.AppendRequestUri("<#= fullNamespace #>.<#= originalActionName #>")<#= string.IsNullOrEmpty(parameterValues) ? string.Empty : ", " + parameterValues #>) + End Function +<#+ + } + + internal override void WriteNamespaceEnd() + { +#> +End Namespace +<#+ + } +} #> \ No newline at end of file