MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:
 MEF中使用导出与导入,实质上就是对一个对象的实例化的过程,通过MEF的特性降低了对象的直接依赖,从而让系统的设计达到一种高灵活、高扩展性的效果。在具体的设计开发中,存在着某些对象是不需要在系统运行或者的附属对象初始化的时候进行实例化的,仅仅只需要在需要使用到他的时候才会进行实例化,从系统的上来说这也是提高系统性能的一种可行的实现方式,这种方式就可以理解为对象的迟延初始化,或者叫迟延加载。MEF也对此使用场景提供了完善的实现机制,下面来看看在MEF中的迟延初始化是如何使用的。
namespace  MEFTraining.LzayImports
{
    
public   interface  ILogger
    {
        
void  WriteLog( string  message);
    }

    [Export(
typeof (ILogger))]
    
public   class  DBLogger : ILogger
    {
        
public   void  WriteLog( string  message)
        {
            MessageBox.Show(message);
        }
    }
}
 
  通过使用前几篇博文中使用的日志组件为例,在日志记录的具体实现对象上进行对象的导出[Export]配置。如果是使用传统的方式进行部件的导入则如下代码块所示:
[Import( typeof (ILogger))]
public  ILogger Logger {  get set ; }
 
  如果需要进行迟延(Lazy)加载,MEF专门提供了用于迟延加载的方式,既使用Lazy类来完成迟延加载,然后通过其他属性Value获取到所加载到的对象。详细的使用如下代码块:
public   partial   class  MainPage : UserControl
{
    
// 传统加载
    [Import( typeof (ILogger))]
    
public  ILogger Logger {  get set ; }
    
    
// 迟延加载
    [Import]
    
public  Lazy < ILogger >  Service;

    
public  MainPage()
    {
        InitializeComponent();

        CompositionInitializer.SatisfyImports(
this );

        Logger.WriteLog(
" 日志内容 " );

        Service.Value.WriteLog(
" 日志内容 " );
    }
}
 
  通过调试输出可以得到使用迟延导入的对象的详细信息,下面是通过在命令窗口中输出的Service和Service.Value的详细信息。
Service
ThreadSafetyMode
= PublicationOnly, IsValueCreated = true , IsValueFaulted = false , Value = {MEFTraining.LzayImports.DBLogger}
    IsValueCreated: 
true
Service.Value
{MEFTraining.LzayImports.DBLogger}
    [MEFTraining.LzayImports.DBLogger]: {MEFTraining.LzayImports.DBLogger}
 
   迟延加载还支持元数据的导出和导入,主要使用[MetadataAttribute]特性实现,实际开发中可以进行自定义元数据结构,这里以一个空的元数据接口进行元数据的导入应用演示。
public   interface  IMetadata
{
      
}
 
  在导出部件中就可以使用元数据特性进行声明,如下简单的应用。
[MetadataAttribute]
[Export(
typeof (Users))]
public   class  Users
{
    
public   string  UserName  =   " 张三 " ;
}
 
  元数据的导入应用如下代码块所示:
public   partial   class  MetadataControl : UserControl
{
    [Import(
typeof (Users))]
    
public  Lazy < Users,IMetadata >  Users {  get set ; }

    
public  MetadataControl()
    {
        InitializeComponent();

        
// 宿主MEF托管扩展容器
        CompositionInitializer.SatisfyImports( this );

        MessageBox.Show(Users.Value.UserName);
    }
}
 
  对于的调试输出为下面代码块所示:
Users
ThreadSafetyMode
= PublicationOnly, IsValueCreated = true , IsValueFaulted = false Value = {MEFTraining.LzayImports.Users}
    
base  {System.Lazy < MEFTraining.LzayImports.Users > }: ThreadSafetyMode = PublicationOnly, IsValueCreated = true , IsValueFaulted = false , Value = {MEFTraining.LzayImports.Users}
    Metadata: {_proxy_MEFTraining.LzayImports.IMetadata_0174a468
- 9771 - 4271 - a37e - 9a4a83eca6bd}
 
  MEF中也提供了专门用于元数据导入、导出的特性[ExportMetadata],使用ExportMetadata基本可以满足大部分元数据的导出、导入支持。通过修改上面的示例来实现自定义元数据结构的导入、导出应用演示。
public   interface  IMetadata
{
    
string  Name {  get ; }
}

[ExportMetadata(
" Name " , " 李四 " )]
[Export(
typeof (Users))]
public   class  Users
{
    
public   string  UserName  =   " 张三 " ;
}
 
  上面的示例代码演示了通过元数据导出属性名为“Name”,其值为“李四”的元数据信息,并且还定义了一个用于承载元数据结构的结构,接下来就可以通过迟延加载导入,进行元数据的获取了。
public   partial   class  MetadataControl : UserControl
{
    [Import(
typeof (Users))]
    
public  Lazy < Users,IMetadata >  Users {  get set ; }

    
public  MetadataControl()
    {
        InitializeComponent();

        
// 宿主MEF托管扩展容器
        CompositionInitializer.SatisfyImports( this );

        MessageBox.Show(Users.Value.UserName);
    }
}
 
  下图为允许调试中的截图,可以很清楚的看到,在进行迟延导入的时候已经将导出部件中的元数据信息成功的导入到了当前对象实例属性中。
    
 
  下面是完整的元数据应用实例代码。
namespace  MEFTraining.LzayImports
{
    
public   partial   class  MetadataControl : UserControl
    {
        [Import(
typeof (Users))]
        
public  Lazy < Users,IMetadata >  Users {  get set ; }

        
public  MetadataControl()
        {
            InitializeComponent();

            
// 宿主MEF托管扩展容器
            CompositionInitializer.SatisfyImports( this );

            MessageBox.Show(Users.Value.UserName);
        }
    }

    
public   interface  IMetadata
    {
        
string  Name {  get ; }
    }

    [ExportMetadata(
" Name " , " 李四 " )]
    [Export(
typeof (Users))]
    
public   class  Users
    {
        
public   string  UserName  =   " 张三 " ;
    }
}
 
   除此之外,迟延加载也是支持弱类型的元数据类型的,也可以对元数据进行过滤,这里就不做详细的介绍,有兴趣的朋友可以自己去研究研究。




本文转自 beniao 51CTO博客,原文链接:http://blog.51cto.com/beniao/349732,如需转载请自行联系原作者

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
5月前
|
存储 JSON 数据格式
Spartacus i18n Resource 的默认加载和 Lazy Load 两种方式的比较
Spartacus i18n Resource 的默认加载和 Lazy Load 两种方式的比较
|
12月前
|
前端开发
Spartacus 应用中 Lazy Loaded Module 初始化逻辑的实现方案
Spartacus 应用中 Lazy Loaded Module 初始化逻辑的实现方案
|
Java 数据库 OceanBase
,Store组件的JVM参数
,Store组件的JVM参数
162 1
user.config.ts文件里定义的配置是如何合并到SAP Spartacus的标准配置里去的
user.config.ts文件里定义的配置是如何合并到SAP Spartacus的标准配置里去的
user.config.ts文件里定义的配置是如何合并到SAP Spartacus的标准配置里去的
|
JavaScript 前端开发
SAP Spartacus module 延迟加载和正常加载的 chunk 内容差异
SAP Spartacus module 延迟加载和正常加载的 chunk 内容差异
SAP Spartacus module 延迟加载和正常加载的 chunk 内容差异
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
104 0
SAP Spartacus lazy load module 里包含了被其他 Component 静态引用的组件该怎么办
|
存储 容器
SAP Spartacus table cell如何通过cxOutlet在运行时动态注入组件
SAP Spartacus table cell如何通过cxOutlet在运行时动态注入组件
SAP Spartacus table cell如何通过cxOutlet在运行时动态注入组件
[重要!] SAP Spartacus加载网络请求的entity状态切换,统一在loader.reducer.ts里完成
[重要!] SAP Spartacus加载网络请求的entity状态切换,统一在loader.reducer.ts里完成
84 0
[重要!] SAP Spartacus加载网络请求的entity状态切换,统一在loader.reducer.ts里完成
SAP Spartacus Unit List树形数据的加载触发时机
SAP Spartacus Unit List树形数据的加载触发时机
SAP Spartacus Unit List树形数据的加载触发时机
以 library 方式启动的 SAP Spartacus Storefront,如何手动实现 User 模块的延迟加载
以 library 方式启动的 SAP Spartacus Storefront,如何手动实现 User 模块的延迟加载
以 library 方式启动的 SAP Spartacus Storefront,如何手动实现 User 模块的延迟加载