接著設計兩個 Logging 與 Error
public interface IHandler<T>
{
void Handle(Action<T> handler);
}
public interface ILogger<T>
{
void Write(Func<T,string> formatter);
}
用法大概像是這樣
public class Handler<T> : IHandler<T>
{
private T _current;
public Handler(T current)
{
this._current = current;
}
public void Handle(Action<T> handler)
=> handler(_current);
}
public class Logger<T> : ILogger<T>
{
private T _current;
private TextWriter writer;
public Logger(T current,TextWriter writer)
{
this._current = current;
this._writer = writer;
}
public void Write(Func<T,string> formatter)
{
writer.Write(formatter(_current));
}
}
這樣似乎不夠,還需要一個可以建構這些功能的方法
public interface ILoggerFactory
{
ILogger<T> Create<T>(T current);
}
public interface IHandlerFactory
{
IHandler<T> Create<T>(T current);
}
public class LoggerFactory : ILoggerFactory
{
public ILogger<T> Create<T>(T current)
=> new Logger<T>(current);
}
public class HandlerFactory : IHandlerFactory
{
public IHandler<T> Create<T>(T current)
=> new Handler<T>(current);
}
最後將原本的Chain
改作為起始物件,名為ChainFactory
public class ChainFactory : IChainFactory
{
private readonly IHandlerFactory _handler;
private readonly ILoggerFactory _logger;
public ChainFactory(ILoggerFactory logger,IHandlerFactory handler)
{
_handler = handler;
_logger = logger;
}
public IChain<T> Create<T>(Func<T> factory)
=> new LazyChain<T>(this,factory);
public IChainAwaiter<T> Create<T>(Task<T> task)
=> new ChainAwaiter<T>(this,task);
}
最後這次就偷懶仰賴一下 DI 來幫我們把剩下的做完吧
這次以 Microsoft.Extensions.DependencyInjection 作為 DI Container
同場佳映 Crawler 也放進去吧
namespace Microsoft.Extensions.DependencyInjection
{
public static class ServiceCollectionExtensions
{
public static IServiceCollection AddChain(this IServiceCollection services)
=> services.AddTransient<IChainFactory, ChainFactory>()
.AddSingleton<ILoggerFactory, LoggerFactory>()
.AddSingleton<IHandlerFactory, HandlerFactory>();
public static IServiceCollection AddCrawler(this IServiceCollection services)
=> services.AddChain()
.AddTransient<IHttpClient,DefaultHttpClient>()
.AddTransient<IHtmlLoader, DefaultHtmlLoader>()
.AddTransient<ICrawler, Crawler>();
}
}
如此一來,注入的準備就可以算是準備完成
上述的程式目的在於,將我們期望的 Logging 與 Handler 能夠注入 Chain 的功能內
再透過 Chain 來執行 Logging 與 Handler 已達成目的