本文主要是介绍WPF入门到跪下 第十一章 Prism(五)IOC的依赖注入,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
IOC的依赖注入
一、构造函数方式的依赖注入
以项目启动时MainWindowViewModel的依赖注入为例,默认情况下Prism框架的项目,在打开窗口时会自动匹配主窗口的视图模型类(PrismApplication
启动),这里是MainWindowViewModel,匹配到之后Container
自动创建MainWindowViewModel的实例,创建时会先检查MainWindowViewModel有没有无参构造函数,如果没有则会检查构造函数的参数类型,并在Container
内部列表中寻找对应类型并创建参数对象,然后使用该参数对象来创建MainWindowViewModel。
设置好PrismApplication
启动方式后,做以下处理实现IOC的构造函数依赖注入:
-
创建业务接口及实现类
public interface IDataAccessBase {DataTable GetDatas(string condition); }public class DataAccess : IDataAccessBase {public DataTable GetDatas(string condition){//做数据访问业务return null;} }
-
MainWindowViewModel的构造函数中传入所依赖的接口类型
public class MainWindowViewModel {public MainWindowViewModel(IDataAccessBase dataAccess){var data = dataAccess.GetDatas("模拟一下");} }
-
类型注册
在
RegisterTypes
函数中注册依赖类型public partial class App : PrismApplication {......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IDataAccessBase, DataAccess>();} }
二、特性方式的依赖注入
注意,特性方式的注入时机要比构造函数方式的注入时机晚,因此如果需要在对象构造时使用依赖对象的话,最好用构造函数依赖注入的方式。
-
类型注册
在
RegisterTypes
函数中注册依赖类型public partial class App : PrismApplication {......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<IDataAccessBase, DataAccess>();} }
-
特性标注
使用
Prism.Unity
命名空间下的Dependency
标注属性成员,Prism框架会从IOC容器中寻找对应的类型并注入到属性中。如果在IOC容器中找不到,则会报错。public class MainWindowViewModel {[Dependency]public IDataAccessBase DataAccess{ get; set; } }
三、注册&注入已经存在的实例对象
有些情况下希望直接将一个已经存在的实例对象注册到IOC容器中;或者某个接口只返回接口类型的对象时,无法通过接口+实现类的方式注册到IOC容器中,只能先创建该实例对象,然后将实例对象注册到IOC容器中(例如Log4net)。这个时候可以使用IContainerRegistry
对象的RegisterInstance
方法。
1、注册
public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterInstance(LogManager.GetLogger("Test"));//可以指定名称//containerRegistry.RegisterInstance(LogManager.GetLogger("Test"), TestLog);}
}
2、注入
注入方式,跟上文的一样,可以通过特性或者构造参数。
需要注意的是,如果指定了名称,就只能通过特性指定名称注入或者使用IUnityContainer
或IContainerExtension
对象实例来获取了。
public MainWindow(ILog log)
{InitializeComponent();log.Error("错误", new Exception("发生了一个异常"));//错误log.Fatal("严重错误", new Exception("发生了一个致命错误"));//严重错误log.Info("信息"); //记录一般信息log.Debug("调试信息");//记录调试信息log.Warn("警告");//记录警告信息
}
IUnityContainer
一、获取注册信息
IUnityContainer
接口的实例中存放了IOC容器中的注册信息,其中包括Prism框架默认注册的以及我们自己注册的。
以下为常用的三种注册方式后,IUnityContainer
实例中存放注册信息的不同状态。
注册接口与类型,没有设置名称
public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<ITestClass, TestClass>();}
}
注册接口与类型,并设置名称
public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<ITestClass, TestClass>("TestClassName");}
}
直接注册类型
public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.Register<TestClass>();}
}
不同的注册方式会导致注册信息的状态有所不同,其中导航、视图、类型的注册根据不同情况也有所不同,在实际开发过程中可以先监控一下IUnityContainer
实例中的注册信息再根据实际情况来使用。
需要注意的是,如果在注册过程中设置了name
属性,那么在向容器中获取对象时,也要使用对应的name
来获取,如果还使用类名来获取,会直接报错。
二、从容器中获取对象
除了能在IUnityContainer
实例中获取到IOC容器的注册信息外,还能通过实例方法Resolve<T>()
从容器中获取指定的依赖对象。
此外,从IContainerProvider
实例的Resolve<T>()
方法中也可以从容器中获取指定的依赖对象。
public partial class App : PrismApplication
{......protected override void RegisterTypes(IContainerRegistry containerRegistry){containerRegistry.RegisterSingleton<ITestClass, TestClass>();}
}
public class MainWindowViewModel
{public MainWindowViewModel(IUnityContainer unityContainer, IContainerProvider containerProvider){var a = unityContainer.Resolve<ITestClass>();var b = containerProvider.Resolve<ITestClass>();var result = a == b; //true}
}
三、实例-Region中删除指定视图
public class FileUploadViewModel:BindableBase
{//页签关闭命令public ICommand CloseCommand { get; set; }public FileUploadViewModel(IRegionManager regionManager, IUnityContainer unityContainer){CloseCommand = new DelegateCommand<string>(uri =>{//从IUnityContainer 实例中获取指定的注册信息对象var obj = unityContainer.Registrations.Where(r => r.Name == uri || r.MappedToType == Type.GetType("FileUploadView")).FirstOrDefault();var name = obj?.MappedToType.Name;if (!string.IsNullOrEmpty(name)){var region = regionManager.Regions["MainViewRegion"];var view = region.Views.Where(v=> v.GetType().Name == name).FirstOrDefault();if (view != null)region.Remove(view);}});}
}
IContainerExtension
Prism的IOC容器中默认注册的还有IContainerExtension
接口,该接口实现了IContainerProvider
和IContainerRegistry
接口,因此其实现类的实例对象同时具有注册和从容器中获取对象的功能,如果希望在App类中的RegisterTypes
方法之外的地方向容器注册的话,可以通过IContainerExtension
的实例对象来完成。
public class MainWindowViewModel
{public MainWindowViewModel(IUnityContainer unityContainer, IContainerExtension containerProvider){containerProvider.Register<TestClass>();var test = containerProvider.Resolve<TestClass>();}
}
这篇关于WPF入门到跪下 第十一章 Prism(五)IOC的依赖注入的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!