我目前正在學習 DI 并進行實驗。這是我的練習代碼,只是一個概述,我所做的就像模仿一個駕駛模擬器游戲,玩家在他們的車庫里有兩輛車:本田和豐田。并且玩家先用本田,然后換豐田,再換回本田。
using Microsoft.Extensions.DependencyInjection;
using System;
using Microsoft.Extensions.Hosting;
using static System.Guid;
namespace ConsoleApp2
{
// ----------- CARS
public interface ICar
{
string Description { get; }
}
public class Honda : ICar
{
private string Id = NewGuid().ToString()[^4..]; // just to see if instance has changed
public string Description => "HONDA " Id;
}
public class Toyota : ICar
{
private string Id = NewGuid().ToString()[^4..]; // just to see if instance has changed
public string Description => "TOYOTA " Id;
}
// ----------- CAR FACTORY
public enum CarType
{
Unknown,
Honda,
Toyota
}
public interface ICarFactory
{
CarType CarType { set; }
ICar GetCar();
}
public class CarFactory : ICarFactory
{
ICar _car;
CarType _carType = CarType.Unknown;
public CarType CarType
{
set
{
if(_carType != value)
{
switch (value)
{
case CarType.Honda: _car = new Honda(); break;
case CarType.Toyota: _car = new Toyota(); break;
default: throw new NotImplementedException();
}
_carType = value;
}
}
}
public ICar GetCar() { return _car; }
}
// ----------- MAIN
class Program
{
static void Main(string[] args)
{
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddSingleton<ICarFactory, CarFactory>())
.Build();
// --------------
ChooseCar(host.Services, CarType.Honda); // user chooses Honda
// lets say a user changed a configuration and wants to use Toyota all through
ChooseCar(host.Services, CarType.Toyota);
// lets say a user changed a configuration and wants to use the same Honda (previous selection)
ChooseCar(host.Services, CarType.Honda);
}
static void ChooseCar(IServiceProvider services, CarType c)
{
using IServiceScope serviceScope = services.CreateScope();
IServiceProvider provider = serviceScope.ServiceProvider;
var carfactory = provider.GetRequiredService<ICarFactory>();
carfactory.CarType = c;
Console.WriteLine("Using:" carfactory.GetCar().Description);
Console.WriteLine("Using:" carfactory.GetCar().Description);
}
}
}
這是輸出:
Using:HONDA 6573
Using:HONDA 6573
Using:TOYOTA c20f
Using:TOYOTA c20f
Using:HONDA b537
Using:HONDA b537
根據這個輸出,最后一部分回傳的 Honda 與第一個不同的實體,但是,玩家想要以前的 Honda。現在,我可以讓工廠處理/記住這些實體,以確保它會回傳以前的本田。但是,我認為工廠做得比它應該做的要多,我想知道 DI 框架在這方面是否可以提供幫助?如果我繼續這個想法,工廠正在做大部分作業來處理以前的 ICar 實體。我只希望工廠只負責生產新車,不記得是否制造了以前的實體。
如果 DI 有什么可以幫助消除工廠的,那就更好了。我現在在想的是,每次更改設定時都呼叫下面的代碼并更改 ICar 以回傳豐田或本田,但是每次創建構建器并重新配置服務是一種不好的做法嗎?
using IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
services.AddSingleton<ICar, Honda>()) // or Toyota, depending on what is needed
.Build();
另外,如果我這樣做,我將如何處理車庫中有兩個或多個豐田(或本田)的情況(例如,有豐田 RAV-4 和豐田普銳斯,豐田普銳斯和 ToyotaRav4 可能有不同的等級) ?
基本上,我的最終目標是讓 DI 根據用戶選擇回傳本田或豐田,如果可能的話,不使用工廠。
uj5u.com熱心網友回復:
我曾經使用這種方法解決多個實作問題:
public interface ICar
{
}
public class Honda : ICar { }
public class Toyota : ICar { }
public interface ICarProvider<TCar> where TCar : ICar
{
ICar ProvideCar();
}
public class CarProvider<TCar> : ICarProvider<TCar> where TCar : ICar, new()
{
private ICar _car;
public ICar ProvideCar()
{
if (_car == null)
{
_car = new TCar();
}
return _car;
}
}
然后在你的啟動中,你需要有這個:
services.AddSingleton<ICarProvider<Toyota>, CarProvider<Toyota>>();
services.AddSingleton<ICarProvider<Honda>, CarProvider<Honda>>();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/407934.html
標籤:
上一篇:MediatRIPipelineBehavior<TRequest,TResponse>錯誤為型別“TRequest”不能用作泛型型別或方法中的型別引數“TRequest”
