1

Ich versuche, die StringBuilderCodeWriter in Microsoft.EntityFrameworkCore.Design mit meiner eigenen benutzerdefinierten Implementierung zu ersetzen, um das Gerüst zu ändern, um Repository-Musterklassen zu generieren.Ersetzen von Diensten in EntityFrameworkCore.Design (DesignTimeServicesBuilder.cs)

Ich überschreibe die ConfigureServices Methode in der DesignTimeServicesBuilder, um meine CustomStringBuilderCodeWritter hinzuzufügen, aber ich kann es nicht bekommen, meine Implementierung zu verwenden.

ich dies testen EF-Core in einer .NET-Core-Konsole App aus 1,1

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 Diese Implementierung erstellt eine zusätzliche Klasse, während EntityConfigurations durchlaufen werden, um eine Repository-Stilklasse zu generieren.

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); 
     } 
    } 
} 

Antwort

0

Mein oben beschriebene Problem wurde in der CustomDesignTimeServicesBuilder.cs Datei befindet und war wegen dieser Zeile:

return base.ConfigureServices(services);

die ...

Grundsätzlich

return services;

werden benötigt Ich glaube, dass ich meine Injektion überschrieb, indem ich einen weiteren Anruf an die Basismachte.

1

Try Basis abstrakte Klasse CodeWriter statt StringBuilderCodeWriter wie folgt zu verwenden: Injektion in CustomDesignTimeServicesBuilder

public class CustomStringBuilderCodeWriter : CodeWriter 

Dann fügen Sie Service wie folgt:

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; 
} 
Verwandte Themen