EntityFrameworkCore.Design (DesignTimeServicesBuilder.cs) 中的服务更换
Service replacement in EntityFrameworkCore.Design (DesignTimeServicesBuilder.cs)
我正在尝试用我自己的自定义实现替换 Microsoft.EntityFrameworkCore.Design
中的 StringBuilderCodeWriter
,以便修改脚手架以生成存储库模式 classes。
我正在重写 DesignTimeServicesBuilder
中的 ConfigureServices
方法来添加我的 CustomStringBuilderCodeWritter
但我无法让它使用我的实现。
我正在使用 EF Core 1.1 在 .NET Core 控制台应用程序中对此进行测试
Program.cs
using System.Collections.Generic;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
namespace RepositoryPattern
{
public class Program
{
public static void Main(string[] args)
{
IOperationReportHandler handler = new OperationReportHandler();
IOperationReporter reporter = new OperationReporter(handler);
var startup = new StartupInvoker(reporter, Assembly.Load(new AssemblyName("Microsoft.EntityFrameworkCore.Design")), "ADONET_DATA_DIR", @"ANOTHER_OUTPUT_PATH");
CustomDesignTimeServicesBuilder servicesBuilder = new CustomDesignTimeServicesBuilder(startup);
var services = servicesBuilder.Build("Microsoft.EntityFrameworkCore.SqlServer");
var generator = services.GetRequiredService<ReverseEngineeringGenerator>();
// The TableSelectionSet seems to be ignored for some reason, ignore for now.
var tableSelectionSet = new TableSelectionSet(new List<string> { "Customers", "Employees" }, new List<string> { "dbo" });
var configuration = new ReverseEngineeringConfiguration
{
ConnectionString = @"Server=(localdb)\Samples;Database=Northwind;Trusted_Connection=True;",
ContextClassName = "NorthwindContext",
ProjectPath = @"PROJECT_PATH_GOES_HERE",
ProjectRootNamespace = "RepositoryPattern",
OutputPath = @"WHERE_THE_GENERATED_FILES_GO",
TableSelectionSet = tableSelectionSet,
UseFluentApiOnly = true,
OverwriteFiles = true
};
generator.GenerateAsync(configuration, new CancellationToken());
}
}
}
CustomDesignTimeServicesBuilder.cs
using Microsoft.EntityFrameworkCore.Migrations.Design;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.Extensions.DependencyInjection;
namespace RepositoryPattern
{
public class CustomDesignTimeServicesBuilder : DesignTimeServicesBuilder
{
public CustomDesignTimeServicesBuilder(StartupInvoker startupInvoker) : base(startupInvoker)
{ }
protected override IServiceCollection ConfigureServices(IServiceCollection services)
{
services.AddSingleton<CSharpHelper>();
services.AddSingleton<CSharpMigrationOperationGenerator>();
services.AddSingleton<CSharpSnapshotGenerator>();
services.AddSingleton<MigrationsCodeGenerator, CSharpMigrationsGenerator>();
services.AddScaffolding();
services.AddSingleton<StringBuilderCodeWriter, CustomStringBuilderCodeWriter>();
services.AddLogging();
return base.ConfigureServices(services);
}
}
}
CustomStringBuilderCodeWriter.cs
此实现在循环 EntityConfigurations 时额外创建 class 以生成存储库样式 class.
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Configuration.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
namespace RepositoryPattern
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class CustomStringBuilderCodeWriter : StringBuilderCodeWriter
{
public CustomStringBuilderCodeWriter(
IFileService fileService,
DbContextWriter dbContextWriter,
EntityTypeWriter entityTypeWriter)
: base(fileService, dbContextWriter, entityTypeWriter)
{ }
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public override Task<ReverseEngineerFiles> WriteCodeAsync(
ModelConfiguration modelConfiguration,
string outputPath,
string dbContextClassName,
CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var resultingFiles = new ReverseEngineerFiles();
var generatedCode = DbContextWriter.WriteCode(modelConfiguration);
// output DbContext .cs file
var dbContextFileName = dbContextClassName + FileExtension;
var dbContextFileFullPath = FileService.OutputFile(
outputPath, dbContextFileName, generatedCode);
resultingFiles.ContextFile = dbContextFileFullPath;
foreach (var entityConfig in modelConfiguration.EntityConfigurations)
{
generatedCode = EntityTypeWriter.WriteCode(entityConfig);
// output EntityType poco .cs file
var entityTypeFileName = entityConfig.EntityType.DisplayName() + FileExtension;
var entityTypeFileFullPath = FileService.OutputFile(
outputPath, entityTypeFileName, generatedCode);
resultingFiles.EntityTypeFiles.Add(entityTypeFileFullPath);
RepositoryWriter repositoryWriter = new RepositoryWriter(new CSharpUtilities());
generatedCode = repositoryWriter.WriteCode(entityConfig);
// output Repository .cs file
var repositoryFileName = entityConfig.EntityType.DisplayName() + "Repository" + FileExtension;
var repositoryFileFullPath = FileService.OutputFile(
outputPath, repositoryFileName, generatedCode);
}
return Task.FromResult(resultingFiles);
}
}
}
我上面描述的问题位于 CustomDesignTimeServicesBuilder.cs
文件中,是因为这一行:
return base.ConfigureServices(services);
需要成为...
return services;
基本上我相信我通过再次调用基地 DesignTimeServicesBuilder
来覆盖我的注入。
尝试使用基本抽象 class CodeWriter
而不是 StringBuilderCodeWriter
如下:
public class CustomStringBuilderCodeWriter : CodeWriter
然后在CustomDesignTimeServicesBuilder
中添加服务注入如下:
protected override IServiceCollection ConfigureServices(IServiceCollection services) {
services.AddSingleton<CSharpHelper>();
services.AddSingleton<CSharpMigrationOperationGenerator>();
services.AddSingleton<CSharpSnapshotGenerator>();
services.AddSingleton<MigrationsCodeGenerator, CSharpMigrationsGenerator>();
services.AddScaffolding();
services.AddSingleton<CodeWriter, CustomStringBuilderCodeWriter>();
services.AddLogging();
return services;
}
我正在尝试用我自己的自定义实现替换 Microsoft.EntityFrameworkCore.Design
中的 StringBuilderCodeWriter
,以便修改脚手架以生成存储库模式 classes。
我正在重写 DesignTimeServicesBuilder
中的 ConfigureServices
方法来添加我的 CustomStringBuilderCodeWritter
但我无法让它使用我的实现。
我正在使用 EF Core 1.1 在 .NET Core 控制台应用程序中对此进行测试
Program.cs
using System.Collections.Generic;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
namespace RepositoryPattern
{
public class Program
{
public static void Main(string[] args)
{
IOperationReportHandler handler = new OperationReportHandler();
IOperationReporter reporter = new OperationReporter(handler);
var startup = new StartupInvoker(reporter, Assembly.Load(new AssemblyName("Microsoft.EntityFrameworkCore.Design")), "ADONET_DATA_DIR", @"ANOTHER_OUTPUT_PATH");
CustomDesignTimeServicesBuilder servicesBuilder = new CustomDesignTimeServicesBuilder(startup);
var services = servicesBuilder.Build("Microsoft.EntityFrameworkCore.SqlServer");
var generator = services.GetRequiredService<ReverseEngineeringGenerator>();
// The TableSelectionSet seems to be ignored for some reason, ignore for now.
var tableSelectionSet = new TableSelectionSet(new List<string> { "Customers", "Employees" }, new List<string> { "dbo" });
var configuration = new ReverseEngineeringConfiguration
{
ConnectionString = @"Server=(localdb)\Samples;Database=Northwind;Trusted_Connection=True;",
ContextClassName = "NorthwindContext",
ProjectPath = @"PROJECT_PATH_GOES_HERE",
ProjectRootNamespace = "RepositoryPattern",
OutputPath = @"WHERE_THE_GENERATED_FILES_GO",
TableSelectionSet = tableSelectionSet,
UseFluentApiOnly = true,
OverwriteFiles = true
};
generator.GenerateAsync(configuration, new CancellationToken());
}
}
}
CustomDesignTimeServicesBuilder.cs
using Microsoft.EntityFrameworkCore.Migrations.Design;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.Extensions.DependencyInjection;
namespace RepositoryPattern
{
public class CustomDesignTimeServicesBuilder : DesignTimeServicesBuilder
{
public CustomDesignTimeServicesBuilder(StartupInvoker startupInvoker) : base(startupInvoker)
{ }
protected override IServiceCollection ConfigureServices(IServiceCollection services)
{
services.AddSingleton<CSharpHelper>();
services.AddSingleton<CSharpMigrationOperationGenerator>();
services.AddSingleton<CSharpSnapshotGenerator>();
services.AddSingleton<MigrationsCodeGenerator, CSharpMigrationsGenerator>();
services.AddScaffolding();
services.AddSingleton<StringBuilderCodeWriter, CustomStringBuilderCodeWriter>();
services.AddLogging();
return base.ConfigureServices(services);
}
}
}
CustomStringBuilderCodeWriter.cs 此实现在循环 EntityConfigurations 时额外创建 class 以生成存储库样式 class.
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Configuration.Internal;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
namespace RepositoryPattern
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class CustomStringBuilderCodeWriter : StringBuilderCodeWriter
{
public CustomStringBuilderCodeWriter(
IFileService fileService,
DbContextWriter dbContextWriter,
EntityTypeWriter entityTypeWriter)
: base(fileService, dbContextWriter, entityTypeWriter)
{ }
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public override Task<ReverseEngineerFiles> WriteCodeAsync(
ModelConfiguration modelConfiguration,
string outputPath,
string dbContextClassName,
CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
var resultingFiles = new ReverseEngineerFiles();
var generatedCode = DbContextWriter.WriteCode(modelConfiguration);
// output DbContext .cs file
var dbContextFileName = dbContextClassName + FileExtension;
var dbContextFileFullPath = FileService.OutputFile(
outputPath, dbContextFileName, generatedCode);
resultingFiles.ContextFile = dbContextFileFullPath;
foreach (var entityConfig in modelConfiguration.EntityConfigurations)
{
generatedCode = EntityTypeWriter.WriteCode(entityConfig);
// output EntityType poco .cs file
var entityTypeFileName = entityConfig.EntityType.DisplayName() + FileExtension;
var entityTypeFileFullPath = FileService.OutputFile(
outputPath, entityTypeFileName, generatedCode);
resultingFiles.EntityTypeFiles.Add(entityTypeFileFullPath);
RepositoryWriter repositoryWriter = new RepositoryWriter(new CSharpUtilities());
generatedCode = repositoryWriter.WriteCode(entityConfig);
// output Repository .cs file
var repositoryFileName = entityConfig.EntityType.DisplayName() + "Repository" + FileExtension;
var repositoryFileFullPath = FileService.OutputFile(
outputPath, repositoryFileName, generatedCode);
}
return Task.FromResult(resultingFiles);
}
}
}
我上面描述的问题位于 CustomDesignTimeServicesBuilder.cs
文件中,是因为这一行:
return base.ConfigureServices(services);
需要成为...
return services;
基本上我相信我通过再次调用基地 DesignTimeServicesBuilder
来覆盖我的注入。
尝试使用基本抽象 class CodeWriter
而不是 StringBuilderCodeWriter
如下:
public class CustomStringBuilderCodeWriter : CodeWriter
然后在CustomDesignTimeServicesBuilder
中添加服务注入如下:
protected override IServiceCollection ConfigureServices(IServiceCollection services) {
services.AddSingleton<CSharpHelper>();
services.AddSingleton<CSharpMigrationOperationGenerator>();
services.AddSingleton<CSharpSnapshotGenerator>();
services.AddSingleton<MigrationsCodeGenerator, CSharpMigrationsGenerator>();
services.AddScaffolding();
services.AddSingleton<CodeWriter, CustomStringBuilderCodeWriter>();
services.AddLogging();
return services;
}