Skip to content

Instantly share code, notes, and snippets.

@chgeuer
Last active May 6, 2020 10:49
Show Gist options
  • Save chgeuer/47267184d8689e9ead93db01dea41cbb to your computer and use it in GitHub Desktop.
Save chgeuer/47267184d8689e9ead93db01dea41cbb to your computer and use it in GitHub Desktop.
namespace PlayingWithIoCWebApp
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
public class Startup
{
public Startup(IConfiguration configuration) { Configuration = configuration; }
public IConfiguration Configuration { get; }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
// inject an Observable
services.AddSingleton<IObservable<WeatherForecast>>(_ => SomeDataSource.WeatherData);
// inject a transient dependency (which will require SomeSpecificSingletonDependency)
services.AddTransient<ISomeValueProvider, SomeEphemeralThing>();
// inject a functional dependency
services.AddSingleton<Func<Task<Secret>>>(_ => ExternalThing.GetSecret);
// inject a transient dependency
services.AddSingleton(_ => new SomeSpecificSingletonDependency(someValue: Guid.NewGuid().ToString()));
// inject a transient (main) dependency
services.AddTransient<IWeatherForecastService, WeatherForecastService>();
}
}
public class Secret
{
public string SecretValue { get; set; }
}
public static class ExternalThing
{
public static async Task<Secret> GetSecret()
{
await Console.Out.WriteLineAsync("Somebody wants a secret");
await Task.Delay(TimeSpan.FromSeconds(1));
return new Secret { SecretValue = "some secret" };
}
}
public interface ISomeValueProvider
{
string SomeValue { get; }
}
public class SomeEphemeralThing : ISomeValueProvider
{
public string SomeValue { get; }
public SomeEphemeralThing(SomeSpecificSingletonDependency otherDependency)
{
var myOwnIdentity = Guid.NewGuid();
this.SomeValue = $"{otherDependency.SomeValue} -- {myOwnIdentity}";
}
}
public class SomeSpecificSingletonDependency
{
public string SomeValue { get; }
public SomeSpecificSingletonDependency(string someValue) { this.SomeValue = someValue; }
}
public static class SomeDataSource
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
public static IObservable<WeatherForecast> WeatherData
{
get
{
var rng = new Random();
return Observable.Create<WeatherForecast>(observer =>
{
foreach (var index in Enumerable.Range(1, 5))
{
var item = new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
};
observer.OnNext(item);
}
observer.OnCompleted();
return Disposable.Empty;
});
}
}
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
public interface IWeatherForecastService
{
Task<ResponseType> CreateForecast();
}
public class WeatherForecastService : IWeatherForecastService
{
private readonly ILogger<WeatherForecastController> _logger;
private readonly IObservable<WeatherForecast> getWeatherForecastData;
private readonly SomeSpecificSingletonDependency someSingleton;
private readonly ISomeValueProvider ephemeralThingie;
private readonly Func<Task<Secret>> getSecret;
public WeatherForecastService(
ILogger<WeatherForecastController> logger,
IObservable<WeatherForecast> getWeatherForecastData,
Func<Task<Secret>> getSecret,
SomeSpecificSingletonDependency someSingleton,
ISomeValueProvider ephemeralThingie)
{
_logger = logger;
this.getWeatherForecastData = getWeatherForecastData;
this.someSingleton = someSingleton;
this.ephemeralThingie = ephemeralThingie;
this.getSecret = getSecret;
}
async Task<ResponseType> IWeatherForecastService.CreateForecast()
{
var secret = await this.getSecret();
var weather = getWeatherForecastData.ToEnumerable();
return new ResponseType
{
Secret = secret.SecretValue,
Weather = weather,
SingletonValue = this.someSingleton.SomeValue,
EphemeralValue = this.ephemeralThingie.SomeValue,
};
}
}
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly IWeatherForecastService weatherService;
public WeatherForecastController(IWeatherForecastService weatherService) { this.weatherService = weatherService; }
[HttpGet]
public Task<ResponseType> Get() => weatherService.CreateForecast();
}
public class ResponseType
{
public string Secret { get; set; }
public string EphemeralValue { get; set; }
public string SingletonValue { get; set; }
public IEnumerable<WeatherForecast> Weather { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment