| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- /* 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.Reflection;
- namespace MongoDB.Bson.Serialization.Conventions
- {
- /// <summary>
- /// A convention that finds readable and writeable members and adds them to the class map.
- /// </summary>
- public class ReadWriteMemberFinderConvention : ConventionBase, IClassMapConvention
- {
- // private fields
- private readonly BindingFlags _bindingFlags;
- private readonly MemberTypes _memberTypes;
- // constructors
- /// <summary>
- /// Initializes a new instance of the <see cref="ReadWriteMemberFinderConvention" /> class.
- /// </summary>
- public ReadWriteMemberFinderConvention()
- : this(BindingFlags.Instance | BindingFlags.Public)
- { }
- /// <summary>
- /// Initializes a new instance of the <see cref="ReadWriteMemberFinderConvention" /> class.
- /// </summary>
- /// <param name="memberTypes">The member types.</param>
- public ReadWriteMemberFinderConvention(MemberTypes memberTypes)
- : this(memberTypes, BindingFlags.Instance | BindingFlags.Public)
- { }
- /// <summary>
- /// Initializes a new instance of the <see cref="ReadWriteMemberFinderConvention" /> class.
- /// </summary>
- /// <param name="bindingFlags">The binding flags.</param>
- public ReadWriteMemberFinderConvention(BindingFlags bindingFlags)
- : this(MemberTypes.Field | MemberTypes.Property, bindingFlags)
- { }
- /// <summary>
- /// Initializes a new instance of the <see cref="ReadWriteMemberFinderConvention" /> class.
- /// </summary>
- /// <param name="memberTypes">The member types.</param>
- /// <param name="bindingFlags">The binding flags.</param>
- public ReadWriteMemberFinderConvention(MemberTypes memberTypes, BindingFlags bindingFlags)
- {
- _memberTypes = memberTypes;
- _bindingFlags = bindingFlags | BindingFlags.DeclaredOnly;
- }
- // public methods
- /// <summary>
- /// Applies a modification to the class map.
- /// </summary>
- /// <param name="classMap">The class map.</param>
- public void Apply(BsonClassMap classMap)
- {
- // order is important for backwards compatibility and GetMembers changes the order of finding things.
- // hence, we'll check member types explicitly instead of letting GetMembers handle it.
- if ((_memberTypes & MemberTypes.Field) == MemberTypes.Field)
- {
- var fields = classMap.ClassType.GetTypeInfo().GetFields(_bindingFlags);
- foreach (var field in fields)
- {
- MapField(classMap, field);
- }
- }
- if ((_memberTypes & MemberTypes.Property) == MemberTypes.Property)
- {
- var properties = classMap.ClassType.GetTypeInfo().GetProperties(_bindingFlags);
- foreach (var property in properties)
- {
- MapProperty(classMap, property);
- }
- }
- }
- // private methods
- private void MapField(BsonClassMap classMap, FieldInfo fieldInfo)
- {
- if (fieldInfo.IsInitOnly || fieldInfo.IsLiteral)
- {
- // we can't write
- return;
- }
- classMap.MapMember(fieldInfo);
- }
- private void MapProperty(BsonClassMap classMap, PropertyInfo propertyInfo)
- {
- if (!propertyInfo.CanRead || !propertyInfo.CanWrite)
- {
- // only read and write properties are mapped
- return;
- }
- // skip indexers
- if (propertyInfo.GetIndexParameters().Length != 0)
- {
- return;
- }
- // skip overridden properties (they are already included by the base class)
- var getMethodInfo = propertyInfo.GetMethod;
- if (getMethodInfo.IsVirtual && getMethodInfo.GetBaseDefinition().DeclaringType != classMap.ClassType)
- {
- return;
- }
- classMap.MapMember(propertyInfo);
- }
- }
- }
|