// This is the best DI factory sample. public static void Run() { Console.WriteLine($"开始运行{nameof(Demo5)}"); ContainerBuilder cb = new ContainerBuilder(); cb.RegisterModule <CoreModule>(); cb.RegisterModule <SmsCoreModule>(); cb.RegisterModule <ConsoleSmsModule>(); cb.RegisterModule <HttpApiSmsModule>(); cb.RegisterInstance(new SmsConfig { SmsSenderType = SmsSenderType.HttpAPi }).As <SmsConfig>(); IContainer container = cb.Build(); IUserBll userBll = container.Resolve <IUserBll>(); Console.WriteLine(userBll.GetHashCode()); bool login = userBll.Login("12345678901", "Password"); Console.WriteLine(login); login = userBll.Login("10987654321", "ytrewq"); Console.WriteLine(login); Console.WriteLine($"结束运行{nameof(Demo5)}"); }
public static void Run() { // Also abstracted the factory, it is better than demo3 for factory Console.WriteLine($"开始运行{nameof(Demo4)}"); ContainerBuilder cb = new ContainerBuilder(); cb.RegisterType <UserDal>().As <IUserDal>(); cb.RegisterType <UserBll>().As <IUserBll>(); cb.RegisterType <SmsSenderFactory>().As <ISmsSenderFactory>(); cb.RegisterType <ConsoleSmsSenderFactoryHandler>() .As <ISmsSenderFactoryHandler>(); cb.RegisterType <SmsSenderFactoryHandler>() .As <ISmsSenderFactoryHandler>(); cb.RegisterType <ConfigProvider>().As <IConfigProvider>(); IContainer container = cb.Build(); IUserBll userBll = container.Resolve <IUserBll>(); bool login = userBll.Login("12345678901", "Password"); Console.WriteLine(login); login = userBll.Login("10987654321", "ytrewq"); Console.WriteLine(login); Console.WriteLine($"结束运行{nameof(Demo4)}"); }
private static void UseAutoFac() { //创建容器构造者,用于注册组件和服务(组件:接口实现类,服务:接口) ContainerBuilder builder = new ContainerBuilder(); //注册组件UserBll类,并把服务IUserBll接口暴露给该组件 //把服务(IUserBll)暴露给组件(UserBll) builder.RegisterType <UserBll>().As <IUserBll>(); // builder.RegisterType<DogBll>().As<IAnimalBll>();//把DogBll类注册给IAnimalBll接口,注意在TestBllImpl项目中有多个IAnimalBll的实现类 builder.RegisterType <DogBll>().Named <IAnimalBll>("Dog"); builder.RegisterType <CatBll>().Named <IAnimalBll>("Cat"); //创建容器 IContainer container = builder.Build(); //使用容器解析服务(不推荐这样,可能造成内存的泄露) //IUserBll userBll = container.Resolve<IUserBll>(); //IAnimalBll dogBll = container.Resolve<IAnimalBll>(); //使用容器的生命周期解析服务(这样可以确保服务实例被妥善地释放和垃圾回收) using (ILifetimeScope scope = container.BeginLifetimeScope()) { IUserBll userBll = scope.Resolve <IUserBll>(); IAnimalBll dogBll = scope.ResolveNamed <IAnimalBll>("Dog"); IAnimalBll catBll = scope.ResolveNamed <IAnimalBll>("Cat"); userBll.Login("shanzm", "123456"); dogBll.Cry(); catBll.Cry(); } }
//在使用AutoFac的时候, 建议所有的实现类都写成无状态的 //无状态的就是实现类中只去实现接口,而不要添加一些属性和字段 //这样在注册接口的时候,所有的实现类的对象可以设置为单例模式 //即整个系统中实现类的对象只有一个,降低了内存的占用,而且不会存在数据修改形成的脏数据 private static void UseAutoFac6() { ContainerBuilder builder = new ContainerBuilder(); Assembly asm = Assembly.Load(" TestBLLImpl"); //这里通过使用SingleInstance()实现注册给接口的实现类的对象以单例模式 builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().SingleInstance(); IContainer container = builder.Build(); //IUserBll userBll1 = container.Resolve<IUserBll>(); //userBll1.Login("shanzm", "1111"); //IUserBll userBll2 = container.Resolve<IUserBll>(); //userBll2.Login("shanzm", "2222"); using (var scope = container.BeginLifetimeScope()) { IUserBll userBll1 = scope.Resolve <IUserBll>(); userBll1.Login("shanzm", "1111"); IUserBll userBll2 = scope.Resolve <IUserBll>(); userBll2.Login("shanzm", "2222"); //对比你就会发现,其实userBll1和userBll2指向的是同一个对象 //因为是单例模式,所以在该程序中所有创建的IUserBll对象都是同一个。 //若是去掉.SingleInstance()则会打印为false,即默认的不是单例模式 Console.WriteLine(ReferenceEquals(userBll1, userBll2));//打印结果:true } }
public static void Run() { Console.WriteLine($"开始运行{nameof(Demo1)}"); ContainerBuilder cb = new ContainerBuilder(); cb.RegisterType <UserDal>().As <IUserDal>(); cb.RegisterType <UserBll>().As <IUserBll>(); cb.RegisterType <ConsoleSmsSender>().As <ISmsSender>(); IContainer container = cb.Build(); IUserBll userBll = container.Resolve <IUserBll>(); bool login = userBll.Login("12345678901", "Password"); Console.WriteLine(login); login = userBll.Login("10987654321", "ytrewq"); Console.WriteLine(login); Console.WriteLine($"结束运行{nameof(Demo1)}"); }
private void button1_Click(object sender, EventArgs e) { if (IsChange && CurrentUser.UserName == txtUserName.Text.Trim()) { this.ShowInfo("当前登录账户相同."); return; } if (checkBox1.Checked) { if (string.IsNullOrEmpty(txtPhone.Text)) { this.ShowInfo("请输入手机."); } } else { if (string.IsNullOrEmpty(txtUserName.Text)) { this.ShowInfo("请输入用户名.."); } } if (string.IsNullOrEmpty(txtPassword.Text)) { this.ShowInfo("请输入密码."); } UserModel userModel = new UserModel { UserName = txtUserName.Text, Phone = txtPhone.Text, Password = txtPassword.Text, Status = 1, }; var user = _userBll.Login(userModel); if (user != null) { CurrentUser = user; //如果是切换用户,直接隐藏,否则弹出主页面. if (!IsChange) { MainForm mainForm = new MainForm(); mainForm.Show(); } var msg = $"操作员:{user.Name},工号:{user.UserName},{DateTime.Now.ToString()}登录成功."; NLogger.LogInfo(msg, user.UserName); this.Hide(); } else { var msg = $"工号/手机号:{txtUserName.Text + txtPhone.Text},{DateTime.Now.ToString()}登录失败."; NLogger.LogInfo(msg, txtUserName.Text + txtPhone.Text); this.ShowInfo("用户名或密码错误."); } }
public static void Run() { Console.WriteLine($"开始运行{nameof(Demo2)}"); ContainerBuilder cb = new ContainerBuilder(); cb.RegisterType <UserDal>().As <IUserDal>(); cb.RegisterType <UserBll>().As <IUserBll>(); // 使用预编译命令,使得 Release 和 Debug 版本注册的对象不同,从而实现调用的短信API不同 #if DEBUG cb.RegisterType <ConsoleSmsSender>().As <ISmsSender>(); #else cb.RegisterType <HttpApiSmsSender>().As <ISmsSender>(); #endif IContainer container = cb.Build(); IUserBll userBll = container.Resolve <IUserBll>(); bool login = userBll.Login("12345678901", "Password"); Console.WriteLine(login); login = userBll.Login("10987654321", "ytrewq"); Console.WriteLine(login); Console.WriteLine($"结束运行{nameof(Demo2)}"); }
public static void Run() { Console.WriteLine($"开始运行{nameof(Demo3)}"); ContainerBuilder cb = new ContainerBuilder(); cb.RegisterType <UserDal>().As <IUserDal>(); cb.RegisterType <UserBll>().As <IUserBll>(); cb.RegisterType <SmsSenderFactory>().As <ISmsSenderFactory>(); cb.RegisterType <ConfigProvider>().As <IConfigProvider>(); // The default value for enum in register is the first enum. Here is Console //cb.RegisterType<SmsConfig>().As<SmsConfig>(); // This kind of writing is better than reading directly through the configuration in the class. // More flexible... /* * Note: * I think in this case, ContainerBuilder cannot register an enum instance. * So we can only register the SmsConfig instance. */ cb.RegisterInstance(new SmsConfig { SmsSenderType = SmsSenderType.Console }).As <SmsConfig>(); IContainer container = cb.Build(); IUserBll userBll = container.Resolve <IUserBll>(); bool login = userBll.Login("12345678901", "Password"); Console.WriteLine(login); login = userBll.Login("10987654321", "ytrewq"); Console.WriteLine(login); Console.WriteLine($"结束运行{nameof(Demo3)}"); }
//一个实现类实现了多个接口 private static void UseAutoFac2() { ContainerBuilder builder = new ContainerBuilder(); //MasterBll实现了多个接口,我们可以把该类注册给他所有实现的接口 //换言之,只要是MasterBll实现的接口,我们都可以该他一个MasterBll类型的对象 //但是注意,这个MasterBll对象只包含当前接口的方法 builder.RegisterType <MasterBll>().AsImplementedInterfaces();//把MasterBll类注册给所有他实现的接口 //即一个组件暴露了多个服务,这里就等价于: //builder.RegisterType<MasterBll>().As<IUserBll>().As<IMasterBll>(); IContainer container = builder.Build(); IUserBll userBll = container.Resolve <IUserBll>(); //其实这里的userBll是MasterBll类型的对象,但是只具有IUserBll接口中的方法 userBll.Login("shanzm", "11111"); //打印:登录用户是Master:shanzm Console.WriteLine(userBll.GetType()); //打印:TestBLLImpl.MasterBll }
void btnLogin_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(stbAccount.SkinTxt.Text)) { errorProvider.SetError(stbAccount, "请您输入帐号后再登录!"); return; } if (string.IsNullOrEmpty(stbPassword.SkinTxt.Text)) { errorProvider.SetError(stbPassword, "请您输入密码后再登录!"); return; } var user = new User { Account = stbAccount.SkinTxt.Text, Password = stbPassword.SkinTxt.Text, IsClient = _isClient }; if (LoginCfg != null) { if (LoginCfg.RememberPassword && !_useInputPassword) { user.Password = LoginCfg.Password; } } bool isAutoLogin = !_useInputPassword && LoginCfg != null && (LoginCfg.RememberPassword || LoginCfg.AutoLogin); _globalApplicationData.ApplicationData.UpdateInfo = _updateInfoBll.Get(); _userBll.Login(new LoginInfo { User = user, UpdateInfo = _globalApplicationData.ApplicationData.UpdateInfo }, isAutoLogin, _loginResponse); }
//把所有的接口实现类都注册 private static void UseAutoFac3() { //从上面几个示例,你可以发现好像使用依赖反转,好像有点麻烦! //若是TestBLL中有许多类,需要注册,则就可以显示出使用控制反转的 ContainerBuilder builder = new ContainerBuilder(); Assembly asm = Assembly.Load(" TestBLLImpl"); //把TestBLLImpl程序集中的所有类都是注册给他的接口 builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces(); //注意RegisterAssemblyTypes()的参数可以是多个程序集 IContainer container = builder.Build(); //其实到这里你就会发现使用AutoFac的便利了, //你需要在TestIBLL项目中给定义每个接口,在TestBllImpl项目中去实现每个接口 //在TestUI项目中就不需要像以前一样去实例每一个TestBLLImpl项目中的类,使用AutoFac把每个类注册给他的接口 //然后直接调用接口对象就可以了,而且你都不用明白到底是哪个一个类实现该接口 //从而实现了解耦 IUserBll userBll = container.Resolve <IUserBll>(); userBll.Login("shanzm", "123456"); Console.WriteLine(userBll.GetType());//调试时查看uerBll接口对象中的具体实现对象:TestBllImpl.UserBll }
private static void UseAutoFac7() { ContainerBuilder builder = new ContainerBuilder(); Assembly asm = Assembly.Load(" TestBLLImpl"); //这里通过使用SingleInstance()实现注册给接口的实现类的对象以单例模式 builder.RegisterAssemblyTypes(asm).AsImplementedInterfaces().SingleInstance(); IContainer container = builder.Build(); using (var scope1 = container.BeginLifetimeScope()) { IUserBll userBll1 = scope1.Resolve <IUserBll>(); userBll1.Login("shanzm", "1111"); using (var scope2 = container.BeginLifetimeScope()) { IUserBll userBll2 = scope2.Resolve <IUserBll>(); userBll2.Login("shanzm", "2222"); Console.WriteLine(ReferenceEquals(userBll1, userBll2)); //因为是单一实例,所以就是在不同的生命周期中,也是同一个实例,打印结果:true } } }
void OnLoginRequest(IMessage msg, SessionEventArgs e, bool reLogin = false) { var loginInfo = msg.Obj as LoginInfo; LoginState state = LoginState.Failed; if (loginInfo != null) { var session = Global.GetSession(new UserSessionIdMetaData { Account = loginInfo.User.Account }); if (!reLogin && session != null) { state = LoginState.LoggedIn; goto Response; } if (reLogin && session != null) { session.SessionId = null; } try { state = _userBll.Login(loginInfo.User); if (state == LoginState.NotAudit) { e.Session.SessionId = new UserSessionIdMetaData { Id = loginInfo.User.Id, Account = loginInfo.User.Account }; goto Response; } if (state == LoginState.Successed) { if (!reLogin) { var clientSession = Global.GetSession(new UserSessionIdMetaData { Account = loginInfo.User.Account, IsClient = true }); if (clientSession == null) { state = LoginState.ClientOffline; goto Response; } var clientLoginUpdateInfo = (clientSession.SessionId as UserSessionIdMetaData).UpdateInfo; var clientLastUpdateInfo = CacheManager.GetUpdateInfo(2, _updateInfoCtreator); if (clientLastUpdateInfo != null) { if (clientLoginUpdateInfo == null || (clientLastUpdateInfo.Version.Equals( clientLoginUpdateInfo.Version, StringComparison.InvariantCultureIgnoreCase) && clientLastUpdateInfo.LastUpdateTime >= clientLoginUpdateInfo.LastUpdateTime)) { state = LoginState.ClientIsNotLatestVersion; } goto Response; } if (_hangUpTimeBll.TotalMinutes(loginInfo.User.Id) < 6 * 60) { state = LoginState.HangUpTimeNotEnough; goto Response; } } } } catch (Exception ex) { ErrorLog(msg.Header.Type, ex); state = LoginState.Failed; } } Response: if (state == LoginState.Successed) { e.Session.SessionId = new UserSessionIdMetaData { Id = loginInfo.User.Id, Account = loginInfo.User.Account }; } e.Session.Send(state, reLogin ? MessageType.ReLoginResponse : MessageType.LoginResponse); }