MEF初体验之九:部件生命周期

理解MEF容器中部件的生命周期及其含义是非常重要的。鉴于MEF重点在开放端应用程序,这将变得尤其重要的,一旦app ships和第三方扩展开始运行,作为应用程序的开发者将很好地控制这一系列的部件。生命周期可以被解释为这样一个部件期望的共享物,无论是一个新的部件被创建还是一个部件被关闭或释放都由控制策略来翻译。

Shared, Non Shared and ownership

通过使用PartCreationPolicyAttribute特性设置CreationPolicy(类级别)来定义一个部件的共享物。下面的值是受支持的:
Shared:部件作者告诉MEF,一个部件的实例可以存在在每一个容器中(指定将由容器创建关联的该ComposablePart 的单个共享实例,并由所有请求者共享该实例)
NonShared:部件作者告诉MEF,一个部件每一次的导出请求都将由一个部件新的实例来提供服务。(指定将由容器为每个请求者创建一个关联的该ComposablePart的新的非共享实例)
Any or not supplied value:部件作者允许部件既可以支持Shared,也可以支持NonShared.

可以使用[System.ComponentModel.Composition.PartCreationPolicyAttribute]特性在一个部件上定义创建策略:

[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IMessageSender))]
public class SmtpSender : IMessageSender
{
}

这个容器将一直拥有它创建的部件的所有权。换句话说,该所有权从不会转移到一个通过使用容器实例(直接地)或一个导入(间接地)来请求它的行动者上来。

导入也可以定义或者约束这种被用来提供导入值的部件策略创建。你需要做的一切是为RequiredCreationPolicy指定CreationPolicy枚举值:

[Export]
public class Importer
{[Import(RequiredCreationPolicy=CreationPolicy.NonShared)]public Dependency Dep { get; set; }
}

对于与importer相关的部件需要使用共享的场景来说是很用的。默认地,RequiredCreationPolicy被设置为Any,因此Shared或者NonShared部件都可以提供值。

-Part.AnyPart.SharedPart.NonShared
Import.AnySharedSharedNon Shared
Import.SharedSharedSharedNo Match
Import.NonSharedNon SharedNo MatchNon Shared

 

 

 

 

 注意:当两边都定义CreationPolicy为Any,结果它将是一个Shared部件。

来个例子:

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;namespace PartLifetime
{class Program{[ImportMany(RequiredCreationPolicy=CreationPolicy.Shared)]public IEnumerable<IMessageSender> Senders { get; set; }static void Main(string[] args){Program p = new Program();p.Compose();foreach (var item in p.Senders){item.Send("Hi,MEF");}Console.ReadKey();}void Compose(){AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());var container = new CompositionContainer(catalog);container.ComposeParts(this);}}interface IMessageSender{void Send(string msg);}[Export(typeof(IMessageSender))][PartCreationPolicy(CreationPolicy.Shared)]class EmailSender : IMessageSender{public void Send(string msg){Console.WriteLine("Email sent:" + msg);}}[Export(typeof(IMessageSender))][PartCreationPolicy(CreationPolicy.NonShared)]class SMSSender : IMessageSender{public void Send(string msg){Console.WriteLine("SMS sent:" + msg);}}}

我们发现,当Import的请求创建策略为Shared,则自动匹配EmailSender组件;当为NonShared时,自动匹配SMSSende组件;当省略或者为Any时,自动匹配Shared和NonShared。

释放容器

通常,一个容器实例是部件生命周期的持有者。由容器创建的部件实例拥有的生命周期取决于容器的生命周期。标志容器生命周期结束的方式是释放它。释放一个容器的含义是:

  • 实现IDisposable接口的部件将会调用Dispose方法
  • 被容器占有的部件的引用将被清除
  • Shared组件将被释放和清除
  • Lazy导出组件在容器被释放后将不会工作
  • 操作可能会抛出System.ObjectDisposedExecption

容器和部件引用

我们相信,.Net GC是适当地清理可依赖的最好的东西。然后,我们也需要提供一个有确定性行为的容器。因此,这个容器将不会拥有它创建的部件的引用,除非下面的条件之一成立:

  • 这个部件被标记为Shared
  • 这个部件实现了IDisposable接口
  • 一个或者多个部件被配置为允许重组

对于那些条件,部件引用将被容器拥有。结合这个事实,你可以有NonShared部件,并且一直从容器来请求它们,然后内存需求将迅速成为一个问题。为了减轻这个问题,你应该依靠在下面接下来的两个话题的讨论的策略。

作用域操作和资源提前回收

一些常见类型的应用程序,像web apps和windows服务,在每个桌面应用上却又很大不同。它们可能更加依赖批量简短的操作。例如,一个windows服务可能会直接地监视,一旦一批可预估的文件存在,就将开始一个批处理操作来转换这些文件成另外一种格式。Web操作可能由每次请求操作所决定。

对于那些场景,你应该使用子容器或者提前释放对象。后者可以使容器释放和清掉非共享的部件。

为了提前释放对象,你需要调用由组合容器暴露的ReleaseExport方法。

var batchProcessorExport = container.GetExport<IBatchProcessor>();var batchProcessor = batchProcessorExport.Value;
batchProcessor.Process();container.ReleaseExport(batchProcessorExport);

容器分层

另一种解决相同问题的方式是使用容器分层。你可以创建容器并将它连接到一个父容器并作为其子容器。注意除非你提供了一个不同的catalog到子容器中,否则将不会有很大帮助,因为仍然会在父容器中实例化。

因此,你应该做的是,基于一种标准过滤父容器,这种标准是应该被创建在父容器中的一系列部件和那些应该被创建在子容器中的部件区分开来,或者是,你应该完全指定一个新的catalog来暴露一系列应该被创建在子容器中的部件。子容器正如所期望的那样是短期存在的,创建在它里面的部件将会更早地被释放掉。一个通用的解决办法是将共享的部件创建在父容器中,而将非共享的部件创建在子容器中。由于共享部件可能会依赖由非共享部件提供的导出,这时主catalog必须包含整个一系列的部件而子容器应该有一个仅包含非共享部件的过滤主容器的视图。

可处理命令

可处理命令并不能以任何方式确保。那意味着你不应该在你的dispose方法上试图使用导入。例如:

[Export]
public class SomeService : IDisposable
{[Import]public ILogger Logger { get; set; }public void Dispose(){Logger.Info("Disposing"); // might throw exception!
    }
}

在你的dispose方法实现上使用导入的logger实例可能会有问题,因为这个ILogger契约的实现也可能是可处理的,而此时可能它已经被处理掉了。

添加部件/移除部件

并不是每一个部件都是由容器创建的。你也可以从容器中添加和移除部件。这个过程触发了容器,
使其开始创建部件来满足递归添加的部件的依赖。当部件被移除时,MEF足够聪明,它将会回收资源并且处理掉被部件添加的非共享部件。

注意:MEF将从不会占有你提供的实例的所有权,但是,它有由它自己创建的满足你实例导入的部件的所有权。

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace PartLifetime
{class Example{static void Main(){var catalog = new AssemblyCatalog(typeof(Program).Assembly);var container = new CompositionContainer(catalog);var root = new Root();//add external part
            container.ComposeParts(root);//...use the composed root instance//remove external part//var batch = new CompositionBatch();//var rootPart = batch.AddExportedValue<Root>(new Root());//container.Compose(batch);//batch = new CompositionBatch();//batch.RemovePart(rootPart);//container.Compose(batch);container.ReleaseExport<NonSharedDependency>(new Lazy<NonSharedDependency>());Console.ReadKey();}}class Root{[Import(RequiredCreationPolicy=CreationPolicy.NonShared)]public NonSharedDependency Dep { get; set; }}[Export,PartCreationPolicy(CreationPolicy.NonShared)]class NonSharedDependency : IDisposable{public void Dispose(){Console.WriteLine("Disposed");}}}

 

转载于:https://www.cnblogs.com/jellochen/p/3667704.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386318.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET MVC中在Action获取提交的表单数据方法总结 (4种方法,转载备忘)

有Index视图如下&#xff1a; 视图代码如下&#xff1a; [html] view plaincopyprint?<% Page Language"C#" MasterPageFile"~/Views/Shared/Site.Master" Inherits"System.Web.Mvc.ViewPage" %> <asp:Content ID"Content1&qu…

解析底层原理!Android开发者面试如何系统复习?帮你突破瓶颈

现状 后端转 Android 我该从何处下手&#xff0c;现在学习 android 晚吗&#xff1f; 我的回答是晚还不至于&#xff0c;因为目前是市场趋于稳定正常&#xff0c;这个是市场发展的比如趋势&#xff0c;现在火爆大家都看好的人工智能&#xff0c;大数据&#xff0c;犹如2010年…

解析底层原理!月薪20k+的Android面试都问些什么?深夜思考

正文 Android行业主要问题是初级Android太多了&#xff0c;会写xml和Activity的程序员太多了&#xff0c;初中级程序员面临很大的竞争&#xff0c;现状也就偏于高级开发者。越来越多的初中级Android程序员找不到满意的工作&#xff0c;甚至根本找不到工作&#xff01;所以很多…

解锁Android性能优化的五大误区!满满干货指导

笼统来说&#xff0c;中年程序员容易被淘汰的原因其实不外乎三点。 1、输出能力已到顶点。这个人奋斗十来年了&#xff0c;依旧碌碌无为&#xff0c;很明显这人的天花板就这样了&#xff0c;说白了&#xff0c;天赋就这样。 2、适应能力越来越差。年纪大&#xff0c;有家庭&…

意外收获字节跳动内部资料,一篇文章帮你解答

前言 俗话说“生于忧患&#xff0c;死于安乐”&#xff0c;其实大部分中年危机&#xff0c;就是在安乐中产生的。 有的人或许会反驳&#xff0c;“照你这么说&#xff0c;我还必须奋斗了&#xff0c;不奋斗就要死&#xff0c;难道选择安逸的生活就不对吗&#xff1f;我就没有…

成功跳槽百度工资从15K涨到28K,已整理成文档

开头 在一般的互联网公司的技术人员的面试中&#xff0c;大概会经历3到4轮的面试&#xff0c;差不多2-3轮的技术面&#xff0c;还有1轮的HR面试&#xff0c;有人面试题是有关“目标”&#xff0c;有的关于“方法”&#xff0c;有的关于“算法”&#xff0c;有的关于“基础”。…

我三年开发经验,从字节跳动抖音离职后,吐血整理

前言 前不久写过一篇博客&#xff0c;里面介绍了一位朋友由二本渣渣毕业在外包公司工作两年多后&#xff0c;跳槽逆袭成功&#xff0c;现在进入了OPPO公司的故事。 后面很多朋友私信我&#xff0c;表示想要这位朋友的面经。 其实我觉得&#xff0c;大家对面经完全没必要这么…

熊逸《唐诗50讲》田园篇 - 学习笔记与感想

此篇已加入熊逸《唐诗50讲》学习笔记索引目录。 一、田园篇具体内容 田园牧歌对于在现代社会里打拼的人们来说&#xff0c;距离一万光年&#xff0c;但是身心俱疲的时候&#xff0c;读两首田园诗却是最好的治愈&#xff0c;因为诗里岁月柔软、风物沛然。这一篇里&#xff0c;熊…

我三年开发经验,从字节跳动抖音离职后,满满干货指导

前言 程序员这个行业&#xff0c;日新月异&#xff0c;技术体系更新速度快&#xff0c;新技术新框架层出不穷&#xff0c;所有的技术都像是一个无底洞&#xff0c;当你学得越多就会发现不懂的越多&#xff0c;不懂的越多&#xff0c;需要学习的就更多。 因此&#xff0c;一旦…

我了解到的面试的一些小内幕!顺利通过阿里Android岗面试

前言 从毕业到现在面试也就那么几家公司&#xff0c;单前几次都比较顺利&#xff0c;在面到第三家时都给到了我offer&#xff01;前面两次找工作&#xff0c;没考虑到以后需要什么&#xff0c;自己的对未来的规划是什么&#xff0c;只要有份工作&#xff0c;工资符合自己的要求…

我们究竟还要学习哪些Android知识?吐血整理

前言 闲来无事在家偶然翻到了之前整理的文档和面试要做到准备路线&#xff0c;虽然内容有点多&#xff0c;但是技多不压身&#xff0c;多多益善 本部分内容是关于Android进阶的一些知识总结&#xff0c;涉及到的知识点比较杂&#xff0c;不过都 是面试中几乎常问的知识点&…

我们究竟还要学习哪些Android知识?满满干货指导

咸鱼翻身不断上演 2018年5月份&#xff0c;北京&#xff0c;在所谓的互联网寒冬里&#xff0c;一个普通二本的学生&#xff0c;在小公司工作一年后&#xff0c;跳槽拿到了百度的offer&#xff0c;月薪从9k变为17k&#xff0c;涨薪幅度接近100%。 2018年底&#xff0c;上海&am…

我们究竟还要学习哪些Android知识?看这一篇就够了!

雪上加霜 本人一名Android程序员&#xff0c;今年29岁了。大厂小厂都呆过&#xff0c;现在在腾讯工作&#xff01;明明工作顺利&#xff0c;家庭和睦儿女成全&#xff0c;但是总是会感觉到&#xff0c;一股无形的压力&#xff0c;推着我走&#xff01;作为一名程序员我最怕的不…

Daily scrum 10.15

今天新的UI到了&#xff0c;展示如下。 Icon&#xff1a; Wallpaper&#xff1a; Lay out&#xff1a; search resutls&#xff1a; 感谢我们的UI support Wenchao Shi的帮助&#xff01; 接下来的一周是bug fix阶段&#xff0c;我们总结了一下目前的bug&#xff0c;整理如下&a…

我在美团Android研发岗工作的那5年,含泪整理面经

这篇文章主要介绍了20道经典Handler题及答案解析&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者面试复习具有一定的参考学习价值&#xff0c;内容过多可以先收藏慢慢观看&#xff0c;需要的朋友们下面随着小编来一起学习学习吧。 另外各位观众老爷觉…

我想谈谈关于Android面试那些事,一篇文章帮你解答

开头 通常作为一个Android APP开发者&#xff0c;我们并不关心Android的源代码实现&#xff0c;不过随着Android开发者越来越多&#xff0c;企业在筛选Android程序员时越来越看中一个程序员对于Android底层的理解和思考&#xff0c;这里的底层主要就是Android Framewok中各个组…

给后辈的一点建议,分享PDF高清版

前言 咱们这行似乎每个人都有个常识&#xff1a;程序员做到35岁之后&#xff0c;职业道路就很窄了&#xff0c;但我不信这个邪&#xff0c;我今年37岁&#xff0c;依然活跃在开发一线&#xff0c;并且做到了月入四万&#xff0b;。 偶尔也有人问&#xff0c;你是怎么打破35岁…

给后辈的一点建议,面试建议

前言 相信很多同学都会有这样的感受&#xff0c;前三天刚刚复习的知识点&#xff0c;今天问的时候怎么就讲不出个所以然了呢&#xff1f; 本文的目的就是致力于帮助大家尽可能的建立Android知识体系&#xff0c;希望大家会喜欢~ 技术专家VS管理&#xff0c;哪条路更适合你&am…

给后辈的一点建议,面试必会

前言 2017年进大学开始接触Android&#xff0c;从刚开始接触就不断地听到Android市场饱和&#xff0c;工作难找等消息。虽然当时也非常迷茫&#xff0c;不过由于第一次深入接触编程语言&#xff0c;再加上自己的一点兴趣&#xff0c;就一直坚持下来了。 到现在要毕业了&#…

美团Android开发工程师岗位职能要求,真香

前言 说起程序员人们的第一印象就是工资高、加班凶、话少钱多头发少。再加上现在科技互联网公司太吃香&#xff0c;bat、华为小米等公司程序员加班情况被广泛传播&#xff0c;程序员用生命在敲代码的印象刻在了很多人的心里。 与其它行业一样&#xff0c;凡是有高级和普通&…