iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 28
0
Software Development

如何讓程式碼告訴你他在做什麼?系列 第 29

Day-28 想要做什麼東西,蓋工廠就對了

接著設計兩個 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 已達成目的

備註:


  • 如您目前是團隊工作,則請遵守團隊所訂下的撰寫規範,此篇文章僅為參考建議使用
  • 在.Net Core 上的模組化已經可以單純用 AddChain or AddCrawler 來完成
  • 這也是為什麼在.Net Core上可以 AddMvc 的理由,當然啦,實際內容不會像上面那樣單純
  • 透過同樣的設定方式做為開發的準則,我個人是覺得可以有效幫助程式的質感和泛用性

上一篇
Day-27 如空氣一般的 Log
下一篇
Day-29 Morpheus : Free Your Mind
系列文
如何讓程式碼告訴你他在做什麼?31

尚未有邦友留言

立即登入留言