/// <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)
 {
 }
        /// <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;
        }
示例#3
0
        private static CanConvertTypeMatchStrategy ToCanConvertTypeMatchStrategy(
            this RelatedTypesToInclude relatedTypesToInclude)
        {
            CanConvertTypeMatchStrategy result;

            switch (relatedTypesToInclude)
            {
            case RelatedTypesToInclude.None:
                result = CanConvertTypeMatchStrategy.TypeToConsiderEqualsRegisteredType;
                break;

            case RelatedTypesToInclude.Descendants:
                result = CanConvertTypeMatchStrategy.TypeToConsiderIsAssignableToRegisteredType;
                break;

            case RelatedTypesToInclude.Ancestors:
                result = CanConvertTypeMatchStrategy.TypeToConsiderIsAssignableFromRegisteredType;
                break;

            case RelatedTypesToInclude.AncestorsAndDescendants:
                result = CanConvertTypeMatchStrategy.TypeToConsiderIsAssignableToOrFromRegisteredType;
                break;

            default:
                throw new NotSupportedException(Invariant($"This {nameof(RelatedTypesToInclude)} is not supported: {relatedTypesToInclude}."));
            }

            return(result);
        }
示例#4
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);
        }
示例#5
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)
 {
 }
示例#9
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;
        }
示例#11
0
        private static IReadOnlyCollection <Type> GetRelatedTypesToInclude(
            Type type,
            RelatedTypesToInclude relatedTypesToInclude)
        {
            // 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;

            relatedTypesToInclude = relatedTypesToInclude == RelatedTypesToInclude.Default
                ? type.ResolveDefaultIntoActionableRelatedTypesToInclude()
                : relatedTypesToInclude;

            if (relatedTypesToInclude == RelatedTypesToInclude.None)
            {
                return(new Type[0]);
            }

            // Short-circuit restricted types.  We will see these types here because we want to explore them in
            // GetMemberTypesToInclude (e.g. List<MyModel>), but we are not interested in their related types
            // (e.g. IEnumerable).
            if (IsRestrictedType(type))
            {
                return(new Type[0]);
            }

            // In a past iteration of this code we checked type.IsAssignableFrom against all loaded types, and vice versa.
            // In that iteration we purposefully avoided TypeHelper.IsAssignableTo because of performance issues related
            // to the OBeautifulCode.Validation calls in that method.  Also, IsAssignableTo throws when parameter 'type'
            // is a generic type definition.
            // Unfortunately, IsAssignableFrom is not a complete solution for generic types.
            // For generic types, IsAssignableFrom sometimes find ancestors but not always, depending on how
            // the type's inheritance is structured/declared.  Consider:
            // class Parent<T> { }
            // class Child<T> : Parent<T> { }
            // typeof(Child<>).BaseType != typeof(Parent<>)
            // typeof(Parent<>).IsAssignableFrom(typeof(Child<>)) == false
            // typeof(Child<>).BaseType is actually not a loaded type.  So this "related type" relationship cannot be discovered
            // using the methodology of the prior iteration of this code.
            DiscoverAncestorsAndDescendants(type);

            IReadOnlyCollection <Type> result;

            switch (relatedTypesToInclude)
            {
            // note we don't need to check whether TypeToAncestorTypesMap or TypeToAncestorTypesMap contains type
            // because type is guaranteed to be keys in those dictionaries after the call to DiscoverAncestorsAndDescendants() above
            case RelatedTypesToInclude.Ancestors:
                result = TypeToAncestorTypesMap[type].ToList();
                break;

            case RelatedTypesToInclude.Descendants:
                result = TypeToDescendantTypesMap[type].ToList();
                break;

            case RelatedTypesToInclude.AncestorsAndDescendants:
                result = new Type[0].Concat(TypeToAncestorTypesMap[type]).Concat(TypeToDescendantTypesMap[type]).ToList();
                break;

            default:
                throw new NotSupportedException(Invariant($"This {nameof(RelatedTypesToInclude)} is not supported: {relatedTypesToInclude}"));
            }

            // 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 = result
                     .Concat(genericTypeDefinitions)
                     .ToList();

            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);
示例#14
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)
 {
 }