时间:2019年04月04日 | 作者 : aaronyang | 分类 : C#人爱学不学 | 浏览: 1867次 | 评论 0 人
先研究使用Castle.Windsor5.0
新建控制台4.5Framework的
新建1个类库,放2个接口和2个实现 和一个Main方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ClassLibrary1 { public interface IDependency1 { object SomeObject { get; set; } } public interface IDependency2 { object SomeOtherObject { get; set; } } public class Dependency1 : IDependency1 { public object SomeObject { get; set; } } public class Dependency2 : IDependency2 { public object SomeOtherObject { get; set; } } public class Main { private IDependency1 object1; private IDependency2 object2; public Main(IDependency1 dependency1, IDependency2 dependency2) { object1 = dependency1; object2 = dependency2; } public void DoSomething() { object1.SomeObject = "Hello World"; object2.SomeOtherObject = "Hello Mars"; } } }
请注意,构造函数需要两个参数,与接口相同。 这里我们注入依赖项而不是创建每个依赖项的实例。 除非我们还提供两个依赖项,否则我们无法从主类创建对象。
控制台通过nuget 搜索安装Castle.Windsor
var container = new WindsorContainer(); container.Register(Castle.MicroKernel.Registration.Component.For<ClassLibrary1.Main>()); container.Register(Castle.MicroKernel.Registration.Component.For<ClassLibrary1.IDependency1>().ImplementedBy<ClassLibrary1.Dependency1>()); container.Register(Castle.MicroKernel.Registration.Component.For<ClassLibrary1.IDependency2>().ImplementedBy<ClassLibrary1.Dependency2>()); // CREATE THE MAIN OBJECT AND INVOKE ITS METHOD(S) AS DESIRED. var mainThing = container.Resolve<ClassLibrary1.Main>(); mainThing.DoSomething();
打上断点,开始调试
我们通过构造函数注入方式,把两个接口 都赋值上了对应的实现。
我们把这种行为叫做 IOC,不要记什么依赖注入了。
这种,要在客户端,使用 注册 这种行为(接口和实现对应绑定上),都是老套路,比如 配置文件方式绑定,或者硬代码 绑定。 注入:构造函数,属性,方法参数。然后就是绑定时候指定生命周期,或者名称。
DEMO1 默认生命周期,在Resolve一下,还是上次的实例
结论1:
可以直接注册一个单例类 container.Register(Castle.MicroKernel.Registration.Component.For<一个类>());
结论2:
注册接口和实现 container.Register(Castle.MicroKernel.Registration.Component.For<接口1>().ImplementedBy<接口1的实现>());
默认也是单例
结论3:
可以指定生命周期方式,常用:Transient和Singleton,Transient是每次请求都创建一个新实例,Singleton是单例,他们都是LifeStyle的属性
测试
结论4: 同接口多个实现 可以取 name获得不同的示例
上面是一些1对1 自己知道类型和实现的 注册,那么默认 已某种规则注册呢,比如 知道接口类型,不知道有多少个实现
DEMO2
var cTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(ClassLibrary1.IDependency1).IsAssignableFrom(t) select t; foreach (var t in cTypes) container.Register(Component.For(t).LifeStyle.Transient);
从当前程序集找到 实现IDependency1接口的所有子类,然后注册
当然 我们的接口在另一个类库,也就是另一个程序集了。
Assembly.GetExecutingAssembly()是获取当前运行的程序集
加载其他程序集
var _clpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "ClassLibrary1.dll");
Assembly ass = Assembly.LoadFrom(_clpath);
正常我们都是通过IWindsorInstaller方法Install统一注册,初始化castle的windsor相关的方法
where指定了同命名空间下的
public class AyCastleWindsorInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { var _clpath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "ClassLibrary1.dll"); Assembly ass = Assembly.LoadFrom(_clpath); container.Register(Classes.FromAssembly(ass) .Where(Component.IsInSameNamespaceAs<ClassLibrary1.IDependency1>()) .WithService.DefaultInterfaces() .LifestyleTransient()); } } class Program { static void Main(string[] args) { Console.Title = "AY windsor研究学习"; var container = new WindsorContainer(); container.Install(FromAssembly.This()); var d2_1 = container.Resolve<ClassLibrary1.IDependency1>(); var d2_2 = container.Resolve<ClassLibrary1.IDependency1>(); if (d2_1.GetHashCode() == d2_2.GetHashCode()) { Console.WriteLine("单例"); } else { Console.WriteLine("不是单例"); } Console.ReadKey(); } }
指定 命名空间:InNamespace("ClassLibrary1")
你也可以在install方法里面单独 一个一个的注册
这里过滤条件是: 和IDependency1一个命名空间下的类型,然后进行自动注册的。然后声明周期是Transient,所以 每次请求都是一个新对象。
所以这里不是单例。
换成 LifestyleSingleton就是单例了。
竟然能注册,你当然可以写成配置文件方式了,自己映射。
打断点查看,一目了然了。
如上我测试了Dispose方法,发现调用完了,还是没释放container的,下面还是可以resolve拿到对象的。不管了。
与按照规则批量注册类似,差别在于每个程序集内部自己实现一个IWindsorInstaller接口来定义注册规则。也就是将注册规则下放到程序集。
首先,需要指定对哪些程序集进行安装注册(只指定对程序集的搜索规则):
container.Install(FromAssembly.InDirectory(new AssemblyFilter("Extensions")));//Extensions目录下的所有程序集。
时间 2019-4-4 10:58
关于Install方法的FromAssembly类型,F12进去,有很多方法,感兴趣自己折腾下。
当然,也支持配置,
那么配置文件怎么写?
新建app.config(如果你没有的话)
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler,Castle.Windsor" /> </configSections> <castle> <components> <component id="ide1" service="ClassLibrary1.IDependency1,ClassLibrary1" type="ClassLibrary1.Dependency1,ClassLibrary1"> </component> </components> </castle> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/> </startup> </configuration>
测试
接下来修改实现,增加默认值
修改配置
然后运行,
和
这是根据配置文件中的name来拿到的对象,那么声明周期怎么指定呢?默认是单例
<component id="ide11" service="ClassLibrary1.IDependency1,ClassLibrary1" type="ClassLibrary1.Dependency11,ClassLibrary1" lifestyle="Transient"> </component>
lifestyle="singleton|thread|transient|pooled|custom"
当然还可以指定参数,然后给实例的属性赋值
首先我们修改Main方法
public class Main { private IDependency1 object1; private IDependency2 object2; public int Haha { get; set; } public void WriteHaha() { Console.WriteLine(Haha); } public Main(IDependency1 dependency1, IDependency2 dependency2) { object1 = dependency1; object2 = dependency2; } public void DoSomething() { object1.SomeObject = "Hello World"; object2.SomeOtherObject = "Hello Mars"; } }
由于上面依赖了 IDependency2,所以必须给这个服务也注册进去。我们添加了Haha参数
修改客户端app.config
<components> <component id="ide1" service="ClassLibrary1.IDependency1,ClassLibrary1" type="ClassLibrary1.Dependency1,ClassLibrary1"> </component> <component id="ide11" service="ClassLibrary1.IDependency1,ClassLibrary1" type="ClassLibrary1.Dependency11,ClassLibrary1" lifestyle="Transient"> </component> <component id="ide2" service="ClassLibrary1.IDependency2,ClassLibrary1" type="ClassLibrary1.Dependency2,ClassLibrary1"> </component> <component id="aymain" type="ClassLibrary1.Main,ClassLibrary1"> <parameters> <Haha>2019</Haha> </parameters> </component> </components>
我们默认实例给了Haha这个属性,一个2019的值
我们已经自动实例了Main对象,这里2019通过配置方式赋值上去的,由于单例,任意地方都是这个对象的。
IWindsorContainer container = new WindsorContainer("a.config");
或通过Install方法
container.Install(
Configuration.FromXmlFile("a.config"));
其实写到这里,已经过去了很久,自己百度加上 F12看源码,或者下载Castle.Core源码溯源,或者看单元测试用例。才写出上面这点内容。AY继续
Windsor很强大的,源码阅读难度对我来说很大了,很难搞懂。
随着慢慢发现,Facility这个知识点也很多,官方源码提供了
举个网上能找到的例子,比如Logging
我AY编译了Tests项目,在bin文件夹下
找到了常用的2种日志方式,一个是log4net的,一个nlog
这里用log4net测试,拷贝,这2个dll到项目,并且引用他
项目通过nuget引用log4net类库
然后新建一个log4net.config
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!--日志配置部分--> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> </configSections> <log4net> <root> <priority value="All" /> <appender-ref ref="FileAppender" /> <appender-ref ref="InfoLoging" /> </root> <appender name="FileAppender" type="log4net.Appender.RollingFileAppender"> <file value="log\\log.txt" /> <appendToFile value="true" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="10000KB" /> <rollingStyle value="Size" /> <staticLogFileName value="true" /> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="ERROR" /> <levelMax value="ERROR" /> </filter> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /> </layout> </appender> <appender name="InfoLoging" type="log4net.Appender.RollingFileAppender"> <file value="log\\logData.txt" /> <appendToFile value="true" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="10000KB" /> <rollingStyle value="Size" /> <staticLogFileName value="true" /> <filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="INFO" /> <levelMax value="INFO" /> </filter> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" /> </layout> </appender> </log4net> </configuration>
然后增加AddFacility 添加到容器中
container.AddFacility<LoggingFacility>(f => f.LogUsing<Castle.Services.Logging.Log4netIntegration.Log4netFactory>() .WithConfig("log4net.config"));
我是通过它的单元测试看到的,Nlog方式的自己看
拷贝过来,使用运行时候,Logging会报错的,引用的Castle.Windsor的版本有问题,它要0.0.0.0的,实际上我们是5.0
我只能把它源码拷贝过来,也就3个文件
然后新建一个类,顶部放上一个ILogger
public class SimpleLoggingComponent { private ILogger logger; public SimpleLoggingComponent(ILogger logger) { this.logger = logger; } public void TestLog() { Logger.Error("Ay测试日志Error"); Logger.Debug("Ay测试日志Debug的"); } public ILogger Logger { get { return logger; } } }
测试使用代码如下:
var container = new WindsorContainer(); //container.Install(FromAssembly.This()); container.Install(Configuration.FromAppConfig()); container.AddFacility<LoggingFacility>(f => f.LogUsing<Castle.Services.Logging.Log4netIntegration.ExtendedLog4netFactory>() .WithConfig("log4net.config")); container.Register(Component.For(typeof(SimpleLoggingComponent)).Named("component")); var test = container.Resolve<SimpleLoggingComponent>("component"); test.TestLog();
运行demo后,会输出日志了,至于日志的 控制,自己学习log4net怎么用的就行了。
由于这里我只对Error和Info输出的,所以自己能理解的。
关于Windsor就讲研究到这里了,当然这东西和 Asp.Net MVC还有Wcf配合 DEMO都是有的,自己折腾下就差不多了。
它目前Core也支持了,老项目了,很值得学习。
AY先这样了。
====================www.ayjs.net 杨洋 wpfui.com ayui ay aaronyang=======请不要转载谢谢了。=========
自己的其他文章:写给自己的Castle.NET 4.0笔记[1]
抖音:wpfui 工作wpf,目前主maui
招聘合肥一枚WPF工程师,跟我一个开发组,10-15K,欢迎打扰
目前在合肥市企迈科技就职
AYUI8全源码 Github地址:前往获取
杨洋(AaronYang简称AY,安徽六安人)和AY交流
高中学历,2010年开始web开发,2015年1月17日开始学习WPF
声明:AYUI7个人与商用免费,源码可购买。部分DEMO不免费
不是从我处购买的ayui7源码,我不提供任何技术服务,如果你举报从哪里买的,我可以帮你转正为我的客户,并送demo
查看捐赠AYUI7.X MVC教程 更新如下:
第一课 第二课 程序加密教程
额 本文暂时没人评论 来添加一个吧
发表评论