Home > database >  Use single instance of class across many classes
Use single instance of class across many classes

Time:06-06

On an Net.Core 6 project I have the IEndpoint extension

public interface IEndpoint {
  void Map(IEndpointRouteBuilder builder);  
}

And an implementation example:

public class CountryEndpoint : IEndpoint {
  
  public void Map(IEndpointRouteBuilder builder) {

    builder.MapGet("countries", async ([FromServices] IService service) => {
      List<Country> countries = await service.GetCountries();
      return Results.Ok(countries);
    })
    .WithName("Countries");
    .WithApiVersionSet(versionSet)
    .MapToApiVersion( 1.0 );

  }

}

I configure the endpoints on my application using:

builder.Services.AddEndpoints(typeof(Program));

WebApplication application = builder.Build();

application.MapEndpoints();

Where AddEndpoints and MapEndpoints extensions are:

public static IServiceCollection AddEndpoints(this IServiceCollection services, params Type[] types) {

  services
    .Scan(x => x.FromAssembliesOf(types).AddClasses(y => y.AssignableTo(typeof(IEndpoint))).AsImplementedInterfaces().WithScopedLifetime());

  return services;

}

public static class ApplicationBuilderExtensions {

  public static IEndpointRouteBuilder MapEndpoints(this IEndpointRouteBuilder builder) {

    using (IServiceScope scope = builder.ServiceProvider.CreateScope()) {
      IEnumerable<IEndpoint> endpoints = scope.ServiceProvider.GetServices<IEndpoint>();

      foreach (IEndpoint endpoint in endpoints)
        endpoint.Map(builder);
    }

    return builder;

  }

}

Question

On CountryEndpoint's Map` method I have:

.WithApiVersionSet(versionSet) 

The versionSet variable is created in Program code as follows:

ApiVersionSet versionSet = application.NewApiVersionSet().HasApiVersion(new ApiVersion(1.0)).ReportApiVersions().Build();

How can I create such a variable and use it in Endpoints' Map method?

Usually the versionSet variable and the Map methods are in Program code.

CodePudding user response:

You can create static class with corresponding static field (for example a partial Program class) and use it to store the value and use it in Map:

Top-level statement (Program.cs):

...
ApiVersionSet versionSet = application.NewApiVersionSet().HasApiVersion(new ApiVersion(1.0)).ReportApiVersions().Build();
VersionSet  = versionSet;
application.MapEndpoints(); // use Program.VersionSet in IEndpoint.Map implementation
...

// end of top-level statement
static partial class Program
{
    internal static ApiVersionSet VersionSet {get;set;}
}

But I would argue that making ApiVersionSet a parameter of IEndpoint.Map and ApplicationBuilderExtensions.MapEndpoints would be a much better approach:

public interface IEndpoint {
  void Map(IEndpointRouteBuilder builder, ApiVersionSet versionSet);  
}

public static class ApplicationBuilderExtensions {
  public static IEndpointRouteBuilder MapEndpoints(this IEndpointRouteBuilder builder, ApiVersionSet versionSet) {

    using (IServiceScope scope = builder.ServiceProvider.CreateScope()) {
      IEnumerable<IEndpoint> endpoints = scope.ServiceProvider.GetServices<IEndpoint>();

      foreach (IEndpoint endpoint in endpoints)
        endpoint.Map(builder, versionSet); // pass it here
    }

    return builder;
  }
}

And in top-level statement:

ApiVersionSet versionSet = ...;
application.MapEndpoints(versionSet);
  • Related