public static IDto ToDto(this IDictionary <string, object> unTypedDto, TypeInfo dtoType)
        {
            if (unTypedDto == null)
            {
                throw new ArgumentNullException(nameof(unTypedDto));
            }

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

            IDto dto = (IDto)Activator.CreateInstance(dtoType);

            Dictionary <string, object> extraProps = null;

            if (dto is IOpenType openTypeDto)
            {
                extraProps = openTypeDto.Properties = (openTypeDto.Properties ?? new Dictionary <string, object>());
            }

            foreach (KeyValuePair <string, object> KeyVal in unTypedDto)
            {
                PropertyInfo prop = dtoType.GetProperty(KeyVal.Key);

                object val = KeyVal.Value;

                if (prop != null)
                {
                    if (prop.PropertyType.IsEnum && val != null)
                    {
                        val = Enum.Parse(prop.PropertyType, KeyVal.Value.ToString());
                    }

                    if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string))
                    {
                        // This converts List<object> which contains some Guid values to List<Guid> which contains some Guid values.
                        IList propertyValue = (IList)Activator.CreateInstance(prop.PropertyType);
                        foreach (object item in (IEnumerable)val)
                        {
                            propertyValue.Add(item);
                        }
                        val = propertyValue;
                    }

                    prop.SetValue(dto, val);
                }
                else
                {
                    extraProps?.Add(KeyVal.Key, val);
                }
            }

            return(dto);
        }
        public static IDto ToDto(this IDictionary <string, object> unTypedDto, TypeInfo dtoType)
        {
            if (unTypedDto == null)
            {
                throw new ArgumentNullException(nameof(unTypedDto));
            }

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

            IDto dto = (IDto)Activator.CreateInstance(dtoType);

            Dictionary <string, object> extraProps = null;

            if (dto is IOpenType openTypeDto)
            {
                extraProps = openTypeDto.Properties = (openTypeDto.Properties ?? new Dictionary <string, object>());
            }

            foreach (KeyValuePair <string, object> KeyVal in unTypedDto)
            {
                PropertyInfo prop = dtoType.GetProperty(KeyVal.Key);

                object val = KeyVal.Value;

                if (prop != null)
                {
                    if (prop.PropertyType.IsEnum && val != null)
                    {
                        val = Enum.Parse(prop.PropertyType, KeyVal.Value.ToString());
                    }
                    prop.SetValue(dto, val);
                }
                else
                {
                    extraProps?.Add(KeyVal.Key, val);
                }
            }

            return(dto);
        }
        private static Proababilities CalculateSeqProbabilities(IEnumerable <ISymbol> population)
        {
            var cumulativeProbability = 0.0m;
            var correctionCoeficient  = population.Sum(p => p.Probability) != 1.0m
                                            ? 1.0m / population.Sum(p => p.Probability)
                                            : 1.0m;

            var seqProbabilities = new Proababilities();

            foreach (var entity in population)
            {
                var adjustedProabability = entity.Probability * correctionCoeficient;
                seqProbabilities.Add(entity, (cumulativeProbability, cumulativeProbability + adjustedProabability));
                cumulativeProbability += adjustedProabability;
            }

            if (cumulativeProbability != 1.0m)
            {
                throw new Exception("Symbols probabilities sum must be exactly 100%.");
            }

            return(seqProbabilities);
        }