/* 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.Reflection; namespace MongoDB.Bson.Serialization.Attributes { /// /// Specifies the type of the serializer to use for a class. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Property | AttributeTargets.Field)] public class BsonSerializerAttribute : Attribute, IBsonMemberMapAttribute { // private fields private Type _serializerType; // constructors /// /// Initializes a new instance of the BsonSerializerAttribute class. /// public BsonSerializerAttribute() { } /// /// Initializes a new instance of the BsonSerializerAttribute class. /// /// The type of the serializer to use for a class. public BsonSerializerAttribute(Type serializerType) { _serializerType = serializerType; } // public properties /// /// Gets or sets the type of the serializer to use for a class. /// public Type SerializerType { get { return _serializerType; } set { _serializerType = value; } } // public methods /// /// Applies a modification to the member map. /// /// The member map. public void Apply(BsonMemberMap memberMap) { var serializer = CreateSerializer(memberMap.MemberType); memberMap.SetSerializer(serializer); } /// /// Creates a serializer for a type based on the serializer type specified by the attribute. /// /// The type that a serializer should be created for. /// A serializer for the type. internal IBsonSerializer CreateSerializer(Type type) { var typeInfo = type.GetTypeInfo(); if (typeInfo.ContainsGenericParameters) { var message = "Cannot create a serializer because the type to serialize is an open generic type."; throw new InvalidOperationException(message); } var serializerTypeInfo = _serializerType.GetTypeInfo(); if (serializerTypeInfo.ContainsGenericParameters && !typeInfo.IsGenericType) { var message = "Cannot create a serializer because the serializer type is an open generic type and the type to serialize is not generic."; throw new InvalidOperationException(message); } if (serializerTypeInfo.ContainsGenericParameters) { var genericArguments = typeInfo.GetGenericArguments(); var closedSerializerType = _serializerType.MakeGenericType(genericArguments); return (IBsonSerializer)Activator.CreateInstance(closedSerializerType); } else { return (IBsonSerializer)Activator.CreateInstance(_serializerType); } } } }