Skip to content
This repository was archived by the owner on May 25, 2023. It is now read-only.

Commit f463ab3

Browse files
committed
Using the MVC way of loading dependencies
1 parent 18aada0 commit f463ab3

File tree

1 file changed

+135
-8
lines changed

1 file changed

+135
-8
lines changed

src/AutoMapper.Extensions.Microsoft.DependencyInjection/ServiceCollectionExtensions.cs

Lines changed: 135 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@ public static class ServiceCollectionExtensions
1515

1616
private static readonly Action<IMapperConfigurationExpression> DefaultConfig = cfg => { };
1717
#if DEPENDENCY_MODEL
18+
19+
private static HashSet<string> ReferenceAssemblies { get; } = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
20+
{
21+
//"Microsoft.AspNetCore.Mvc",
22+
//"Microsoft.AspNetCore.Mvc.Abstractions",
23+
//"Microsoft.AspNetCore.Mvc.ApiExplorer",
24+
//"Microsoft.AspNetCore.Mvc.Core",
25+
//"Microsoft.AspNetCore.Mvc.Cors",
26+
//"Microsoft.AspNetCore.Mvc.DataAnnotations",
27+
//"Microsoft.AspNetCore.Mvc.Formatters.Json",
28+
//"Microsoft.AspNetCore.Mvc.Formatters.Xml",
29+
//"Microsoft.AspNetCore.Mvc.Localization",
30+
//"Microsoft.AspNetCore.Mvc.Razor",
31+
//"Microsoft.AspNetCore.Mvc.Razor.Host",
32+
//"Microsoft.AspNetCore.Mvc.TagHelpers",
33+
//"Microsoft.AspNetCore.Mvc.ViewFeatures",
34+
"AutoMapper"
35+
};
36+
1837
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
1938
{
2039
return services.AddAutoMapper(null, DependencyContext.Default);
@@ -27,15 +46,123 @@ public static IServiceCollection AddAutoMapper(this IServiceCollection services,
2746

2847
public static IServiceCollection AddAutoMapper(this IServiceCollection services, Action<IMapperConfigurationExpression> additionalInitAction, DependencyContext dependencyContext)
2948
{
30-
return services.AddAutoMapper(additionalInitAction,
31-
dependencyContext.RuntimeLibraries
32-
// Only load assemblies that reference AutoMapper
33-
.Where(lib =>
34-
lib.Type.Equals("msbuildproject", StringComparison.OrdinalIgnoreCase) ||
35-
lib.Dependencies.Any(d => d.Name.StartsWith(AutoMapperAssembly.GetName().Name, StringComparison.OrdinalIgnoreCase)))
36-
.SelectMany(lib => lib.GetDefaultAssemblyNames(dependencyContext)
37-
.Select(Assembly.Load)));
49+
return services.AddAutoMapper(additionalInitAction, GetCandidateAssemblies(dependencyContext));
50+
}
51+
52+
private static IEnumerable<Assembly> GetCandidateAssemblies(DependencyContext dependencyContext)
53+
{
54+
return GetCandidateLibraries(dependencyContext)
55+
.SelectMany(library => library.GetDefaultAssemblyNames(dependencyContext))
56+
.Select(Assembly.Load);
57+
}
58+
59+
private static IEnumerable<RuntimeLibrary> GetCandidateLibraries(DependencyContext dependencyContext)
60+
{
61+
if (ReferenceAssemblies == null)
62+
{
63+
return Enumerable.Empty<RuntimeLibrary>();
64+
}
65+
66+
var candidatesResolver = new CandidateResolver(dependencyContext.RuntimeLibraries, ReferenceAssemblies);
67+
return candidatesResolver.GetCandidates();
3868
}
69+
70+
private class CandidateResolver
71+
{
72+
private readonly IDictionary<string, Dependency> _dependencies;
73+
74+
public CandidateResolver(IReadOnlyList<RuntimeLibrary> dependencies, ISet<string> referenceAssemblies)
75+
{
76+
var dependenciesWithNoDuplicates = new Dictionary<string, Dependency>(StringComparer.OrdinalIgnoreCase);
77+
foreach (var dependency in dependencies)
78+
{
79+
if (dependenciesWithNoDuplicates.ContainsKey(dependency.Name))
80+
{
81+
throw new InvalidOperationException(
82+
$"A duplicate entry for library reference {dependency.Name} was found. Please check that all package references in all projects use the same casing for the same package references.");
83+
}
84+
dependenciesWithNoDuplicates.Add(dependency.Name, CreateDependency(dependency, referenceAssemblies));
85+
}
86+
87+
_dependencies = dependenciesWithNoDuplicates;
88+
}
89+
90+
private Dependency CreateDependency(RuntimeLibrary library, ISet<string> referenceAssemblies)
91+
{
92+
var classification = DependencyClassification.Unknown;
93+
if (referenceAssemblies.Contains(library.Name))
94+
{
95+
classification = DependencyClassification.AutoMapperReference;
96+
}
97+
98+
return new Dependency(library, classification);
99+
}
100+
101+
private DependencyClassification ComputeClassification(string dependency)
102+
{
103+
var candidateEntry = _dependencies[dependency];
104+
if (candidateEntry.Classification != DependencyClassification.Unknown)
105+
{
106+
return candidateEntry.Classification;
107+
}
108+
else
109+
{
110+
var classification = DependencyClassification.NotCandidate;
111+
foreach (var candidateDependency in candidateEntry.Library.Dependencies)
112+
{
113+
var dependencyClassification = ComputeClassification(candidateDependency.Name);
114+
if (dependencyClassification == DependencyClassification.Candidate ||
115+
dependencyClassification == DependencyClassification.AutoMapperReference)
116+
{
117+
classification = DependencyClassification.Candidate;
118+
break;
119+
}
120+
}
121+
122+
candidateEntry.Classification = classification;
123+
124+
return classification;
125+
}
126+
}
127+
128+
public IEnumerable<RuntimeLibrary> GetCandidates()
129+
{
130+
foreach (var dependency in _dependencies)
131+
{
132+
if (ComputeClassification(dependency.Key) == DependencyClassification.Candidate)
133+
{
134+
yield return dependency.Value.Library;
135+
}
136+
}
137+
}
138+
139+
private class Dependency
140+
{
141+
public Dependency(RuntimeLibrary library, DependencyClassification classification)
142+
{
143+
Library = library;
144+
Classification = classification;
145+
}
146+
147+
public RuntimeLibrary Library { get; }
148+
149+
public DependencyClassification Classification { get; set; }
150+
151+
public override string ToString()
152+
{
153+
return $"Library: {Library.Name}, Classification: {Classification}";
154+
}
155+
}
156+
157+
private enum DependencyClassification
158+
{
159+
Unknown = 0,
160+
Candidate = 1,
161+
NotCandidate = 2,
162+
AutoMapperReference = 3
163+
}
164+
}
165+
39166
#endif
40167

41168
public static IServiceCollection AddAutoMapper(this IServiceCollection services, params Assembly[] assemblies)

0 commit comments

Comments
 (0)