/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace MongoDB.Bson.Serialization.Conventions { /// /// A convention that finds the extra elements member by name (and that is also of type or ). /// public class NamedExtraElementsMemberConvention : ConventionBase, IClassMapConvention { // private fields private readonly IEnumerable _names; private readonly MemberTypes _memberTypes; private readonly BindingFlags _bindingFlags; // constructors /// /// Initializes a new instance of the NamedExtraElementsMemberConvention class. /// /// The name of the extra elements member. public NamedExtraElementsMemberConvention(string name) : this(new [] { name }) { } /// /// Initializes a new instance of the class. /// /// The names. public NamedExtraElementsMemberConvention(IEnumerable names) : this(names, BindingFlags.Instance | BindingFlags.Public) { } /// /// Initializes a new instance of the class. /// /// The names. /// The member types. public NamedExtraElementsMemberConvention(IEnumerable names, MemberTypes memberTypes) : this(names, memberTypes, BindingFlags.Instance | BindingFlags.Public) { } /// /// Initializes a new instance of the class. /// /// The names. /// The binding flags. public NamedExtraElementsMemberConvention(IEnumerable names, BindingFlags bindingFlags) : this(names, MemberTypes.Field | MemberTypes.Property, bindingFlags) { } /// /// Initializes a new instance of the class. /// /// The names. /// The member types. /// The binding flags. /// public NamedExtraElementsMemberConvention(IEnumerable names, MemberTypes memberTypes, BindingFlags bindingFlags) { if (names == null) { throw new ArgumentNullException("names"); } _names = names; _memberTypes = memberTypes; _bindingFlags = bindingFlags | BindingFlags.DeclaredOnly; } // public methods /// /// Applies a modification to the class map. /// /// The class map. public void Apply(BsonClassMap classMap) { var classTypeInfo = classMap.ClassType.GetTypeInfo(); foreach (var name in _names) { var member = classTypeInfo.GetMember(name, _memberTypes, _bindingFlags).SingleOrDefault(); if (member != null) { Type memberType = null; var fieldInfo = member as FieldInfo; if (fieldInfo != null) { memberType = fieldInfo.FieldType; } else { var propertyInfo = member as PropertyInfo; if (propertyInfo != null) { memberType = propertyInfo.PropertyType; } } if (memberType != null && (memberType == typeof(BsonDocument) || typeof(IDictionary).GetTypeInfo().IsAssignableFrom(memberType))) { classMap.MapExtraElementsMember(member); return; } } } } } }