.Net下实现可扩展的编程方法简述
IoC控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则用来解决系统耦合问题。 控制反转还有一个名字叫做依赖注入(DI:Dependency Injection)。IoC中最基本的技术就是interface + reflection,“反射(Reflection)”编程。 。" IoC 容器的职责是对象的创建,核心是对象的生命周期管理(何时创建/怎么创建/何时销毁),就像一个大工厂,对象“托管”在里面。模式的源头都是 SOLID(面向对象的原则)。利用IOC 解耦的核心是:面向抽象,而非实现。即我们只需要关注某一个对象能做什么,怎么用;不需要关注它怎么来,更不需要我们来管理它。
1,Unity
Unity是Enterprise Library 4.0开始加入的一个轻量级的、可扩展的依赖注入容器。
Unity模块包括了下面的特点
• 提供了一个创建对象,以及依赖的对象的方法
• 提供的RegisterType方法用来在容器中注册类型和映射,Resolve方法可以返回任何依赖对象的实例。
• 提供控制反转IOC功能,通过预先配置注入类的对象来实现。你可以在构造函数中指明一个类或者接口(构造函数注入),或者是使用attribute的属性注入,和方法调用注入。
• 支持容器继承,容器可以有子容器,支持对象从子容器传递到父容器中。
• 可以从标准的配置文件中读取信息,例如xml文件
• 在运行时可以配置和改变依赖关系。
• 对类的定义没有任何要求。在类上不需要添加attribute(除非使用属性注入或者是方法调用注入),在类声明中没有任何限制。
• 支持自定义容器,例如,你可以在方法中实现额外的对象构造,和容器功能,例如容器的缓存功能。
三种注入方式:
•构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象。如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前会自定义创建相应参数对象;
•属性注入(Property Injection):如果需要使用到被依赖对象的某个属性,在被依赖对象被创建之后,IoC容器会自动初始化该属性;
• 方法注入(Method Injection):如果被依赖对象需要调用某个方法进行相应的初始化,在该对象创建之后,IoC容器会自动调用该方法。
定义一个接口:
public interface ILogger
{
void Write(string message);
}
实现接口用来扩展应用程序:
public class FlatFileLogger : ILogger
{
public void Write(string message)
{
Console.WriteLine(String.Format("Message:{0}", message));
Console.WriteLine("Target:FlatFile");
}
}
主程序:
class Program
{
static void Main(string[] args)
{
ILogger logger = GetLogger();
logger.Write("Test");
System.Console.ReadLine();
}
/// <summary>
/// 加载日志处理对象
/// </summary>
/// <returns></returns>
public static ILogger GetLogger()
{
//初始化一个容器
IUnityContainer container = new UnityContainer();
//获取unity配置
UnityConfigurationSection config = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
UnityConfigurationSection.CurrentSection.Configure(container);
//向容器中注册对象
ILogger defaultLogger = container.Resolve<ILogger>("Logger");
return defaultLogger;
}
}
扩展配置:
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity>
<typeAliases>
<typeAlias alias="FlatFileLogger" type="IoCTest.Unity.FlatFileLogger, IoCTest.Unity" />
<typeAlias alias="ILogger" type="IoCTest.Unity.ILogger, IoCTest.Unity" />
</typeAliases>
<containers>
<container>
<types>
<type name="Logger" type="ILogger" mapTo="FlatFileLogger" />
</types>
</container>
</containers>
</unity>
</configuration>
2,Spring.NET
Spring.NET是一个应用程序框架,其目的是协助开发人员创建企业级的.NET应用程序。它提供了很多方面的功能,比如依赖注入、面向方面编程(AOP)、数据访问抽象及ASP.NET扩展等等。 Spring.NET的IoC容器所解决的,正是如何在企业应用中将类、对象和服务组合成应用程序的问题。IoC容器将分散的组件组合成完整的应用程序。 。Spring.Core的基础是IObjectFactory接口,该接口用一个简单而优雅的方式实现了工厂模式,使我们可以无需自行编写singleton类型和众多的服务定位器,并允许将对象配置及其依赖关系与具体的程序逻辑解耦。该模块中的IApplicationContext接口是IObjectFactory的扩展,增加了诸多企业级功能,包括使用资源文件进行文本本地化、事件传播和资源装载等等。
定义一个接口:
实现接口:
public class FileLogger : ILogger
{
public void Write(string message)
{
Console.WriteLine(String.Format("Message:{0}", message));
Console.WriteLine("Target:File");
}
}
主程序:
static void Main(string[] args)
{
//初始化容器
IApplicationContext context = ContextRegistry.GetContext();
//获取容器中的对象
ILogger Logger = context.GetObject("Logger") as ILogger;
Logger.Write("Test");
Console.ReadLine();
}
系统配置:
<configuration>
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
</sectionGroup>
</configSections> <spring>
<context>
<resource uri="config://spring/objects"/>
</context>
<objects xmlns="http://www.springframework.net">
<object id="Logger" type="IoCTest.Spring.FileLogger,IoCTest.Spring" >
</object>
</objects>
</spring>
</configuration>
3、MEF组合部件
MEF(Managed Extensibility Framework ) 已经内置在.NET Framework 4.0里面了,只需要添加引用System.ComponentModel.Composition即可。 是.NET平台下一个提供轻量级的、可扩展的、类似插件式的系统架构的、且无需配置的(Attribute Based)扩展性管理框架,让我们可以轻松的对应用程序进行扩展并且对已有的代码产生最小的影响,开发人员在开发过程中根据功能要求定义一些扩展点,之后扩展人员就可以使用这些扩展点与应用程序交互;同时MEF让应用程序与扩展程序之间不产生直接的依赖,这样也允许在多个具有同样的扩展需求之间共享扩展程序。虽然微软的人极力否认MEF是一个IoC/DI的工具,但事实是它的确可以实现Ioc/DI。
使用 MEF 编写的可扩展应用程序的扩展点都会声明一个可由扩展组件(Parts)填充的导入(Import),每个扩展组件都会声明一个导出(Export)。MEF提供一种通过“组合”隐式发现部件的方法,对应用程序进行扩展。 所谓导入(Import)即:在容器中指定“哪个对象需要Compose”,所谓导出(Export)即:指定“哪个类可以被用来Compose”
契约接口:
声明导出:
/// <summary>
/// 哪个类可以被用来Compose,也就是说这个类是不是可以用来填充的实现类,所以Export标记的是类,而不是具体的某个对象。
/// </summary>
[Export("ILogger1", typeof(ILogger))]
public class FileLogger1 : ILogger
{
public void Write(string message)
{
Console.WriteLine(String.Format("Message:{0}", message));
Console.WriteLine("Target:File");
}
}
声明导入:
class Ts
{
/// <summary>
/// 哪个对象需要Compose。也就是需要被实现类给填充,所以Import标记的是对象,一般该对象是接口,因为如果是具体类的话,那还需要Import吗?
/// </summary>
[Import("ILogger1")]
public ILogger Logger { get; set; } public Ts()
{
var catalog = new AggregateCatalog();
//把从Program所在程序集中发现的部件添加到目录中
//catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
//把从指定path发现的部件添加到目录中
catalog.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory));
var container = new CompositionContainer(catalog);
//通过调用容器的ComposeParts()方法可以把容器中的部件组合到一起。
container.ComposeParts(this);
}
}
主程序:
static void Main(string[] args) { Ts ts = new Ts(); ts.Logger.Write("Test"); System.Console.ReadLine(); }
相对于Spring.net这样的框架来说,MEF的优势就是首先它是.NET Framework内置的,你无需添加第三方的引用,担心第三方组件的更新等问题;其次它是免配置的,对Spring.net这样的庞然大物来说免配置很有诱惑力。对Unity来说,它的优势是一样的,.NET Framework内置,无需配置,无需hard code的声明。当然更无需直接引用了,这是所有IoC都做到的。
MEF还可以通过metadata自动发现Parts而无需获取parts的assembly/dll。有关MEF的完整的介绍,请移步MSDN:http://msdn.microsoft.com/en-us/library/dd460648.aspx
.Net下实现可扩展的编程方法简述的更多相关文章
- Windows下使用NIF扩展Erlang方法
在Erlang中,NIF(Native Implemented Function)被用来扩展erlang的某些功能,一般用来实现一些erlang很难实现的,或者一些erlang实现效率不高的功能. N ...
- ASP.NET MVC下的四种验证编程方式
ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效性,我们将针对参数的验证成为Model绑定 ...
- ASP.NET MVC下的四种验证编程方式【转】
ASP.NET MVC采用Model绑定为目标Action生成了相应的参数列表,但是在真正执行目标Action方法之前,还需要对绑定的参数实施验证以确保其有效 性,我们将针对参数的验证成为Model绑 ...
- iOS利用block实现链式编程方法(Objective-C链式编程)
objc利用block实现链式编程方法 因为不好读.block和其他语言的匿名函数一样,很多程序员刚开始很难主动去用他. 本文描述block作为属性的实际使用,看懂block,并讲解如何利用block ...
- Linux下搭建iSCSI共享存储的方法 Linux-IO Target 方式CentOS7-1810下实现
iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够在诸如高速 ...
- Linux下搭建iSCSI共享存储的方法 Linux-IO Target 方式 Debian9.5下实现
iSCSI(internet SCSI)技术由IBM公司研究开发,是一个供硬件设备使用的.可以在IP协议的上层运行的SCSI指令集,这种指令集合可以实现在IP网络上运行SCSI协议,使其能够在诸如高速 ...
- ASP.NET MVC下的四种验证编程方式[续篇]
在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET MVC支持的四种服务端验证的编程方式("手工验证"."标注Validation ...
- paip.函数式编程方法概述以及总结
paip.函数式编程方法概述以及总结 1 函数式编程:函数式风格..很多命令式语言里支持函数式编程风格 1.1 起源 (图灵机,Lisp机器, 神经网络计算机) 1.2 函 ...
- windows下制作PHP扩展
一.编译PHP 转自:http://demon.tw/software/compile-php-on-windows.html 编译PHP扩展必需的一些头文件需要从php源码中获取,其中有一些配置性的 ...
随机推荐
- MATLAB符号运算 分类: 图像处理 2015-07-31 22:53 3人阅读 评论(0) 收藏
1.符号运算 使用MATLAB可以进行多项式乘除运算,也可以进行因式分解. 例1. 多项式乘除运算(x+3)3 >> syms x; >> expand((x+3)^3) an ...
- 理解ros服务和参数 ---- 7
原创博客:转载请表明出处:http://www.cnblogs.com/zxouxuewei/ 周学伟 Description: 本教程介绍了ROS 服务和参数的知识,以及命令行工具rosservi ...
- URAL 1242 Werewolf(DFS)
Werewolf Time limit: 1.0 secondMemory limit: 64 MB Knife. Moonlit night. Rotten stump with a short b ...
- timus 1022 Genealogical Tree(拓扑排序)
Genealogical Tree Time limit: 1.0 secondMemory limit: 64 MB Background The system of Martians’ blood ...
- 两篇很牛的vim使用技巧
读本文之前请注意: 1. 本文的目标是提供一些vim的使用技巧,利用这些技巧可以提高vim的操作效率.部分技巧在vi上也可以使用,但是现在基本上都是用vim了. 2. 本文是整理和总结使用技巧,而非讲 ...
- Questions?
http://www.datastax.com/wp-content/themes/datastax-2014-08/files/NoSQL_Benchmarks_EndPoint.pdf http: ...
- C# Post方式传输报文,和处理响应
public string DoPost(string url, string data) { HttpWebRequest req = GetWebRequest(url, "POST&q ...
- 关于spring 3.0.5的 <mvc:resources mapping="***" location="***">标签的使用
spring mvc 的<mvc;resources mapping="***" location="***">标签是在spring3.0.4出现的 ...
- [Unity 5.2] The imported type `UnityEngine.Advertisements.ShowResult' is defined multiple times
unityAds报这个错: The imported type `UnityEngine.Advertisements.ShowResult' is defined multiple times go ...
- GridView中实现点击某行的任意位置就选中该行
来源:http://auv2009.blog.163.com/blog/static/68858712200992731010670/ 在 GridView中增加一列:(该列是选择按钮,让其不显示) ...