/// <summary>
        /// Builds a valid <see cref="ArtifactsConfiguration"/> based on a <see cref="BoundedContextTopology"/>
        /// </summary>
        /// <param name="boundedContextTopology"></param>
        /// <returns></returns>
        public ArtifactsConfiguration Build(BoundedContextTopology boundedContextTopology)
        {
            var newArtifacts = 0;

            var artifactsDictionary = new MutableArtifactsDictionary();

            foreach (var(feature, featureArtifactsByType) in _currentArtifactsConfiguration)
            {
                var featureArtifacts = artifactsDictionary[feature] = new Dictionary <PropertyInfo, Dictionary <ArtifactId, ArtifactDefinition> >();
                foreach (var artifactType in featureArtifactsByType.GetType().GetProperties())
                {
                    var existingArtifactsForFeatureType = artifactType.GetValue(featureArtifactsByType) as IReadOnlyDictionary <ArtifactId, ArtifactDefinition>;
                    featureArtifacts[artifactType] = new Dictionary <ArtifactId, ArtifactDefinition>(existingArtifactsForFeatureType.ToDictionary(_ => _.Key, _ => _.Value));
                }
            }

            var nonMatchingArtifacts = new List <string>();

            foreach (var artifactType in _artifactTypes)
            {
                newArtifacts += HandleArtifactOfType(
                    artifactType,
                    boundedContextTopology,
                    artifactsDictionary,
                    nonMatchingArtifacts
                    );
            }
            if (nonMatchingArtifacts.Any())
            {
                foreach (var artifactNamespace in nonMatchingArtifacts)
                {
                    _buildMessages.Warning($"An artifact with namespace: '{artifactNamespace}' could not be matched with any feature in the Bounded Context's topology");
                }

                throw new NonMatchingArtifact();
            }

            //new Dictionary<Feature, ArtifactsByTypeDefinition>()
            var artifactsByTypeDefinitionConstructor = typeof(ArtifactsByTypeDefinition).GetConstructors().Single(_ => _.GetParameters().All(p => p.ParameterType.Equals(typeof(IDictionary <ArtifactId, ArtifactDefinition>))));

            var updatedArtifactsConfiguration = new ArtifactsConfiguration(new Dictionary <Feature, ArtifactsByTypeDefinition>(
                                                                               artifactsDictionary.Select(_ =>
            {
                var feature   = _.Key;
                var arguments = artifactsByTypeDefinitionConstructor.GetParameters().Select(arg =>
                {
                    return(_.Value.SingleOrDefault(prop => arg.Name.ToLower().Equals(prop.Key.Name.ToLower())).Value ?? new Dictionary <ArtifactId, ArtifactDefinition>());
                }).ToArray();
                var artifacts = artifactsByTypeDefinitionConstructor.Invoke(arguments) as ArtifactsByTypeDefinition;
                return(new KeyValuePair <Feature, ArtifactsByTypeDefinition>(feature, artifacts));
            }).ToDictionary(_ => _.Key, _ => _.Value)
                                                                               ));

            updatedArtifactsConfiguration.ValidateArtifacts(boundedContextTopology, _artifacts, _buildMessages);

            if (newArtifacts > 0)
            {
                _buildMessages.Information($"Added {newArtifacts} new artifacts to the map.");
            }
            else
            {
                _buildMessages.Information($"No new artifacts added to the map.");
            }

            return(updatedArtifactsConfiguration);
        }
        int HandleArtifactOfType(ArtifactType artifactType, BoundedContextTopology boundedContextConfiguration, MutableArtifactsDictionary artifactsDictionary, List <string> nonMatchingArtifacts)
        {
            var targetProperty = artifactType.TargetPropertyExpression.GetPropertyInfo();

            var newArtifacts = 0;
            var artifacts    = _artifacts.Where(_ => artifactType.Type.IsAssignableFrom(_));

            foreach (var artifact in artifacts)
            {
                var feature = boundedContextConfiguration.FindMatchingFeature(artifact.Namespace, nonMatchingArtifacts);
                if (feature.Value != null)
                {
                    MutableArtifactsByTypeDictionary artifactsByType;
                    if (!artifactsDictionary.TryGetValue(feature.Key, out artifactsByType))
                    {
                        artifactsByType = artifactsDictionary[feature.Key] = new Dictionary <PropertyInfo, Dictionary <ArtifactId, ArtifactDefinition> >();
                    }

                    Dictionary <ArtifactId, ArtifactDefinition> mutableArtifacts;
                    if (!artifactsByType.TryGetValue(targetProperty, out mutableArtifacts))
                    {
                        mutableArtifacts = artifactsByType[targetProperty] = new Dictionary <ArtifactId, ArtifactDefinition>();
                    }

                    if (!mutableArtifacts.Any(_ => _.Value.Type.GetActualType() == artifact))
                    {
                        var artifactObject = new Dolittle.Artifacts.Artifact(ArtifactId.New(), ArtifactGeneration.First);
                        if (artifact.HasAttribute <ArtifactAttribute>())
                        {
                            artifactObject = (artifact.GetTypeInfo().GetCustomAttributes(typeof(ArtifactAttribute), false).First() as ArtifactAttribute).Artifact;
                        }

                        AddNewArtifact(artifactObject, artifact, mutableArtifacts, artifactType.TypeName);
                        newArtifacts++;
                    }
                    else
                    {
                        if (artifact.HasAttribute <ArtifactAttribute>())
                        {
                            var artifactObject = (artifact.GetTypeInfo().GetCustomAttributes(typeof(ArtifactAttribute), false).First() as ArtifactAttribute).Artifact;

                            var existingArtifact = mutableArtifacts.Single(_ => _.Value.Type.GetActualType() == artifact);
                            if (!existingArtifact.Key.Value.Equals(artifactObject.Id.Value))
                            {
                                mutableArtifacts.Remove(existingArtifact.Key);
                                AddNewArtifact(artifactObject, artifact, mutableArtifacts, artifactType.TypeName);
                                newArtifacts++;
                            }
                        }
                    }
                }
            }
            return(newArtifacts);
        }