c# UnityContainer 依赖注入的分析

本文介绍了一种在WPF应用程序中使用依赖注入技术实现模块化和解耦的方法。通过具体的示例,展示了如何动态加载ViewModel并初始化其依赖项。

本文未经作者许可,不得转载引用,若需引用,请务必通过邮件方式联系作者,联系邮箱 xuanzhaopeng#gmail.com


在进行windows桌面应用程序或windows phone app开发的过程中,我们将会使用WPF.NET ,而他的亮点在于将界面的设计和软件的逻辑完全的分开,所有的数据进行绑定,所有的命令也同样绑定,这里不再冗余描述如何绑定变量和命令,而着重讲在绑定数据后,后端逻辑中的数据也通过依赖注入的方式进行设计,这么做的原因在于,我们的app使用的数据可能来自于webservice,譬如手机应用,我们不可能在手机中存储庞大的数据库,而是通过webservice来获取和更新数据,因此,如果我们仍然主动监控数据,这就意味着数据的更新是被动的,必须让用户触发,触发后将获得的数据设置到页面绑定的变量上,而如果是一个实时系统,你怎么做呢? 只能利用依赖注入,并且依赖注入能让你的系统更加模块化。 因此我举一个例子给大家看。


我们现在有一个ViewModel要初始化

[AppViewModel]
class ClockViewModel 
    {
        public ClockViewModel(IServices Services)
        {
        }
}

这个viewmodel存放在一个dll中,我们现在要动态加载这个类,当然此时必须用Assembly和Attribute

private Type GetClassByAttribute(Type attributeType)
{
     Assembly assembly = this.GetType().Assembly;
     var types = assembly.GetTypes().Where(t => Attribute.IsDefined(t, attributeType)).ToList();
     return types.First();
}


通过GetClassByAttribute函数,传入参数为AppViewModel的类型, 我们就可以得到ClockViewModel的Type

现在我们要在依赖注入中注册这个Type

Type ViewModelType = this.GetClassByAttribute(typeof(AppViewModelAttribute));
this.IoCContainer.RegisterType(ViewModelType);


其中对象IoCContainer就是实例化后的UnityContainer ,这里用到了RegisterType, 有关这种函数的相关用法,请查询

http://msdn.microsoft.com/en-us/library/cc440951.aspx


此时,我们通过Assembly只得到了ViewModel的类型,而不是实例化的对象,现在的目标是要初始化这个实例对象


因此我们要利用以下方式得到实例化对象

this.ViewModel = this.IoCContainer.Resolve(ViewModelType);


大功告成,我们通过Resolve方法,传入类型,就可以得到这个对象了,此时回顾前面的所有步骤,基本不存在在一层套一层实例化的冗余!

但是!!! 还没有结束,可能有些朋友会问,在ViewModel的构造函数中,其中必须传入一个参数类型为IService接口的对象,但我们根本没处理过这个对象,所以在我们执行上一行代码之前,必须先初始化这些接口对象!!

this.IoCContainer.RegisterType<IDataStreamingChannelFactory, DataStreamingChannelFactory>();
this.IoCContainer.RegisterType<IStreamingDataProvider, StreamingDataProvider>();
this.IoCContainer.RegisterType<IServices, ServiceRoot>();

我们这里看一下 ServiceRoot 的构造函数,

internal class ServiceRoot : IServices, IDataServices, IInfraServices
{
        public ServiceRoot(IIoCContainer ioc, IDataStreamingChannelFactory channelFactory, IStreamingDataProvider streamingProvider)
        {

        }
}

他的构造函数中,用到了IDataStreamingChannelFactory和IStreamingDataProvider,所以我们在注册IService之前,就应该把这两个也注册了


到此时,所有的步骤结束,完成了一个0耦合的对象实例化的过程。


寻求一份 c# 或java高级架构师的工作,或软件网站自动化测试及测试工具管理CI AGILE的高级管理工作

工作地点  北京

联系方式 xuanzhaopeng#gmail.com


### C# Unity 框架中实现依赖注入的方法和示例 #### 使用 NuGet 添加 Unity 为了在项目中集成 Unity 容器,可以通过 NuGet 包管理器安装 `Unity.Container` 或者手动引用 `Microsoft.Practices.Unity.dll` 和 `Microsoft.Practices.Unity.Configuration.dll` 文件[^1]。 ```shell Install-Package Unity-container ``` #### 注册类型和服务 注册服务时可以指定其生命周期范围。对于大多数场景,默认采用瞬态 (Transient) 生命周期更为合适,即每次请求都创建新的实例: ```csharp var container = new UnityContainer(); container.RegisterType<IService, Service>(new TransientLifetimeManager()); ``` 这里通过调用 `RegisterType<TFrom,TTo>()` 方法来关联接口与具体实现类,并利用 `TransientLifetimeManager()` 来确保每次获取的服务都是新实例[^2]。 #### 构造函数注入 构造函数注入是最常见的 DI 方式之一。当客户端需要访问某个服务时,只需声明该服务作为参数传递给构造函数即可: ```csharp public class ClientClass { private readonly IService _service; public ClientClass(IService service){ this._service = service; } } ``` 接着可以在配置文件或代码中完成实际的对象初始化工作并将其传入构造函数内[^3]。 #### Setter 属性注入 除了构造函数外,还可以使用属性 setter 进行依赖注入。这种方式适用于某些特殊场合下的需求调整: ```csharp public class ClientClass{ public IService Service { get; set; } // 假设有一个方法用于执行业务逻辑操作 public void DoWork(){ var result = this.Service.DoSomething(); Console.WriteLine(result); } } // 在外部设置依赖关系 clientClass.Service = unityContainer.Resolve<IService>(); ``` 此片段展示了如何设定一个公开的属性 `_ServiceImpl` 并提供相应的 setter 访问修饰符以便后续由 IoC 容器自动填充所需组件。 #### 单例模式的支持 若要让某特定类型的对象在整个应用程序运行期间只存在唯一实例,则应选择单例(Singleton)模式。这可通过如下方式达成: ```csharp container.RegisterType<ISingletonService, SingletonService>( new ContainerControlledLifetimeManager() ); ``` 上述语句中的 `ContainerControlledLifetimeManager()` 表达了对单一全局共享实例的需求,从而实现了传统意义上的单例行为[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值