MEF筆記 之延遲加載


文章參考:在MEF中實現延遲加載部件  作者:TianFang

 僅有一個服務提供者時候

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

namespace 延遲加載
{
    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]
        //延遲加載
        Lazy<ILogger> _logger;
        //非延遲加載
        //ILogger _logger;
        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);

            //如果不是延遲加載的話這兒會創建ConsoleLogger對象
            container.ComposeParts(this);
            //非延遲加載
            //_logger.Log("logworld");
            //延遲加載
            _logger.Value.Log("hello world");

        }
    }
}
View Code

 

 當某一組件並不是立刻需要使用,或者內存開銷很大。影響程序加載的速度。比如當程序啟動的時候。這個時候我們可以使用延遲加載,也就是只有當程序用到的時候才會去加載該部件。我們可以使用Lazy<T>來標記導入的類型。這樣就簡單的實現了延遲加載。

注意如果使用Lazy<T>來標記對象類型的話,需要通該實例的Value屬性調用實例方法 _logger.Value.Log("hello world");

如果是非延遲加載

如果延遲加載:

 

當有多個服務提供者的時候

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延遲加載
{
    interface ILogger
    {
        void Log(string message);
    }
    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("ConsoleLogger    " + message);
        }
    }

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

    class Host
    {   //非延遲加載
        //[ImportMany]
        //ILogger[] _logger = null;
        //延遲加載
        [ImportMany]
        Lazy<ILogger>[] _Lazylogger = 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");
            //延遲加載,當調用的時候才創建對象,
            //但是因為這兒有一個遍歷,所以當調用一個對象的時候就會創建所以對象
            _Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
        }
    }
}
View Code

 

此時可以用ImportMany標記導入,同時用Lazy<T>包裝我們的導入類型。但是此時有個問題,就是當我們如果通過類型遍歷多個對象尋找可用導入時候,會創建所有對象。所以此時我們可以用元數據來判斷是否使我們需要的導入。

通過元數據匹配需要的導入

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延遲加載
{
    interface ILogger
    {
        void Log(string message);
    }
    //通過標記元數據來標記導出服務
    [ExportMetadata("Name", "Console Logger")]
    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("ConsoleLogger    " + message);
        }
    }
    //通過標記元數據來標記導出服務
    [ExportMetadata("Name", "DbLogger")]
    [Export(typeof(ILogger))]
    class DbLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("DbLogger    " + message);
        }
    }
    public interface ILoggerData
    {
        string Name { get; }
    }
    class Host
    {
        //延遲加載
        [ImportMany]
        Lazy<ILogger,ILoggerData>[] _Lazylogger = null;
        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);
            //非延遲加載此時會創建所有對象
            container.ComposeParts(this);
            //延遲加載,當調用的時候才創建對象,
            //但是因為這兒有一個遍歷,所以當調用一個對象的時候就會創建所以對象
            //_Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
            _Lazylogger.FirstOrDefault(i => i.Metadata.Name == "DbLogger").Value.Log("DbLogger");

        }
    }
}
View Code

通過元數據可以匹配我們需要的導出服務。但是,通過單純的標記  [ExportMetadata("Name", "DbLogger")]很麻煩,而且屬性筆記多的時候代碼也不整潔。對此我們可以封裝一個元數據特性

   

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
namespace 延遲加載
{
    interface ILogger
    {
        void Log(string message);
    }
    //通過標記元數據來標記導出服務
     [LoggerData("Console Logger")]
    [Export(typeof(ILogger))]
    class ConsoleLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("ConsoleLogger    " + message);
        }
    }
    //通過標記元數據來標記導出服務
    [LoggerData("DbLogger")]
    [Export(typeof(ILogger))]
    class DbLogger : ILogger
    {
        public void Log(string message)
        {
            Console.WriteLine("DbLogger    " + message);
        }
    }
    public interface ILoggerData
    {
        string Name { get; }
    }
    [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;
        }
    }
    class Host
    {
        //延遲加載
        [ImportMany]
        Lazy<ILogger, ILoggerData>[] _Lazylogger = null;
        public Host()
        {
            var catalog = new AssemblyCatalog(this.GetType().Assembly);
            var container = new CompositionContainer(catalog);
            //非延遲加載此時會創建所有對象
            container.ComposeParts(this);
            //延遲加載,當調用的時候才創建對象,
            //但是因為這兒有一個遍歷,所以當調用一個對象的時候就會創建所以對象
            //_Lazylogger.FirstOrDefault(i => i.Value is DbLogger).Value.Log("DbLogger");
            _Lazylogger.FirstOrDefault(i => i.Metadata.Name == "DbLogger").Value.Log("DbLogger");

        }
    }
}

 

本文地址:http://www.cnblogs.com/santian/p/4357324.html

博客地址:http://www.cnblogs.com/santian/

轉載請以超鏈接形式標明文章原始出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM