您的位置:首页 > 移动开发 > Unity3D

Unity学习笔记(一):StopLight QuickStart

2008-04-20 00:25 393 查看
曾几何时,从Spring中认识了IoC这个词语,但它并没有撩动我的心,原因很简单,我懵懂年代的程序连个静态Factory来创建实例都显得有点多余,Ioc更没有登场的必要。真正认识IoC也许是在使用Castle的时候,记得印象最深刻的一个情景是,我们团队当时的BS项目,开始设计时使用了一个第三方组件,后来需求变动了,这个第三方组件的功能却跟不上需求,我们不得不要换用一个新的组件,但是项目已经部署,客户要求更新后如果出问题能自行恢复到旧版本,当时想到一个笨拙的方法是,要求客户备份一下程序,然后出问题覆盖之就可以了,但是这样有个个问题,新开发模块和维护模块是同时进行部署的,怎能保证同一个模块中一部分使用新的程序,而一部分要恢复到旧程序中去呢,显然在旧办法中不重新编译就达不到这个要求,而其中即使有良好的版本控制,也是一两个文件Undo就能了事的,幸好这时Windsor跳进了我们的视线,使用它通过配置文件实现组件的自由设换,帮助我们轻松度过难关。这虽然不是一个应用IoC的正途例子,却在实际中帮了我们大忙^_^,要想正统的了解IoC,就要重温Martin Fowler大叔的经典文章《Inversion of Control Containers and the Dependency Injection pattern中文版
随着P&P团队发布Entlib 4.0 的蓝图,Unity慢慢映入我的眼帘,又是一个轻量级的IoC,现在终于发布了1.0版本,到底性能如何,让我们先看看附带的StopLight QuickStart

1.在代码中注册对象的映射
代码如下:


IUnityContainer container = new UnityContainer()


.RegisterType<ILogger, TraceLogger>()


.RegisterType<IStoplightTimer, RealTimeTimer>();




// 为容器注册默认注入实例


Application.Run(container.Resolve<StoplightForm>());



基本的流程是:创建注入容器 => 注册对象映射 => 调用对象时根据映射关系创建对象
在这个QuickStart中创建对像具体的流程是
StoplightForm -》StoplightPresenter -》Stoplight -》ILogger -》TraceLogger
-》StoplightSchedule -》IStoplightTimer -》RealTimeTimer -》ILogger(有重复的话,会检查是否已经曾经实例化过,如果有,找出所使用实例化的策略去实例化或者不重新实例化(单件模式))

在要实例化接口的地方使用Dependency属性,如(这里使用属性来做关联处理,对调试造成一定的麻烦,使用Unity时可能会在这里跟踪代码丢失的问题,唯一解决的办法就是直接使用Unity的源码嵌套到项目中进行使用 ^_^)


[Dependency]


public ILogger Logger




...{




get ...{ return logger; }




set ...{ logger = value; }


}

具体在Unity里面的是实现是


public object Resolve(IBuilderContext context) // IBuilderContext : 包含要生成父对象的构建信息




...{


Guard.ArgumentNotNull(context, "context");


NamedTypeBuildKey key = new NamedTypeBuildKey(type, name);


IBuilderContext recursiveContext = context.CloneForNewBuild(key, null);




// 根据注册关联的信息按照响应的实例策略一层一层实例化


return recursiveContext.Strategies.ExecuteBuildUp(recursiveContext);


}



同一接口也可以注册多个实例
如添加一个实现类


internal class MakeFunLogger : ILogger




...{




ILogger Members#region ILogger Members




public void Write(string message)




...{


Trace.WriteLine(string.Format("{0}: {1}",


DateTime.Now,


message + ",与Windsor相比,Unity仍需努力"));


}




#endregion


}





注册代码改为


IUnityContainer container = new UnityContainer()


.RegisterType<ILogger, TraceLogger>()


.RegisterType<ILogger, MakeFunLogger>()


.RegisterType<IStoplightTimer, RealTimeTimer>();

大家也许和我有同样的疑问,这里同时为ILogger注册了两个实例,那么运行时到底是实例哪一个呢?答案是后注册的那个(这个印象中和windsor好像是相反的,呵呵)

2.在配置文件中注册对象的映射
1)添加Configuration相关应用
Microsoft.Practices.Unity.Configuration;
System.Configuration

2)创建建App.Config


<?xml version="1.0" encoding="utf-8" ?>


<configuration>




<configSections>


<!--


使用编译好的Unity组件


<section name="unity"


type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,


Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,


Culture=neutral, PublicKeyToken=31bf3856ad364e35" />


-->




<!--


直接使用Unity源码


(ps:我习惯应用组件不表明Version,因为组件版本是在更新的,如果限死Version有时候很麻烦,当然了,原则上同一组件的接口是不变才行,^_^)


-->


<section name="unity"


type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,


Microsoft.Practices.Unity.Configuration" />


</configSections>




<unity>




<typeAliases>


<!--


创建对象别名,不是必须的


其type格式是:对像的全名,程序集名


-->


<typeAlias alias="ILogger"


type="StopLight.ServiceInterfaces.ILogger, StopLight" />


<typeAlias alias="IStoplightTimer"


type="StopLight.ServiceInterfaces.IStoplightTimer, StopLight" />




<typeAlias alias="TraceLogger"


type="StopLight.ServiceImplementations.TraceLogger, StopLight" />


<typeAlias alias="RealTimeTimer"


type="StopLight.ServiceImplementations.RealTimeTimer, StopLight" />




</typeAliases>




<containers>


<container name="containerOne">




<types>




<!--


注册映射,这里使用默认的生命周期和实例策略,具体设置可以看文档 ^_^


-->


<type type="ILogger" mapTo="TraceLogger"/>


<type type="IStoplightTimer" mapTo="RealTimeTimer" />




</types>


</container>


</containers>


</unity>


</configuration>





3)修改注册代码


// 使用配置文件


IUnityContainer container = new UnityContainer();


UnityConfigurationSection section


= (UnityConfigurationSection)ConfigurationManager.GetSection("unity");


section.Containers["containerOne"].Configure(container);

这样就可以使用文件进行配置 ^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: