/// <summary> /// 初始化插件。 /// 请勿在此方法调用<see cref="M:FxEcis.T0000.IoC.EcisContainer.Resolve(System.Type)" />、<see cref="M:FxEcis.T0000.IoC.EcisContainer.ResolveAll(System.Type)" />方法,这会导致容器锁定,后续的注册会失败。 /// 如需要解析类型,应该使用<see cref="P:FxEcis.T0000.IoC.EcisContainer.EventAggregator" />获取<see cref="T:FxEcis.T0000.IoC.ContainerEndInitEvent" />事件,然后在事件触发后解析 /// </summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { //这样是注册一个类型,每次解析时都会新建一个实例对象 //container.Register<ISaveTriageInfo,SaveTriageInfo1>(); //这样是注册到集合 container.RegisterCollection <ISaveTriageInfo>(new [] { typeof(SaveTriageInfo1), typeof(SaveTriageInfo2) }); //SaveTriageInfo2构造参数内包含了ILogger //这里注册后,解析SaveTriageInfo2时,会自动传入Logger的实例 //注册不分先后顺序 container.Register <ILogger, Logger>(); //注册到单个实现和注册到集合并不冲突。具体的解析,可看ResolveIoCPlugin //但是一般不会这样用,程序设计时,应该就确定一个接口能有多少个实现。 //比如说,一个分诊保存的逻辑,只能有一个。但是,病历插入内容模块的接口,可以有插入医嘱、插入检查等等的实现。 //这样注册,是单例模式,容器只会创建一个实例对象,然后将其缓存,每次解析都会返回这个实例。 //container.RegisterSingleton<ISaveTriageInfo, SaveTriageInfo1>(); //这样注册,也是单例模式,这样是自己创建一个实例,这种情况,适用于,构造函数中需要传入int,string等简单类型等情况 //如果是构造函数是可变参数,也需要使用这种方式注册。IoC的内部实现不允许构造函数是可变参数。 //container.RegisterInstance<ISaveTriageInfo>(new SaveTriageInfo1()); //这样注册,会将上面的注册给替换掉,SaveTriageInfo1被替换成SaveTriageInfo2。 //container.Register<ISaveTriageInfo, SaveTriageInfo2>(); //高级注册说明,EcisContainer是其它IoC框架的封装 //如果以上注册方法无法满足需求(这种情况应该很少遇到) //目前内部使用的是SimpleInjector,可查看其文档:https://simpleinjector.readthedocs.io/en/latest/quickstart.html //内部容器在: //container.Container }
private static void WhenEndInit(EcisContainer container) { //在容器初始化完毕后再发送事件,防止在注册之前就已经触发事件了 //这里是模拟发布事件 //正常情况下,发送事件应该在我们程序内部发送,然后插件这里只做订阅操作。 container.EventAggregator.GetEvent <TestEvent>().Publish("测试事件已发送"); }
/// <summary> /// 初始化插件。 /// 请勿在此方法调用<see cref="M:FxEcis.T0000.IoC.EcisContainer.Resolve(System.Type)" />、<see cref="M:FxEcis.T0000.IoC.EcisContainer.ResolveAll(System.Type)" />方法,这会导致容器锁定,后续的注册会失败。 /// 如需要解析类型,应该使用<see cref="P:FxEcis.T0000.IoC.EcisContainer.EventAggregator" />获取<see cref="T:FxEcis.T0000.IoC.ContainerEndInitEvent" />事件,然后在事件触发后解析 /// </summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { //一般来说,插件这里是不需要解析实例的,即调用 EcisContainer.Resolve 方法。因为很少用得到。 //这里只是为了显示如何在程序内解析实例的。 //请勿直接在这里调用 EcisContainer.Resolve 方法,会导致内部容器被锁定。 //插件的载入顺序不是固定的,如果这里直接解析了类型,如果下一个插件还需要注册类型,将导致程序直接抛出异常。 //所以这里需要订阅 ContainerEndInitEvent 事件(容器已初始化完毕事件),然后再进行解析操作。 container.EventAggregator.GetEvent <ContainerEndInitEvent>().Subscribe(ResolveWhenEndInit); }
/// <summary>初始化插件</summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { //获取到TestEvent事件 var @event = container.EventAggregator.GetEvent <TestEvent>(); //订阅事件。 //如果在插件中,Subscribe注册的方法,需要是静态方法,防止订阅被回收。 //或者调用 Subscribe 方法时,keepSubscriberReferenceAlive 参数改成 true。 //或者用其它方式自己管理该方法,如静态类等来保持该方法不会被.net的垃圾回收器回收。 //订阅事件的方法,有多个重载,可自己查看。 @event.Subscribe(Test, ThreadOption.PublisherThread); //订阅可以进行过滤。 //比如说,这里判断事件的传参不是空值的情况下,才调用Test方法。 @event.Subscribe(Test, ThreadOption.PublisherThread, true, s => !string.IsNullOrWhiteSpace(s)); }
/// <summary>初始化插件</summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { //这里用的是Harmony //使用的功能也会是相对来说比较简单的 //项目说明是 https://github.com/pardeike/Harmony/wiki //有相关问题,可访问以上URL查看详细的文档 var harmony = HarmonyInstance.Create("Ecis.Pacth"); //这样是最方便注册补丁的方法。 //但是这样也一样需要在补丁的类增加 HarmonyPatch 等属性 //但是这样会存在一个问题,如果这个DLL有两个插件,都需要使用这个功能(两个插件都调用了该方法),可能会导致补丁多次注册,从而执行了多次。 //harmony.PatchAll(Assembly.GetExecutingAssembly()); //以下写法比较麻烦,但是会更加稳定,不会影响到其它插件的运行 var original = AccessTools.Method(typeof(PatientRegisterStrategy), "PatientRegister"); var prefix = new HarmonyMethod(typeof(PatchPatientRegisterStaticMethod), "Prefix"); var postfix = new HarmonyMethod(typeof(PatchPatientRegisterStaticMethod), "Postfix"); var transpiler = new HarmonyMethod(typeof(PatchPatientRegisterStaticMethod), "Transpiler"); harmony.Patch(original, prefix, postfix, transpiler); }
private static void ResolveWhenEndInit(EcisContainer container) { //因为容器都已经初始化了,全部的插件也都载入完成了。这里已经可以解析实例。 //用于判断有没有注册这个类型 container.IsRegister <ISaveTriageInfo>(); container.IsRegisterCollection <ISaveTriageInfo>(); //这里获取到的是 SaveTriageInfo1 //因为RegisterIoCPlugin.cs中,调用的是 // container.Register<ISaveTriageInfo,SaveTriageInfo1>(); //如果没注册过该类型,直接解析的话会抛出异常。 var saveTriageInfo = container.Resolve <ISaveTriageInfo>(); saveTriageInfo.Save(null); //这里获取到的是 SaveTriageInfo1 ,SaveTriageInfo2 //因为RegisterIoCPlugin.cs中,调用的是 // container.RegisterCollection<ISaveTriageInfo>(new []{typeof(SaveTriageInfo1),typeof(SaveTriageInfo2) }); var saveTriageInfos = container.ResolveAll <ISaveTriageInfo>(); foreach (var triageInfo in saveTriageInfos) { triageInfo.Save(null); } //这样也可以解析集合。 var saveTriageInfos2 = container.Resolve <IEnumerable <ISaveTriageInfo> >().ToList(); foreach (var triageInfo in saveTriageInfos2) { triageInfo.Save(null); } //注意,如果只调用了container.Register来注册,只能用container.Resolve来解析。 //如果只调用了container.RegisterCollection来注册,只能用container.ResolveAll或Resolve<IEnumerable<>>来解析。 //否则解析不到数据,并且会抛出异常。 }
/// <summary>初始化插件</summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { container.EventAggregator.GetEvent <ContainerEndInitEvent>().Subscribe(WhenEndInit); }
/// <summary> /// 初始化插件。 /// 请勿在此方法调用<see cref="M:FxEcis.T0000.IoC.EcisContainer.Resolve(System.Type)" />、<see cref="M:FxEcis.T0000.IoC.EcisContainer.ResolveAll(System.Type)" />方法,这会导致容器锁定,后续的注册会失败。 /// 如需要解析类型,应该使用<see cref="P:FxEcis.T0000.IoC.EcisContainer.EventAggregator" />获取<see cref="T:FxEcis.T0000.IoC.ContainerEndInitEvent" />事件,然后在事件触发后解析 /// </summary> /// <param name="container">默认的<see cref="T:FxEcis.T0000.IoC.EcisContainer" />容器</param> public override void InitPlugin(EcisContainer container) { }