private static void AddConverter(IConverterRepository repository, Type converterType)
        {
            IEnumerable <object> attributes = converterType.GetCustomAttributes(typeof(ConverterAttribute), true);
            IConverter           converter  = (IConverter)Activator.CreateInstance(converterType);

            foreach (ConverterAttribute attribute in attributes)
            {
                if (attribute.HasTypesDefined)
                {
                    Type sourceType = attribute.SourceType;
                    Type targetType = attribute.TargetType;
                    repository.Add(sourceType, targetType, converter);
                }
                else
                {
                    IEnumerable <Type> interfaceTypes = converterType.GetInterfaces();
                    foreach (Type interfaceType in interfaceTypes)
                    {
                        if (interfaceType.IsGenericType && typeof(IConverter <,>) == interfaceType.GetGenericTypeDefinition())
                        {
                            Type[] parameters = interfaceType.GetGenericArguments();
                            Type   sourceType = parameters[0];
                            Type   targetType = parameters[1];
                            repository.Add(sourceType, targetType, converter);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Adds converters for EventSourcing logging.
 /// </summary>
 /// <param name="repository">A converter repository.</param>
 /// <returns>A converter repository.</returns>
 public static IConverterRepository AddEventSourcingLogging(this IConverterRepository repository)
 {
     Ensure.NotNull(repository, "repository");
     return(repository
            .Add(new EnvelopeMessageConverter())
            .Add(new CommandMessageConverter())
            .Add(new EventMessageConverter()));
 }
        /// <summary>
        /// Adds <paramref name="tryConvert"/> for convertion of string value separated by <paramref name="separator"/>
        /// to <see cref="List{TTargetItem}"/>, <see cref="IList{TTargetItem}"/>, <see cref="ICollection{TTargetItem}"/> and <see cref="IEnumerable{TTargetItem}"/>.
        /// </summary>
        /// <typeparam name="TTargetItem">Type of collection item.</typeparam>
        /// <param name="repository">The repository to register converter to.</param>
        /// <param name="tryConvert">The converter delegate.</param>
        /// <param name="separator">Item separator.</param>
        /// <returns><paramref name="repository"/>.</returns>
        public static IConverterRepository AddStringToCollection <TTargetItem>(this IConverterRepository repository, OutFunc <string, TTargetItem, bool> tryConvert, string separator = ",")
        {
            Ensure.NotNull(repository, "repository");
            StringToCollectionConverter <TTargetItem> converter = new StringToCollectionConverter <TTargetItem>(separator, new DefaultConverter <string, TTargetItem>(tryConvert));

            return(repository
                   .Add <string, List <TTargetItem> >(converter)
                   .Add <string, IList <TTargetItem> >(converter)
                   .Add <string, ICollection <TTargetItem> >(converter)
                   .Add <string, IEnumerable <TTargetItem> >(converter));
        }
        /// <summary>
        /// Adds converter to the <paramref name="repository"/> for converting <see cref="TimeSpan"/> to/from <see cref="JToken"/>.
        /// </summary>
        /// <param name="repository">The repository to add converters to.</param>
        /// <returns>Self (for fluency).</returns>
        public static IConverterRepository AddJsonTimeSpan(this IConverterRepository repository)
        {
            Ensure.NotNull(repository, "repository");

            TimeSpanToJsonConverter converter = new TimeSpanToJsonConverter();

            return(repository
                   .Add <TimeSpan, JToken>(converter)
                   .Add <JToken, TimeSpan>(converter)
                   .Add <JValue, TimeSpan>(converter)
                   .Add <string, TimeSpan>(TimeSpan.TryParse));
        }
        /// <summary>
        /// Adds <paramref name="tryConvert"/> for conversion from <see cref="String"/> to <typeparamref name="TTarget"/>.
        /// Alse adds support for nullable conversion from <see cref="String"/> to <see cref="Nullable{TTarget}"/>.
        /// </summary>
        /// <typeparam name="TTarget">Target type.</typeparam>
        /// <param name="repository">The repository to register converter to.</param>
        /// <param name="tryConvert">The converter delegate.</param>
        /// <param name="isWhitespaceAccepted">Whether whitespaces should be treated as nulls.</param>
        /// <returns><paramref name="repository"/>.</returns>
        public static IConverterRepository AddStringTo <TTarget>(this IConverterRepository repository, OutFunc <string, TTarget, bool> tryConvert, bool isWhitespaceAccepted = true)
            where TTarget : struct
        {
            Ensure.NotNull(repository, "repository");
            Ensure.NotNull(tryConvert, "tryConvert");

            IConverter <string, TTarget> converter = new DefaultConverter <string, TTarget>(tryConvert);

            return(repository
                   .Add <string, TTarget>(converter)
                   .Add <string, TTarget?>(new StringToNullableConverter <TTarget>(converter, isWhitespaceAccepted)));
        }
        /// <summary>
        /// Adds converters from/to <see cref="GuidKey"/>, <see cref="StringKey"/> and <see cref="IKey"/> (of type <see cref="GuidKey"/> or <see cref="StringKey"/>) and <see cref="JToken"/>.
        /// </summary>
        /// <param name="repository">The repository to add converters to.</param>
        /// <returns>Self (for fluency).</returns>
        public static IConverterRepository AddJsonKey(this IConverterRepository repository)
        {
            Ensure.NotNull(repository, "repository");

            GuidKeyToJTokenConverter   guidConverter   = new GuidKeyToJTokenConverter();
            StringKeyToJTokenConverter stringConverter = new StringKeyToJTokenConverter();
            KeyToJTokenConverter       keyConverter    = new KeyToJTokenConverter();

            return(repository
                   .Add <GuidKey, JToken>(guidConverter)
                   .Add <JToken, GuidKey>(guidConverter)
                   .Add(typeof(List <GuidKey>), typeof(JToken), guidConverter)
                   .Add(typeof(JToken), typeof(IEnumerable <GuidKey>), guidConverter)
                   .Add <StringKey, JToken>(stringConverter)
                   .Add <JToken, StringKey>(stringConverter)
                   .Add(typeof(List <StringKey>), typeof(JToken), stringConverter)
                   .Add(typeof(JToken), typeof(IEnumerable <StringKey>), stringConverter)
                   .Add <IKey, JToken>(keyConverter)
                   .Add <JToken, IKey>(keyConverter)
                   .Add(typeof(List <IKey>), typeof(JToken), keyConverter)
                   .Add(typeof(JToken), typeof(IEnumerable <IKey>), keyConverter));
        }
 /// <summary>
 /// Adds <paramref name="converter"/> for conversion from <typeparamref name="TSource"/> to <typeparamref name="TTarget"/>.
 /// </summary>
 /// <typeparam name="TSource">Source type.</typeparam>
 /// <typeparam name="TTarget">Target type.</typeparam>
 /// <param name="repository">The repository to register converter to.</param>
 /// <param name="converter">The converter.</param>
 /// <returns><paramref name="repository"/>.</returns>
 public static IConverterRepository Add <TSource, TTarget>(this IConverterRepository repository, IConverter <TSource, TTarget> converter)
 {
     Ensure.NotNull(repository, "repository");
     repository.Add(typeof(TSource), typeof(TTarget), converter);
     return(repository);
 }