Skip to content

Commit 3800c68

Browse files
committed
Design: Stop invoking Startup.ConfigureServices
Part of #8164
1 parent 0ab838a commit 3800c68

12 files changed

+34
-487
lines changed

src/EFCore.Design/Design/Internal/DatabaseOperations.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ public DatabaseOperations(
3636
_projectDir = projectDir;
3737
_rootNamespace = rootNamespace;
3838

39-
var startup = new StartupInvoker(reporter, startupAssembly);
40-
_servicesBuilder = new DesignTimeServicesBuilder(startup);
39+
_servicesBuilder = new DesignTimeServicesBuilder(startupAssembly);
4140
}
4241

4342
public virtual Task<ReverseEngineerFiles> ScaffoldContextAsync(

src/EFCore.Design/Design/Internal/DbContextOperations.cs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public class DbContextOperations
2222
private readonly IOperationReporter _reporter;
2323
private readonly Assembly _assembly;
2424
private readonly Assembly _startupAssembly;
25-
private readonly IServiceProvider _runtimeServices;
2625

2726
// This obsolete constructor maintains compatibility with Scaffolding
2827
public DbContextOperations(
@@ -47,9 +46,6 @@ public DbContextOperations(
4746
_reporter = reporter;
4847
_assembly = assembly;
4948
_startupAssembly = startupAssembly;
50-
51-
var startup = new StartupInvoker(reporter, startupAssembly);
52-
_runtimeServices = startup.ConfigureServices();
5349
}
5450

5551
public virtual void DropDatabase([CanBeNull] string contextType)
@@ -114,25 +110,15 @@ where i.GetTypeInfo().IsGenericType
114110
}
115111
}
116112

117-
// Look for DbContext classes registered in the service provider
118-
var registeredContexts = _runtimeServices.GetServices<DbContextOptions>()
119-
.Select(o => o.ContextType);
120-
foreach (var context in registeredContexts.Where(c => !contexts.ContainsKey(c)))
121-
{
122-
contexts.Add(
123-
context,
124-
FindContextFactory(context) ?? (() => (DbContext)ActivatorUtilities.GetServiceOrCreateInstance(_runtimeServices, context)));
125-
}
126-
127113
// Look for DbContext classes in assemblies
128114
var types = _startupAssembly.GetConstructableTypes()
129115
.Concat(_assembly.GetConstructableTypes())
130-
.Select(i => i.AsType())
131116
.ToList();
132-
var contextTypes = types.Where(t => typeof(DbContext).IsAssignableFrom(t))
117+
var contextTypes = types.Where(t => typeof(DbContext).GetTypeInfo().IsAssignableFrom(t)).Select(
118+
t => t.AsType())
133119
.Concat(
134-
types.Where(t => typeof(Migration).IsAssignableFrom(t))
135-
.Select(t => t.GetTypeInfo().GetCustomAttribute<DbContextAttribute>()?.ContextType)
120+
types.Where(t => typeof(Migration).GetTypeInfo().IsAssignableFrom(t))
121+
.Select(t => t.GetCustomAttribute<DbContextAttribute>()?.ContextType)
136122
.Where(t => t != null))
137123
.Distinct();
138124
foreach (var context in contextTypes.Where(c => !contexts.ContainsKey(c)))
@@ -173,14 +159,13 @@ private Func<DbContext> FindContextFactory(Type contextType)
173159
var factoryInterface = typeof(IDbContextFactory<>).MakeGenericType(contextType).GetTypeInfo();
174160
var factory = contextType.GetTypeInfo().Assembly.GetConstructableTypes()
175161
.Where(t => factoryInterface.IsAssignableFrom(t))
176-
.Select(t => t.AsType())
177162
.FirstOrDefault();
178163
if (factory == null)
179164
{
180165
return null;
181166
}
182167

183-
return () => ((IDbContextFactory<DbContext>)Activator.CreateInstance(factory)).Create(
168+
return () => ((IDbContextFactory<DbContext>)Activator.CreateInstance(factory.AsType())).Create(
184169
Array.Empty<string>());
185170
}
186171

src/EFCore.Design/Design/Internal/DesignTimeServicesBuilder.cs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.IO;
6+
using System.Linq;
67
using System.Reflection;
78
using JetBrains.Annotations;
89
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -24,15 +25,15 @@ namespace Microsoft.EntityFrameworkCore.Design.Internal
2425
/// </summary>
2526
public class DesignTimeServicesBuilder
2627
{
27-
private readonly StartupInvoker _startup;
28+
private readonly Assembly _startupAssembly;
2829

2930
/// <summary>
3031
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
3132
/// directly from your code. This API may change or be removed in future releases.
3233
/// </summary>
33-
public DesignTimeServicesBuilder([NotNull] StartupInvoker startupInvoker)
34+
public DesignTimeServicesBuilder([NotNull] Assembly startupAssembly)
3435
{
35-
_startup = startupInvoker;
36+
_startupAssembly = startupAssembly;
3637
}
3738

3839
/// <summary>
@@ -80,7 +81,7 @@ protected virtual IServiceCollection ConfigureServices([NotNull] IServiceCollect
8081
.AddLogging();
8182

8283
private IServiceCollection ConfigureProviderServices(string provider, IServiceCollection services, bool throwOnError = false)
83-
=> _startup.ConfigureDesignTimeServices(GetProviderDesignTimeServices(provider, throwOnError), services);
84+
=> ConfigureDesignTimeServices(GetProviderDesignTimeServices(provider, throwOnError), services);
8485

8586
/// <summary>
8687
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@@ -105,7 +106,13 @@ protected virtual IServiceCollection ConfigureContextServices(
105106
.AddTransient(_ => contextServices.GetService<IModel>());
106107

107108
private IServiceCollection ConfigureUserServices(IServiceCollection services)
108-
=> _startup.ConfigureDesignTimeServices(services);
109+
{
110+
var designTimeServicesType = _startupAssembly.GetLoadableDefinedTypes()
111+
.Where(t => typeof(IDesignTimeServices).GetTypeInfo().IsAssignableFrom(t)).Select(t => t.AsType())
112+
.FirstOrDefault();
113+
114+
return ConfigureDesignTimeServices(designTimeServicesType, services);
115+
}
109116

110117
private Type GetProviderDesignTimeServices(string provider, bool throwOnError)
111118
{
@@ -160,5 +167,18 @@ private Type GetProviderDesignTimeServices(string provider, bool throwOnError)
160167
throwOnError: true,
161168
ignoreCase: false);
162169
}
170+
171+
private static IServiceCollection ConfigureDesignTimeServices(
172+
Type designTimeServicesType,
173+
IServiceCollection services)
174+
{
175+
if (designTimeServicesType != null)
176+
{
177+
var designTimeServices = (IDesignTimeServices)Activator.CreateInstance(designTimeServicesType);
178+
designTimeServices.ConfigureDesignTimeServices(services);
179+
}
180+
181+
return services;
182+
}
163183
}
164184
}

src/EFCore.Design/Design/Internal/HostingEnvironment.cs

Lines changed: 0 additions & 51 deletions
This file was deleted.

src/EFCore.Design/Design/Internal/MigrationsOperations.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ public MigrationsOperations(
4848
assembly,
4949
startupAssembly);
5050

51-
var startup = new StartupInvoker(reporter, startupAssembly);
52-
_servicesBuilder = new DesignTimeServicesBuilder(startup);
51+
_servicesBuilder = new DesignTimeServicesBuilder(startupAssembly);
5352
}
5453

5554
public virtual MigrationFiles AddMigration(

src/EFCore.Design/Design/Internal/StartupInvoker.cs

Lines changed: 0 additions & 155 deletions
This file was deleted.

src/EFCore.Design/EFCore.Design.csproj

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@
1414
<ItemGroup>
1515
<ProjectReference Include="..\EFCore.Relational.Design\EFCore.Relational.Design.csproj" />
1616
</ItemGroup>
17-
<ItemGroup>
18-
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
19-
</ItemGroup>
2017
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3'">
2118
<PackageReference Include="System.Collections.NonGeneric" Version="$(CoreFxVersion)" />
2219
</ItemGroup>

src/EFCore/Infrastructure/DesignTimeProviderServicesAttribute.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ public sealed class DesignTimeProviderServicesAttribute : Attribute
2626
/// </summary>
2727
/// <param name="typeName">
2828
/// The name of the type that can be used to add the database providers design time services to a <see cref="ServiceCollection" />.
29-
/// This type should contain a method with the following signature
30-
/// <code>public IServiceCollection ConfigureDesignTimeServices(IServiceCollection serviceCollection)</code>.
29+
/// This type should implement <see cref="IDesignTimeServices" />.
3130
/// </param>
3231
/// <param name="assemblyName">
3332
/// The name of the assembly that contains the design time services.
@@ -49,8 +48,7 @@ public DesignTimeProviderServicesAttribute(
4948

5049
/// <summary>
5150
/// Gets the name of the type that can be used to add the database providers design time services to a <see cref="ServiceCollection" />.
52-
/// This type should contain a method with the following signature
53-
/// <code>public IServiceCollection ConfigureDesignTimeServices(IServiceCollection serviceCollection)</code>.
51+
/// This type should implement <see cref="IDesignTimeServices"/>.
5452
/// </summary>
5553
public string TypeName { get; }
5654

0 commit comments

Comments
 (0)