最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#在MEF框架中實(shí)現(xiàn)延遲加載部件

 更新時(shí)間:2022年06月23日 11:29:02   作者:天方  
這篇文章介紹了C#在MEF框架中實(shí)現(xiàn)延遲加載部件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

在MEF的宿主中,當(dāng)我們通過(guò)Import聲明導(dǎo)入的對(duì)象時(shí),組裝(Compose)的時(shí)候會(huì)創(chuàng)建該對(duì)象。例如:

    interface ILogger
    {
        void Log(string message);
    }

    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("logger 1" + message);
        }
    }

    class Host
    {
        [Import]
        ILogger _logger = null;

        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);

            //這兒會(huì)創(chuàng)建ConsoleLogger對(duì)象
            container.ComposeParts(this);

            _logger.Log("hello world");
        }
    }

有的時(shí)候,有些組件的創(chuàng)建開(kāi)銷比較大,但又不會(huì)立即使用。此時(shí),我們希望通過(guò)延遲初始化的方式將其延遲到使用的時(shí)候創(chuàng)建,從而提高性能(常見(jiàn)的是提高啟動(dòng)速度)。MEF是支持這一模式的,我們只需要修改一下導(dǎo)入的聲明形式即可。

    [Import]
    Lazy<ILogger> _logger = null;

這樣,Logger就會(huì)延遲到第一次使用的時(shí)候創(chuàng)建了。

元數(shù)據(jù)MetaData

有的時(shí)候,對(duì)于同一個(gè)服務(wù)有多個(gè)提供者,我們需要從中選擇一個(gè)使用。MEF提供了ImportMany來(lái)解決這一需求。

有的時(shí)候,對(duì)于同一個(gè)服務(wù)有多個(gè)提供者,我們需要從中選擇一個(gè)使用。MEF提供了ImportMany來(lái)解決這一需求。

    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

    [Export(typeof(ILogger))]
    class DbLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

    class Host
    {
        [ImportMany]
        ILogger[] _logger = null;


        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);

            container.ComposeParts(this);

            _logger.FirstOrDefault(i => i is DbLogger).Log("hello world");
        }
    }

此時(shí),如果我們想使用延遲導(dǎo)入的時(shí)候,就會(huì)變成如下形式:

    class Host
    {
        [ImportMany]
        Lazy<ILogger>[] _loggerServices = null;

        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);

            //這兒會(huì)創(chuàng)建ConsoleLogger對(duì)象
            container.ComposeParts(this);

            _loggerServices.FirstOrDefault(i => i.Value is DbLogger).Value.Log("hello world");
        }
    }

咋一看并沒(méi)有什么問(wèn)題,所有的Logger都是延遲創(chuàng)建的。但是仔細(xì)分析一下就會(huì)發(fā)現(xiàn),要找到DbLogger的時(shí)候,必須遍歷所有的_loggerServices,這個(gè)遍歷會(huì)導(dǎo)致創(chuàng)建Logger。也就是說(shuō),使用第一個(gè)Logger的時(shí)候可能創(chuàng)建所有的Logger。

那么,如何實(shí)現(xiàn)我們只創(chuàng)建所需要的Logger呢? 這個(gè)時(shí)候就輪到元數(shù)據(jù)出場(chǎng)了,MEF中的元數(shù)據(jù)可以將一個(gè)數(shù)據(jù)附加到Export的服務(wù)對(duì)象中一并導(dǎo)出,從而可以通過(guò)元素?fù)?jù)找到對(duì)應(yīng)的服務(wù)。首先我們看看最終的效果吧:

    public interface ILoggerData
    {
        string Name { get; }
    }

    class Host
    {
        [ImportMany]
        Lazy<ILogger, ILoggerData>[] _logger = null;

        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);

            container.ComposeParts(this);

            _logger.FirstOrDefault(i => i.Metadata.Name == "DB Logger").Value.Log("hello world");
        }
    }

這里首先聲明了一個(gè)元數(shù)據(jù)類型的接口ILoggerData,然后,導(dǎo)入的對(duì)象變成了Lazy<ILogger, ILoggerData>,這個(gè)對(duì)象有一個(gè)屬性為Metadata,它的類型就是剛才聲明的ILoggerData。導(dǎo)出的ILogger對(duì)象是延遲創(chuàng)建的,而元數(shù)據(jù)不是延遲創(chuàng)建的。我們可以通過(guò)遍歷ILoggerData來(lái)找到所需要的Logger對(duì)象,從而實(shí)現(xiàn)只創(chuàng)建所使用的Logger對(duì)象。

現(xiàn)在的問(wèn)題是:如何在導(dǎo)出的時(shí)候聲明相關(guān)的元數(shù)據(jù)。MEF提供了兩種方式:

通過(guò)ExportMetadataAttribute標(biāo)記聲明

這種方式是在導(dǎo)出的服務(wù)的時(shí)候一并通過(guò)ExportMetaDataAttribute屬性標(biāo)記元素?fù)?jù):

    [ExportMetadata("Name", "Console Logger")]
    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

    [ExportMetadata("Name", "DB Logger")]
    [Export(typeof(ILogger))]
    class DbLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

ExportMetaDataAttribute有兩個(gè)參數(shù),Name和Value,Name為屬性名稱,Value為屬性值。Compse的時(shí)候,MEF會(huì)先創(chuàng)建一個(gè)實(shí)現(xiàn)了元數(shù)據(jù)對(duì)象,然后將根據(jù)將Value值賦值給Name所對(duì)應(yīng)的屬性名稱。

這么做雖然比較簡(jiǎn)單,但是它有兩個(gè)弊端:

  • 1. 屬性名稱不是強(qiáng)類型

這里我們必須字符串來(lái)給標(biāo)志屬性名稱,它們之間并沒(méi)有語(yǔ)法級(jí)的一致性檢查,在缺少nameof運(yùn)算符的現(xiàn)在,一旦元數(shù)據(jù)屬性名稱更改的話是非常容易出錯(cuò)的。

  • 2. 如果元數(shù)據(jù)有多個(gè)值的話賦值顯得非常累贅。

假如我們?cè)黾恿艘粋€(gè)Priority類型的屬性,

    public interface ILoggerData
    {
        string Name { get; }
        int Priority { get; }
    }

此時(shí),必須對(duì)所有的導(dǎo)出對(duì)象都增加一個(gè)ExportMetadata標(biāo)記,寫出如下形式:

    [ExportMetadata("Name", "DB Logger")]
    [ExportMetadata("Priority", 3)]

當(dāng)屬性更多一點(diǎn)的話相信程序員們就會(huì)罵娘了。并且一旦某個(gè)Export對(duì)象漏寫了,改對(duì)象就不會(huì)被導(dǎo)入。這個(gè)是一個(gè)運(yùn)行時(shí)的錯(cuò)誤,非常不容易排查的。

通過(guò)Attribute標(biāo)記

這種方式可以通過(guò)一個(gè)Attribute來(lái)標(biāo)記元數(shù)據(jù):

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    class LoggerDataAttribute : Attribute, ILoggerData
    {
        public string Name { get; private set; }

        public LoggerDataAttribute(string name)
        {
            this.Name = name;
        }
    }

    [LoggerData("Console Logger")]
    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger, ILoggerData
    {
        public string Name { get; set; }

        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

    [LoggerData("DB Logger")]
    [Export(typeof(ILogger))]
    class DbLogger : ILogger, ILoggerData
    {
        public string Name { get; set; }
        public void Log(string message)
        {
            Console.WriteLine(message);
        }
    }

首先,聲明一個(gè)LoggerDataAttribute,這個(gè)Attribute必須被MetadataAttribute標(biāo)記。然后,在Export的對(duì)象前加上該LoggerDataAttribute,這樣MEF導(dǎo)入的時(shí)候就會(huì)根據(jù)該LoggerDataAttribute創(chuàng)建元數(shù)據(jù)了。

值得一提的是,這里的LoggerDataAttribute本身并不需要實(shí)現(xiàn)ILoggerData接口,它是一個(gè)DuckType的約定,只需要實(shí)現(xiàn)元數(shù)據(jù)的屬性即可。我這里實(shí)現(xiàn)該接口主要是為了讓編譯器保障元數(shù)據(jù)屬性都有被準(zhǔn)確實(shí)現(xiàn)。

到此這篇關(guān)于C#在MEF框架中實(shí)現(xiàn)延遲加載部件的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

堆龙德庆县| 自贡市| 友谊县| 景宁| 南投县| 鹤岗市| 东光县| 黄山市| 砚山县| 怀安县| 武山县| 青海省| 青神县| 永兴县| 社旗县| 十堰市| 蒲江县| 桃源县| 泸溪县| 蓬溪县| 长武县| 新晃| 砚山县| 炎陵县| 贵定县| 金堂县| 天等县| 凤翔县| 长沙市| 永济市| 喀什市| 巴南区| 隆安县| 顺义区| 紫阳县| 古丈县| 伊宁县| 江山市| 玉屏| 万山特区| 松江区|