예제 #1
0
        public static void PopulateFrom(this PartialSchema partialSchema, Schema schema)
        {
            if (schema == null) return;

            partialSchema.type = schema.type;
            partialSchema.format = schema.format;

            if (schema.items != null)
            {
                // TODO: Handle jagged primitive array and error on jagged object array
                partialSchema.items = new PartialSchema();
                partialSchema.items.PopulateFrom(schema.items);
            }

            partialSchema.@default = schema.@default;
            partialSchema.maximum = schema.maximum;
            partialSchema.exclusiveMaximum = schema.exclusiveMaximum;
            partialSchema.minimum = schema.minimum;
            partialSchema.exclusiveMinimum = schema.exclusiveMinimum;
            partialSchema.maxLength = schema.maxLength;
            partialSchema.minLength = schema.minLength;
            partialSchema.pattern = schema.pattern;
            partialSchema.maxItems = schema.maxItems;
            partialSchema.minItems = schema.minItems;
            partialSchema.uniqueItems = schema.uniqueItems;
            partialSchema.@enum = schema.@enum;
            partialSchema.multipleOf = schema.multipleOf;
        }
예제 #2
0
 public void Apply(Schema model, ModelFilterContext context)
 {
     model.Default = new
     {
         Id = "myCartId"
     };
 }
        private static void FixSchemaReference(SchemaRegistry registry, Schema schema, Type referencedType)
        {
            Contract.Requires(schema.@ref != null);

            var schemaIdSelector = registry.GetInstanceField<Func<Type, string>>("_schemaIdSelector", true);

            schema.@ref = "#/definitions/" + schemaIdSelector(referencedType);
        }
예제 #4
0
        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            if (schema == null || schema.properties == null || type == null) return;

            bool isPushTrigger = type.AssemblyQualifiedNameNoTypeParams() == typeof(TriggerInput<string, string>).AssemblyQualifiedNameNoTypeParams();

            foreach (var propertyName in schema.properties.Keys)
            {
                var property = schema.properties[propertyName];

                if (isPushTrigger && propertyName == Constants.CALLBACK_URL_PROPERTY_NAME)
                {
                    #region Apply callback magic defaults

                    // Apply trigger magic defaults:
                    // "x-ms-scheduler-recommendation": "@accessKeys('default').primary.secretRunUri
                    schema.SetChildPropertyRequired(Constants.CALLBACK_URL_PROPERTY_NAME);

                    property.SetVisibility(VisibilityType.Internal);
                    property.SetSchedulerRecommendation(Constants.CALLBACK_URL_MAGIC_DEFAULT);

                    // This is what this will look like (pulled from HTTP Listener API Definition)
                    //
                    // "TriggerInput[TriggerPushParameters,TriggerOutputParameters]": {
                    //     "required": [            <-- SetChildPropertyRequired (on the parent model containing the callbackUrl property)
                    //       "callbackUrl"
                    // ],
                    // "type": "object",
                    // "properties": {
                    //   "callbackUrl": {            <-- SetSchedulerRecommendation (on the actual property)
                    //     "type": "string",
                    //     "x-ms-visibility": "internal",
                    //     "x-ms-scheduler-recommendation": "@accessKeys('default').primary.secretRunUri"
                    //   },

                    #endregion
                }

                // Apply friendly names and descriptions wherever possible
                // "x-ms-summary" - friendly name (applies to properties)
                // schema.properties["prop"].description - description (applies to parameters)

                var propertyInfo = type.GetRuntimeProperties().Where(p => p.Name == propertyName).FirstOrDefault();

                if (propertyInfo == null) return;

                var propertyMetadata = propertyInfo.GetCustomAttribute<MetadataAttribute>();

                if (propertyMetadata != null)
                {
                    property.SetVisibility(propertyMetadata.Visibility);
                    property.SetFriendlyNameAndDescription(propertyMetadata.FriendlyName, propertyMetadata.Description);
                }

            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="dataTypeRegistry"></param>
        /// <param name="type"></param>
        public void Apply(Schema model, SchemaRegistry dataTypeRegistry, Type type)
        {
            if (model != null && dataTypeRegistry != null && type != null)
            {
                var ignoredProperties = type.GetProperties().Where(p => p.GetCustomAttributes(typeof(JsonIgnoreAttribute), false).FirstOrDefault() != null);

                foreach (var property in ignoredProperties)
                {
                    model.properties.Remove(property.Name);
                }
            }
        }
예제 #6
0
        private void ApplyPropertyComments(Schema propertySchema, PropertyInfo propertyInfo)
        {
            if (propertyInfo == null) return;

            var commentId = XmlCommentsIdHelper.GetCommentIdForProperty(propertyInfo);
            var propertyNode = _navigator.SelectSingleNode(string.Format(MemberXPath, commentId));
            if (propertyNode == null) return;

            var propSummaryNode = propertyNode.SelectSingleNode(SummaryTag);
            if (propSummaryNode != null)
            {
                propertySchema.description = propSummaryNode.ExtractContent();
            }
        }
예제 #7
0
        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            if (type == typeof(GetLobbyResponse))
                schema.example = new GetLobbyResponse() { };

            if (type == typeof(GetByResponse))
                schema.example = new GetByResponse() { };

            if (type == typeof(UpdateLobbyRequest))
                schema.example = new UpdateLobbyRequest() { };

            if (type == typeof(ChangeStatusRequest))
                schema.example = new ChangeStatusRequest() { };
        }
        private void ApplyPropertyComments(Schema propertySchema, PropertyInfo propertyInfo)
        {
            if (propertyInfo == null) return;

            var propertyNode = _navigator.SelectSingleNode(
                String.Format(PropertyExpression, propertyInfo.DeclaringType.XmlLookupName(), propertyInfo.Name));
            if (propertyNode == null) return;

            var propSummaryNode = propertyNode.SelectSingleNode(SummaryExpression);
            if (propSummaryNode != null)
            {
                propertySchema.description = propSummaryNode.ExtractContent();
            }
        }
 /// <summary>
 /// Example of updating enum definitions, strip trailing "Internal" before generating swagger doc
 /// </summary>
 /// <param name="schema"></param>
 /// <param name="type"></param>
 private void UpdateEnumDefinitions(Schema schema, Type type)
 {
     foreach (var property in schema.properties)
     {
         if (property.Value.@enum != null)
         {
             var clrType = type.GetProperty(property.Key, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty).PropertyType;
             property.Value.vendorExtensions.Add("x-ms-enum", new
             {
                 name = clrType.Name.TrimEnd("Internal"),
                 modelAsString = bool.TrueString
             });
         }
     }
 }
 public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
 {
     var properties = type.GetProperties();
     foreach (var property in properties)
     {
         object[] attrs = property.GetCustomAttributes(true);
         foreach (object attr in attrs)
         {
             JsonIgnoreAttribute authAttr = attr as JsonIgnoreAttribute;
             if (authAttr != null)
             {
                 schema.properties.Remove(property.Name);
                 break;
             }
         }
     }
 }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="dataTypeRegistry"></param>
        /// <param name="type"></param>
        public void Apply(Schema model, SchemaRegistry dataTypeRegistry, Type type)
        {
            if (model != null && dataTypeRegistry != null && type != null && model.properties != null)
            {
                bool isPushTrigger = false;

                // not taking dependency on runtime dll to avoid circular dependencies betwwen saas and enterprise repo
                if (!string.IsNullOrEmpty(type.AssemblyQualifiedName) && type.AssemblyQualifiedName.StartsWith("Microsoft.Azure.AppService.ApiApps.Service.TriggerInput", StringComparison.InvariantCultureIgnoreCase))
                {
                    isPushTrigger = true;
                }

                foreach (string property in model.properties.Keys)
                {
                    Schema propSchema = model.properties[property];
                    propSchema.vendorExtensions = SetSummaryAndVisibility(type, property, propSchema.description, propSchema.vendorExtensions);

                    if (isPushTrigger && property.Equals("callbackurl", StringComparison.InvariantCultureIgnoreCase))
                    {
                        if (model.required == null)
                        {
                            model.required = new List<string>();
                        }

                        if (!model.required.Contains(property))
                        {
                            model.required.Add(property);
                        }

                        propSchema.vendorExtensions = SummaryAndVisibilityOperationFilter.SetVendorExtension(summary: null, visibility: Visibility.Internal, vendorExtensions: propSchema.vendorExtensions);
                        if (!propSchema.vendorExtensions.ContainsKey(SummaryAndVisibilityOperationFilter.triggerRecommendation))
                        {
                            propSchema.vendorExtensions.Add(SummaryAndVisibilityOperationFilter.triggerRecommendation, SummaryAndVisibilityOperationFilter.callbackRecommendationValue);
                        }
                    }
                }

                // in case of no properties inside the class or object, set the visibility/summary attributes on the class object.
                if (model.properties.Keys.Count == 0)
                {
                    model.vendorExtensions = SetSummaryAndVisibility(type, model.description, model.vendorExtensions);
                }
            }
        }
        private void ExtractAndAddQueryParams(
            Schema sourceSchema,
            string sourceQualifier,
            bool? sourceRequired,
            SchemaRegistry schemaRegistry,
            IList<Parameter> operationParams)
        {
            foreach (var entry in sourceSchema.properties)
            {
                var propertySchema = entry.Value;
                if (propertySchema.readOnly == true) continue;

                var required = (sourceRequired == true)
                    && sourceSchema.required != null && sourceSchema.required.Contains(entry.Key);

                if (propertySchema.@ref != null)
                {
                    var schema = schemaRegistry.Definitions[[email protected]("#/definitions/", "")];

                    ExtractAndAddQueryParams(
                        schema,
                        sourceQualifier + entry.Key.ToCamelCase() + ".",
                        required,
                        schemaRegistry,
                        operationParams);
                }
                else
                {
                    var param = new Parameter
                    {
                        name = sourceQualifier + entry.Key.ToCamelCase(),
                        @in = "query",
                        required = required,
                        description = entry.Value.description,
                        example = entry.Value.example
                    };

                    param.PopulateFrom(entry.Value);
                    if (param.type == "array")
                        param.collectionFormat = "multi";
                    operationParams.Add(param);
                }
            }
        }
        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            var validator = GetValidator(type);

            if (validator == null)
            {
                return;
            }

            schema.required = new List<string>();

            var validatorDescriptor = validator.CreateDescriptor();

            foreach (var key in schema.properties.Keys)
            {
                foreach (var propertyValidator in validatorDescriptor.GetValidatorsForMember(key))
                {
                    if (propertyValidator is NotEmptyValidator)
                    {
                        schema.required.Add(key);
                    }

                    if (propertyValidator is LengthValidator)
                    {
                        var lengthValidator = (LengthValidator) propertyValidator;
                        if (lengthValidator.Max > 0)
                        {
                            schema.properties[key].maxLength = lengthValidator.Max;
                        }

                        schema.properties[key].minLength = lengthValidator.Min;
                    }

                    if (propertyValidator is RegularExpressionValidator)
                    {
                        var regexExpressionValidator = (RegularExpressionValidator) propertyValidator;
                        schema.properties[key].pattern = regexExpressionValidator.Expression;
                    }
                }
                
            }
        }
예제 #14
0
        public void Apply(Schema model, ModelFilterContext context)
        {
            var commentId = XmlCommentsIdHelper.GetCommentIdForType(context.SystemType);
            var typeNode = _navigator.SelectSingleNode(string.Format(MemberXPath, commentId));

            if (typeNode != null)
            {
                var summaryNode = typeNode.SelectSingleNode(SummaryTag);
                if (summaryNode != null)
                    model.description = summaryNode.ExtractContent();
            }

            foreach (var entry in model.properties)
            {
                var jsonProperty = context.JsonObjectContract.Properties[entry.Key];
                if (jsonProperty == null) continue;

                ApplyPropertyComments(entry.Value, jsonProperty.PropertyInfo());
            }
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="schema"></param>
 /// <param name="schemaRegistry"></param>
 /// <param name="type"></param>
 public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
 {
     if (schema != null && schemaRegistry != null && type != null && schema.properties != null)
     {
         foreach (string property in schema.properties.Keys)
         {
             Schema propSchema = schema.properties[property];
             var newType = this.GetOverrideType(type, property);
             if (!string.IsNullOrEmpty(newType))
             {
                 // Only string, boolean and int data types are supported in OverideTypeAttribute. 
                 if (this.IsSupportedDataType(newType))
                 {
                     propSchema.@ref = null;
                     propSchema.type = newType;
                 }
             }
         }
     }
 }
예제 #16
0
        public void Apply(Schema model, ModelFilterContext context)
        {
            var typeNode = _navigator.SelectSingleNode(
                String.Format(TypeExpression, context.SystemType.XmlLookupName()));

            if (typeNode != null)
            {
                var summaryNode = this.GetSummaryNode(typeNode);
                if (summaryNode != null)
                    model.description = summaryNode.ExtractContent();
            }

            foreach (var entry in model.properties)
            {
                var jsonProperty = context.JsonObjectContract.Properties[entry.Key];
                if (jsonProperty == null) continue;

                ApplyPropertyComments(entry.Value, jsonProperty.PropertyInfo());
            }
        }
        public void SchemaFilter_SetsPropsToReadOnly()
        {
            // Arrange
            var filter = new MobileAppSchemaFilter();
            var schema = new Schema()
            {
                properties = new Dictionary<string, Schema>()
                {
                    { "ReadWrite", new Schema() },
                    { "ReadOnly", new Schema() }
                }
            };

            // Act
            filter.Apply(schema, null, typeof(TestType));

            // Assert
            Assert.Null(schema.properties["ReadWrite"].readOnly);
            Assert.True(schema.properties["ReadOnly"].readOnly);
        }
        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            var name = type.FullName;

            if (type.IsGenericType)
            {
                // example of handling a generic resource type
                //if (type.GetGenericTypeDefinition() == typeof(Resource<>))
                //{
                //    schema.vendorExtensions.Add("x-ms-azure-resource", true);
                //}
            }

            UpdateEnumDefinitions(schema, type);

            // filter some types out of the swagger doc
            //if (!(name.StartsWith("SwashApiTest.") || type == typeof(object)))
            //{
            //    schema.vendorExtensions.Add(SwaggerConstants.ToRemoveVendorExtension, "");
            //}
        }
        public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
        {
            if (schema == null)
            {
                throw new ArgumentNullException("schema");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            foreach (PropertyInfo prop in type.GetProperties())
            {
                foreach (var attr in prop.GetCustomAttributes(true))
                {
                    if (typeof(DatabaseGeneratedAttribute).IsAssignableFrom(attr.GetType()))
                    {
                        schema.properties[prop.Name].readOnly = true;
                    }
                }
            }
        }
        private void ExtractAndAddQueryParams(
            Schema sourceSchema,
            string sourceQualifier,
            bool sourceRequired,
            SchemaRegistry schemaRegistry,
            IList<Parameter> operationParams)
        {
            foreach (var entry in sourceSchema.properties)
            {
                var propertySchema = entry.Value;
                var required = sourceRequired
                    && sourceSchema.required != null && sourceSchema.required.Contains(entry.Key); 

                if (propertySchema.@ref != null)
                {
                    var schema = schemaRegistry.Definitions[[email protected]("#/definitions/", "")];
                    ExtractAndAddQueryParams(
                        schema,
                        sourceQualifier + entry.Key.ToLowerInvariant() + ".",
                        required,
                        schemaRegistry,
                        operationParams);
                }
                else
                {
                    var param = new Parameter
                    {
                        name =  sourceQualifier + entry.Key.ToLowerInvariant(),
                        @in = "query",
                        required = required,
                        description = entry.Value.description
                    };
                    param.PopulateFrom(entry.Value);
                    operationParams.Add(param);
                }
            }
        }
        private static void RegisterReferencedTypes(SchemaRegistry registry, IEdmModel edmModel, Schema schema)
        {
            Contract.Requires(registry != null);
            Contract.Requires(schema != null);

            while (true)
            {
                Contract.Assume(schema != null);

                var referencedType = schema.GetReferencedType();

                if (referencedType != null)
                {
                    registry.GetOrRegister(referencedType);
                    FixSchemaReference(registry, schema, referencedType);
                    ApplyEdmModelPropertyNamesToSchema(registry, edmModel, referencedType);
                    return;
                }

                if (schema.properties != null && schema.properties.Any())
                {
                    foreach (var property in schema.properties)
                    {
                        RegisterReferencedTypes(registry, edmModel, property.Value);
                    }
                    return;
                }

                if (schema.items != null)
                {
                    schema = schema.items;
                    continue;
                }
                break;
            }
        }
예제 #22
0
 public void Apply(Schema model, ModelFilterContext context)
 {
     model.Extensions.Add("X-property1", "value");
 }
예제 #23
0
        private Schema CreateObjectSchema(JsonObjectContract jsonContract)
        {
            var properties = jsonContract.Properties
                .Where(p => !p.Ignored)
                .Where(p => !(_ignoreObsoleteProperties && p.IsObsolete()))
                .ToDictionary(
                    prop => prop.PropertyName,
                    prop => CreateInlineSchema(prop.PropertyType).WithValidationProperties(prop)
                );

            var required = jsonContract.Properties.Where(prop => prop.IsRequired())
                .Select(propInfo => propInfo.PropertyName)
                .ToList();

            var schema = new Schema
            {
                required = required.Any() ? required : null, // required can be null but not empty
                properties = properties,
                type = "object"
            };

            foreach (var filter in _schemaFilters)
            {
                filter.Apply(schema, this, jsonContract.UnderlyingType);
            }

            // NOTE: In next major version, _modelFilters will completely replace _schemaFilters
            var modelFilterContext = new ModelFilterContext(jsonContract.UnderlyingType, jsonContract, this);
            foreach (var filter in _modelFilters)
            {
                filter.Apply(schema, modelFilterContext);
            }

            return schema;
        }
 public void Apply(Schema schema, SchemaRegistry schemaRegistry, Type type)
 {
     schema.vendorExtensions.Add("x-schema", "bar");
 }
예제 #25
0
 /// <summary>
 /// Called when generating the schema
 /// </summary>
 public void Apply(Schema model, ModelFilterContext context)
 {
     foreach (var dtProp in model.Properties.Where(x => x.Value.Format == "date-time"))
         dtProp.Value.Format = "date";
 }
예제 #26
0
        internal static IDictionary<string, Schema> GenerateSwaggerDefinitionsForEntities(
            IEnumerable<ArticleType> templateTypes)
        {
            var definitions = new Dictionary<string, Schema>();
            var entityProperties = new Dictionary<string, Schema>
            {
                ["id"] = new Schema
                {
                    type = "string",
                    description = "unique identifier for the entity",
                },
                ["parentid"] = new Schema
                {
                    type = "string",
                    description = "unique identifier for the parent entity",
                },
                ["name"] = new Schema
                {
                    type = "string",
                    description = "name of the entity",
                }
            };

            var articleRequired = new List<string>
            {
                "id",
                "parentid",
                "name"
            };

            var knownEntities = templateTypes
                .SelectMany(t => t.Fields)
                .Where(f => !f.Name.StartsWith("a_"))
                .Where(f => !string.IsNullOrWhiteSpace(f.Entity?.Type))
                .Select(f => f.Entity.Type)
                .Distinct()
                .ToList();

            foreach (var entity in knownEntities)
            {
                var schema = new Schema
                {
                    type = "object",
                    required = articleRequired,
                    properties = entityProperties
                };
                var type = entity;

                definitions.Add($"{type}", schema);

                var resultSchema = new Schema
                {
                    type = "object",
                    properties = new Dictionary<string, Schema>
                    {
                        ["results"] = new Schema {type = "array", items = new Schema {@ref = type}}
                    }
                };
                definitions.Add($"ResultOf{type}", resultSchema);
            }

            return definitions;
        }
예제 #27
0
 public void Apply(Schema schema, SchemaRegistry schemaRegistry, System.Type type)
 {
     SchemaHelper.Apply(schema, schemaRegistry, type);
 }
예제 #28
0
        public static void Apply(Schema schema, SchemaRegistry schemaRegistry, System.Type type)
        {
            var workStr = type.ToString();

            if (type.IsEnum)
            {
                EnumRegist(schemaRegistry, type);
            }
            if (IsNullableEnumType(type))
            {
                var innerType = type.GetGenericArguments()[0];
                EnumRegist(schemaRegistry, innerType);
            }

            if (schema.type == "array")
            {
                if (type.IsArray)
                {
                    Apply(schema.items, schemaRegistry, type.GetElementType());
                }
                else
                {
                    Apply(schema.items, schemaRegistry, type.GetGenericArguments()[0]);
                }
                return;
            }

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                schema.vendorExtensions.Add("CsType", type.GetGenericArguments()[0].Name + "?");
                schema.vendorExtensions.Add("CsNamespace", type.Namespace);

            }
            else
            {
                schema.vendorExtensions.Add("CsType", type.Name);
                schema.vendorExtensions.Add("CsNamespace", type.Namespace);
            }

            if (schema.properties != null)
            {
                foreach (var prop in schema.properties)
                {
                    var pi = type.GetProperty(prop.Key);
                    if (pi != null)
                    {
                        Apply(prop.Value, schemaRegistry, pi.PropertyType);
                    }
                }
            }
        }
예제 #29
0
        internal static IDictionary<string, Schema> GenerateSwaggerDefinitionsForArticles(
            IEnumerable<ArticleType> templateTypes)
        {
            var definitions = new Dictionary<string, Schema>();
            var articleProperties = new Dictionary<string, Schema>
            {
                ["id"] = new Schema
                {
                    type = "string",
                    description = "unique identifier for the object",
                },
                ["parentid"] = new Schema
                {
                    type = "string",
                    description = "unique identifier for the parent object",
                },
                ["parenttype"] = new Schema
                {
                    type = "string",
                    description = "type of the parent object",
                }
            };

            var articleRequired = new List<string>
            {
                "id",
                "parentid",
                "parenttype"
            };

            foreach (var templateType in templateTypes)
            {
                var combinedProperties = articleProperties
                    .Concat(GenerateTypeProperties(templateType).OrderBy(pair => pair.Key))
                    .ToDictionary(pair => pair.Key, pair => pair.Value);

                var schema = new Schema
                {
                    type = "object",
                    required = articleRequired,
                    properties = combinedProperties
                };
                var type = templateType.Type;

                definitions.Add($"{type}", schema);

                var resultSchema = new Schema
                {
                    type = "object",
                    properties = new Dictionary<string, Schema>
                    {
                        ["results"] = new Schema {type = "array", items = new Schema {@ref = type}}
                    }
                };
                definitions.Add($"ResultOf{type}", resultSchema);
            }

            var multiReferenceSchema = new Schema
            {
                type = "object",
                required = new[] { "values", "type" },
                properties = new Dictionary<string, Schema>
                {
                    ["type"] = new Schema
                    {
                        type = "string",
                        description = "type of the reference"
                    },
                    ["values"] = new Schema
                    {
                        type = "array",
                        items = new Schema {type = "string", description = "The unique id of referenced objects"}
                    }
                }
            };

            var singleReferenceSchema = new Schema
            {
                type = "object",
                required = new[] {"values", "type"},
                properties = new Dictionary<string, Schema>
                {
                    ["type"] = new Schema
                    {
                        type = "string",
                        description = "type of the reference"
                    },
                    ["values"] = new Schema
                    {
                        type = "array",
                        maxItems = 1,
                        items = new Schema {type = "string", description = "The unique id of referenced objects"}
                    }
                }
            };

            definitions.Add("MultiReference", multiReferenceSchema);
            definitions.Add("SingleReference", singleReferenceSchema);

            return definitions;
        }
        public ODataActionParameterDescriptor(string parameterName, Type parameterType, bool isOptional, Schema schema, HttpParameterDescriptor reflectedHttpParameterDescriptor) : base(parameterName, parameterType, isOptional, reflectedHttpParameterDescriptor)
        {
            Contract.Requires(schema != null);

            Schema = schema;
        }