/// <summary>
        /// Initializes a new instance of the <see cref="TypeToRegister"/> class, specifying the origin types.
        /// </summary>
        /// <param name="type">The type to register.</param>
        /// <param name="recursiveOriginType">The type whose recursive processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> resulted in the creation of this <see cref="TypeToRegister"/>.</param>
        /// <param name="directOriginType">The type whose processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> directly resulted in the creation of this <see cref="TypeToRegister"/>.</param>
        /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
        /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
        protected TypeToRegister(
            Type type,
            Type recursiveOriginType,
            Type directOriginType,
            MemberTypesToInclude memberTypesToInclude,
            RelatedTypesToInclude relatedTypesToInclude)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (recursiveOriginType == null)
            {
                throw new ArgumentNullException(nameof(recursiveOriginType));
            }

            if (directOriginType == null)
            {
                throw new ArgumentNullException(nameof(directOriginType));
            }

            this.Type = type;
            this.RecursiveOriginType   = recursiveOriginType;
            this.DirectOriginType      = directOriginType;
            this.MemberTypesToInclude  = memberTypesToInclude;
            this.RelatedTypesToInclude = relatedTypesToInclude;
        }
示例#2
0
        /// <inheritdoc />
        protected sealed override TypeToRegister BuildTypeToRegisterForPostInitializationRegistration(
            Type type,
            Type recursiveOriginType,
            Type directOriginType,
            MemberTypesToInclude memberTypesToInclude,
            RelatedTypesToInclude relatedTypesToInclude)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (recursiveOriginType == null)
            {
                throw new ArgumentNullException(nameof(recursiveOriginType));
            }

            if (directOriginType == null)
            {
                throw new ArgumentNullException(nameof(directOriginType));
            }

            var genericTypeDefinition = type.GetGenericTypeDefinition();

            var genericTypeDefinitionTypeToRegister = (TypeToRegisterForPropertyBag)this.RegisteredTypeToRegistrationDetailsMap[genericTypeDefinition].TypeToRegister;

            var result = new TypeToRegisterForPropertyBag(type, recursiveOriginType, directOriginType, memberTypesToInclude, relatedTypesToInclude, genericTypeDefinitionTypeToRegister.StringSerializerBuilderFunc);

            return(result);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegister"/> class with a type that is it's own origin.
 /// </summary>
 /// <param name="type">The type to register.</param>
 /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
 protected TypeToRegister(
     Type type,
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude)
     : this(type, type, type, memberTypesToInclude, relatedTypesToInclude)
 {
 }
示例#4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegisterForPropertyBag{T}"/> class.
 /// </summary>
 /// <param name="memberTypesToInclude">Specifies which member types of <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="stringSerializerBuilderFunc">A func that builds the <see cref="IStringSerializeAndDeserialize"/>.</param>
 public TypeToRegisterForPropertyBag(
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude,
     Func <IStringSerializeAndDeserialize> stringSerializerBuilderFunc)
     : base(typeof(T), memberTypesToInclude, relatedTypesToInclude, stringSerializerBuilderFunc)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegisterForBson{T}"/> class.
 /// </summary>
 /// <param name="memberTypesToInclude">Specifies which member types of <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="bsonSerializerBuilder">Builds an<see cref="IBsonSerializer"/>.</param>
 /// <param name="propertyNameWhitelist">The names of the properties to constrain the registration to.</param>
 public TypeToRegisterForBson(
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude,
     BsonSerializerBuilder bsonSerializerBuilder,
     IReadOnlyCollection <string> propertyNameWhitelist)
     : base(typeof(T), memberTypesToInclude, relatedTypesToInclude, bsonSerializerBuilder, propertyNameWhitelist)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegisterForJson{T}"/> class.
 /// </summary>
 /// <param name="memberTypesToInclude">Specifies which member types of <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="jsonConverterBuilder">Builds a serializing and deserializing <see cref="JsonConverter"/>.</param>
 /// <param name="keyInDictionaryStringSerializer">The serializer to use when dictionaries are keyed on <typeparamref name="T"/> and the keys should be written-to/read-from a string.</param>
 public TypeToRegisterForJson(
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude,
     JsonConverterBuilder jsonConverterBuilder,
     IStringSerializeAndDeserialize keyInDictionaryStringSerializer)
     : base(typeof(T), memberTypesToInclude, relatedTypesToInclude, jsonConverterBuilder, keyInDictionaryStringSerializer)
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegisterForPropertyBag"/> class with a type that is it's own origin.
 /// </summary>
 /// <param name="type">The type to register.</param>
 /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
 /// <param name="stringSerializerBuilderFunc">A func that builds the <see cref="IStringSerializeAndDeserialize"/>.</param>
 public TypeToRegisterForPropertyBag(
     Type type,
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude,
     Func <IStringSerializeAndDeserialize> stringSerializerBuilderFunc)
     : this(type, type, type, memberTypesToInclude, relatedTypesToInclude, stringSerializerBuilderFunc)
 {
 }
示例#8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="TypeToRegisterForJson"/> class, specifying the origin types.
        /// </summary>
        /// <param name="type">The type to register.</param>
        /// <param name="recursiveOriginType">The type whose recursive processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> resulted in the creation of this <see cref="TypeToRegisterForJson"/>.</param>
        /// <param name="directOriginType">The type whose processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> directly resulted in the creation of this <see cref="TypeToRegisterForJson"/>.</param>
        /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
        /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
        /// <param name="jsonConverterBuilder">Builds a serializing and deserializing <see cref="JsonConverter"/>.</param>
        /// <param name="keyInDictionaryStringSerializer">The serializer to use when dictionaries are keyed on <paramref name="type"/> and the keys should be written-to/read-from a string.</param>
        public TypeToRegisterForJson(
            Type type,
            Type recursiveOriginType,
            Type directOriginType,
            MemberTypesToInclude memberTypesToInclude,
            RelatedTypesToInclude relatedTypesToInclude,
            JsonConverterBuilder jsonConverterBuilder,
            IStringSerializeAndDeserialize keyInDictionaryStringSerializer)
            : base(type, recursiveOriginType, directOriginType, memberTypesToInclude, relatedTypesToInclude)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (recursiveOriginType == null)
            {
                throw new ArgumentNullException(nameof(recursiveOriginType));
            }

            if (directOriginType == null)
            {
                throw new ArgumentNullException(nameof(directOriginType));
            }

            if (jsonConverterBuilder != null)
            {
                if (memberTypesToInclude != MemberTypesToInclude.None)
                {
                    throw new ArgumentException(Invariant($"{nameof(jsonConverterBuilder)} is specified, but {nameof(Serialization.MemberTypesToInclude)} is not {MemberTypesToInclude.None}."));
                }

                if (type.IsGenericTypeDefinition)
                {
                    throw new NotSupportedException(Invariant($"{nameof(jsonConverterBuilder)} is specified, but underlying type to register is an open generic."));
                }
            }

            if (keyInDictionaryStringSerializer != null)
            {
                if (type.IsGenericTypeDefinition)
                {
                    throw new NotSupportedException(Invariant($"{nameof(keyInDictionaryStringSerializer)} is specified, but underlying type to register is an open generic."));
                }
            }

            this.JsonConverterBuilder            = jsonConverterBuilder;
            this.KeyInDictionaryStringSerializer = keyInDictionaryStringSerializer;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TypeToRegisterForPropertyBag"/> class, specifying the origin types.
        /// </summary>
        /// <param name="type">The type to register.</param>
        /// <param name="recursiveOriginType">The type whose recursive processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> resulted in the creation of this <see cref="TypeToRegisterForPropertyBag"/>.</param>
        /// <param name="directOriginType">The type whose processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> directly resulted in the creation of this <see cref="TypeToRegisterForPropertyBag"/>.</param>
        /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
        /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
        /// <param name="stringSerializerBuilderFunc">A func that builds the <see cref="IStringSerializeAndDeserialize"/>.</param>
        public TypeToRegisterForPropertyBag(
            Type type,
            Type recursiveOriginType,
            Type directOriginType,
            MemberTypesToInclude memberTypesToInclude,
            RelatedTypesToInclude relatedTypesToInclude,
            Func <IStringSerializeAndDeserialize> stringSerializerBuilderFunc)
            : base(type, recursiveOriginType, directOriginType, memberTypesToInclude, relatedTypesToInclude)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (recursiveOriginType == null)
            {
                throw new ArgumentNullException(nameof(recursiveOriginType));
            }

            if (directOriginType == null)
            {
                throw new ArgumentNullException(nameof(directOriginType));
            }

            if (type.IsGenericTypeDefinition)
            {
                throw new NotSupportedException(Invariant($"Open generics are not supported."));
            }

            if (stringSerializerBuilderFunc != null)
            {
                if (memberTypesToInclude != MemberTypesToInclude.None)
                {
                    throw new ArgumentException(Invariant($"{nameof(stringSerializerBuilderFunc)} is specified, but {nameof(Serialization.MemberTypesToInclude)} is not {MemberTypesToInclude.None}."));
                }
            }

            this.StringSerializerBuilderFunc = stringSerializerBuilderFunc;
        }
示例#10
0
        private static IReadOnlyCollection <Type> GetMemberTypesToInclude(
            Type type,
            MemberTypesToInclude memberTypesToInclude)
        {
            // This is for debugging purposes only.  The debugger doesn't like conditional breakpoints on objects
            // of type Type, so here we are pulling out the name to enable conditional breakpoint on name.
            var typeName = type.Name;

            if (memberTypesToInclude == MemberTypesToInclude.None)
            {
                return(new Type[0]);
            }

            var result = new List <Type>();

            if (memberTypesToInclude.HasFlag(MemberTypesToInclude.GenericArguments))
            {
                // Contrary to what is implied in documentation, a constructed generic type can still
                // contain generic parameters!  Also, and likely related, type.GetGenericArguments() can still
                // return generic parameters!  consider...
                //
                // private class GenericClassToRegister<T>
                // {
                //     public IDictionary<string, MyGenericClass<T>> MyProperty { get; set; }
                // }
                //
                // private class MyGenericClass<T> { }
                //
                // MemberTypesToInclude.DeclaredProperties will pull-in the type of MyProperty
                // When calling this method on that type, we observe the following:
                //
                // propertyType.IsConstructedGenericType == true
                // propertyType.ContainsGenericParameters == true
                // propertyType.IsGenericParameter == false
                // propertyType.IsGenericTypeDefinition == false
                //
                // var dictionaryValueType = propertyType.GetGenericArguments().Last()
                // dictionaryValueType.IsConstructedGenericType == true
                // dictionaryValueType.ContainsGenericParameters == true
                // dictionaryValueType.IsGenericParameter == false
                // dictionaryValueType.IsGenericTypeDefinition == false
                //
                // var genericParameterType = dictionaryValueType.GetGenericArguments().First()
                // genericParameterType.IsConstructedGenericType == false
                // genericParameterType.ContainsGenericParameters == true
                // genericParameterType.IsGenericParameter == true
                // genericParameterType.IsGenericTypeDefinition == false
                if (type.IsGenericType)
                {
                    result.AddRange(type.GenericTypeArguments.Where(_ => !_.IsGenericParameter));
                }
            }

            if (memberTypesToInclude.HasFlag(MemberTypesToInclude.ArrayElement))
            {
                if (type.IsArray)
                {
                    // same considerations as in the comment above about generic arguments:
                    // private class GenericClassToRegister<T>
                    // {
                    //     public IDictionary<string, MyGenericClass<T>>[] MyProperty { get; set; }
                    // }
                    result.Add(type.GetElementType());
                }
            }

            // We want to pull generic arguments and array elements from restricted types (e.g. List<MyModel>)
            // but otherwise we are not interested in the fields and properties of those types, which will
            // contain a bunch of other System and .NET internal types.
            if (!IsRestrictedType(type))
            {
                var fieldAndPropertyTypes = type
                                            .GetMembersFiltered(MemberRelationships.DeclaredInType, MemberOwners.Instance, MemberAccessModifiers.All, MemberKinds.Field | MemberKinds.Property)
                                            .Where(_ =>
                                                   ((_ is PropertyInfo) && memberTypesToInclude.HasFlag(MemberTypesToInclude.DeclaredProperties)) ||
                                                   ((_ is FieldInfo) && memberTypesToInclude.HasFlag(MemberTypesToInclude.DeclaredFields)))
                                            .Select(_ => _.GetUnderlyingType())
                                            .ToList();

                result.AddRange(fieldAndPropertyTypes);
            }

            // there will be open generic types that are not generic type definitions
            // we can only register the generic type definitions but we want to explore both sets of types
            // (e.g. the generic type definition of IDictionary<string, MyGenericClass<T>> is IDictionary<,>,
            // which misses MyGenericClass<>)
            var genericTypeDefinitions = result
                                         .Where(_ => _.IsGenericType && _.ContainsGenericParameters && (!_.IsGenericTypeDefinition))
                                         .Select(_ => _.GetGenericTypeDefinition())
                                         .ToList();

            result.AddRange(genericTypeDefinitions);

            return(result);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="TypeToRegisterForBson"/> class, specifying the origin types.
        /// </summary>
        /// <param name="type">The type to register.</param>
        /// <param name="recursiveOriginType">The type whose recursive processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> resulted in the creation of this <see cref="TypeToRegisterForBson"/>.</param>
        /// <param name="directOriginType">The type whose processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> directly resulted in the creation of this <see cref="TypeToRegisterForBson"/>.</param>
        /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
        /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
        /// <param name="bsonSerializerBuilder">Builds an <see cref="IBsonSerializer"/>.</param>
        /// <param name="propertyNameWhitelist">The names of the properties to constrain the registration to.</param>
        public TypeToRegisterForBson(
            Type type,
            Type recursiveOriginType,
            Type directOriginType,
            MemberTypesToInclude memberTypesToInclude,
            RelatedTypesToInclude relatedTypesToInclude,
            BsonSerializerBuilder bsonSerializerBuilder,
            IReadOnlyCollection <string> propertyNameWhitelist)
            : base(type, recursiveOriginType, directOriginType, memberTypesToInclude, relatedTypesToInclude)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (recursiveOriginType == null)
            {
                throw new ArgumentNullException(nameof(recursiveOriginType));
            }

            if (directOriginType == null)
            {
                throw new ArgumentNullException(nameof(directOriginType));
            }

            if ((bsonSerializerBuilder != null) && (propertyNameWhitelist != null))
            {
                throw new ArgumentException(Invariant($"{nameof(bsonSerializerBuilder)} and {nameof(propertyNameWhitelist)} cannot both be specified."));
            }

            if (bsonSerializerBuilder != null)
            {
                if (memberTypesToInclude != MemberTypesToInclude.None)
                {
                    throw new ArgumentException(Invariant($"{nameof(bsonSerializerBuilder)} is specified, but {nameof(Serialization.MemberTypesToInclude)} is not {MemberTypesToInclude.None}."));
                }

                if (type.IsGenericTypeDefinition)
                {
                    throw new NotSupportedException(Invariant($"{nameof(bsonSerializerBuilder)} is specified, but underlying type to register is an open generic."));
                }
            }

            if (propertyNameWhitelist != null)
            {
                if (!propertyNameWhitelist.Any())
                {
                    throw new ArgumentException(Invariant($"'{nameof(propertyNameWhitelist)}' is an empty enumerable"));
                }

                if (propertyNameWhitelist.Any(string.IsNullOrWhiteSpace))
                {
                    throw new ArgumentException(Invariant($"'{nameof(propertyNameWhitelist)}' contains an element that is null or white space"));
                }

                if (memberTypesToInclude != MemberTypesToInclude.None)
                {
                    throw new ArgumentException(Invariant($"{nameof(propertyNameWhitelist)} is specified, but {nameof(Serialization.MemberTypesToInclude)} is not {MemberTypesToInclude.None}."));
                }

                if (relatedTypesToInclude != RelatedTypesToInclude.None)
                {
                    throw new ArgumentException(Invariant($"{nameof(propertyNameWhitelist)} is specified, but {nameof(Serialization.RelatedTypesToInclude)} is not {RelatedTypesToInclude.None}."));
                }

                if (type.IsGenericTypeDefinition)
                {
                    throw new NotSupportedException(Invariant($"{nameof(propertyNameWhitelist)} is specified, but underlying type to register is an open generic."));
                }
            }

            this.BsonSerializerBuilder = bsonSerializerBuilder;
            this.PropertyNameWhitelist = propertyNameWhitelist;
        }
 /// <summary>
 /// Builds a <see cref="TypeToRegister"/> to be used for post-initialization registration,
 /// which only occurs for closed generic types at serialization-time, because these
 /// runtime types are not discoverable during initialization.
 /// </summary>
 /// <param name="type">The type to register.</param>
 /// <param name="recursiveOriginType">The type whose recursive processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> resulted in the creation of this <see cref="TypeToRegister"/>.</param>
 /// <param name="directOriginType">The type whose processing of <paramref name="memberTypesToInclude"/> and <paramref name="relatedTypesToInclude"/> directly resulted in the creation of this <see cref="TypeToRegister"/>.</param>
 /// <param name="memberTypesToInclude">Specifies which member types of <paramref name="type"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <paramref name="type"/> that should also be registered.</param>
 /// <returns>
 /// The type to register wrapper.
 /// </returns>
 protected abstract TypeToRegister BuildTypeToRegisterForPostInitializationRegistration(
     Type type,
     Type recursiveOriginType,
     Type directOriginType,
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude);
示例#13
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TypeToRegister{T}"/> class.
 /// </summary>
 /// <param name="memberTypesToInclude">Specifies which member types of <typeparamref name="T"/> that should also be registered.</param>
 /// <param name="relatedTypesToInclude">Specifies which types related to <typeparamref name="T"/> that should also be registered.</param>
 protected TypeToRegister(
     MemberTypesToInclude memberTypesToInclude,
     RelatedTypesToInclude relatedTypesToInclude)
     : base(typeof(T), memberTypesToInclude, relatedTypesToInclude)
 {
 }