Autofac详解

Autofac详解

零、文章目录

一、Autofac详解

1、概述

  • Autofac是第三方IOC容器,是当前最流行的IOC容器。
  • 功能强大,比asp.netcore内置容器强大得多,支持属性注入和方法注入,支持AOP。
  • 官网地址:http://autofac.org/
  • 源码下载地址:https://github.com/autofac/Autofac

2、快速开始

(1)Nuget引入程序包

Autofac   基于版本6.3演示,Net5

(2)容器创建对象

//创建一个容器建造者
ContainerBuilder containerBuilder = new ContainerBuilder();
//注册普通类
containerBuilder.RegisterType<Honer>();
//build一下,得到一个容器
IContainer container = containerBuilder.Build();
//可以基于容器来获取对象的实例
Honer phone = container.Resolve<Honer>();

3、注册的类型

(1)注册普通类

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>();
IContainer container = containerBuilder.Build();
Honer phone = container.Resolve<Honer>();

(2)注册抽象与实现

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
IContainer container = containerBuilder.Build();
IPhone phone = container.Resolve<IPhone>();

(3)注册程序集

  • RegisterAssemblyTypes(程序集数组),程序集必须是public的
  • AsImplementedInterfaces():表示注册的类型,以接口的方式注册
  • PropertiesAutowired():支持属性注入
  • Where:满足条件类型注册

var basePath = AppContext.BaseDirectory;
var dll = Path.Combine(basePath, "MyAutofac.dll");
ContainerBuilder containerBuilder = new ContainerBuilder();
var assemblysServices = Assembly.LoadFrom(dll);
containerBuilder.RegisterAssemblyTypes(assemblysServices).Where(t => !t.Name.EndsWith("XXX")).AsImplementedInterfaces().PropertiesAutowired();                        
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

image-20220615171348335

4、三种注入方式

(1)构造函数注入

默认支持,无法用特性进行筛选,默认选参数最多的构造函数进行注入

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>();
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

image-20220507144924795

(2)全部属性注入

关键词PropertiesAutowired,这个对象所有属性全部注入

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired();
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

image-20220507145543126

(3)标记特性的属性注入

关键词PropertiesAutowired,定义特性选择器CustomPropertySelector

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>().PropertiesAutowired(new CustomPropertySelector());
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

public class CustomPropertySelector : IPropertySelector
{public bool InjectProperty(PropertyInfo propertyInfo, object instance){var flag = propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(SelectPropAttribute));return flag;}
}

image-20220507151030788

(4)方法注入

关键词OnActivated,指定调用方法

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>();
containerBuilder.RegisterType<Teacher>().As<ITeacher>().OnActivated(p =>{p.Instance.SetStudent1(p.Context.Resolve<IStudent>());});
containerBuilder.RegisterType<Student>().As<IStudent>();
IContainer container = containerBuilder.Build();
ITeacher teacher = container.Resolve<ITeacher>();

image-20220507154431887

5、对象生命周期

(1)瞬时生命周期

每次获取都是全新的实例,关键词InstancePerDependency,默认的生命周期

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerDependency();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerDependency:phone1==phone2=>{isflg1}");

InstancePerDependency:phone1==phone2=>False

(2)单例生命周期

同一个进程内都是同一个实例,关键词SingleInstance

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().SingleInstance();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"SingleInstance:phone1==phone2=>{isflg1}");
using (var scope = container.BeginLifetimeScope())
{IPhone phone3 = scope.Resolve<IPhone>();IPhone phone4 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone3, phone4);Console.WriteLine($"SingleInstance:phone3==phone4=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone3);Console.WriteLine($"SingleInstance:phone1==phone3=>{isflg3}");
}

SingleInstance:phone1==phone2=>True
SingleInstance:phone3==phone4=>True
SingleInstance:phone1==phone3=>True

(3)作用域生命周期

同一个作用域内都是同一个实例,关键词InstancePerLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerLifetimeScope();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerLifetimeScope:phone1==phone2=>{isflg1}");
IPhone phone3 = null;
IPhone phone4 = null;
using (var scope = container.BeginLifetimeScope())
{phone3 = scope.Resolve<IPhone>();phone4 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone3, phone4);Console.WriteLine($"InstancePerLifetimeScope:phone3==phone4=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone3);Console.WriteLine($"InstancePerLifetimeScope:phone1==phone3=>{isflg3}");
}
IPhone phone5 = null;
IPhone phone6 = null;
using (var scope = container.BeginLifetimeScope())
{phone5 = scope.Resolve<IPhone>();phone6 = scope.Resolve<IPhone>();bool isflg2 = object.ReferenceEquals(phone5, phone6);Console.WriteLine($"InstancePerLifetimeScope:phone5==phone6=>{isflg2}");bool isflg3 = object.ReferenceEquals(phone1, phone5);Console.WriteLine($"InstancePerLifetimeScope:phone1==phone5=>{isflg3}");
}
bool isflg4 = object.ReferenceEquals(phone3, phone5);
Console.WriteLine($"InstancePerLifetimeScope:phone3==phone5=>{isflg4}");

InstancePerLifetimeScope:phone1==phone2=>True
InstancePerLifetimeScope:phone3==phone4=>True
InstancePerLifetimeScope:phone1==phone3=>False
InstancePerLifetimeScope:phone5==phone6=>True
InstancePerLifetimeScope:phone1==phone5=>False
InstancePerLifetimeScope:phone3==phone5=>False

(4)作用域范围生命周期

在作用域范围外无法创建实例,在作用域范围里面,同一个作用域下面的对象是同一个,关键词InstancePerMatchingLifetimeScope

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerMatchingLifetimeScope("scope1", "scope2");
IContainer container = containerBuilder.Build();
IPhone phone1 = null;
IPhone phone2 = null;
using (var scope = container.BeginLifetimeScope("scope1"))
{phone1 = scope.Resolve<IPhone>();phone2 = scope.Resolve<IPhone>();bool isflg1 = object.ReferenceEquals(phone1, phone2);Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone2=>{isflg1}");
}
IPhone phone3 = null;
using (var scope = container.BeginLifetimeScope("scope2"))
{phone3 = scope.Resolve<IPhone>();
}                   
IPhone phone4 = null;
using (var scope = container.BeginLifetimeScope("scope2"))
{                        phone4 = scope.Resolve<IPhone>();
}
bool isflg2 = object.ReferenceEquals(phone3, phone4);
Console.WriteLine($"InstancePerMatchingLifetimeScope:phone3==phone4=>{isflg2}");
bool isflg3 = object.ReferenceEquals(phone1, phone3);
Console.WriteLine($"InstancePerMatchingLifetimeScope:phone1==phone3=>{isflg3}");

InstancePerMatchingLifetimeScope:phone1==phone2=>True
InstancePerMatchingLifetimeScope:phone3==phone4=>False
InstancePerMatchingLifetimeScope:phone1==phone3=>False

(5)一次请求同一个对象

关键词InstancePerRequest,只能在web项目中调试,控制台报错

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().InstancePerRequest();
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"InstancePerRequest:phone1==phone2=>{isflg1}");

6、支持配置文件注册

(1)nuget引入程序集

Autofac
Autofac.Configuration
Microsoft.Extensions.Configuration.Json

(2)配置文件autofac.json,属性->始终复制

{"components": [{//实现"type": "Net5.IOC.Honer,Net5.IOC",//抽象"services": [{"type": "Net5.IOC.IPhone,Net5.IOC"}],//生命周期"instanceScope": "single-instance",//属性注入 "injectProperties": true}]
}

(3)通过配置文件注册创建对象

ContainerBuilder containerBuilder = new ContainerBuilder();
IConfigurationBuilder config = new ConfigurationBuilder();
IConfigurationSource autofacJsonConfigSource = new JsonConfigurationSource()
{Path = "Autofac/autofac.json",Optional = false,//boolean,默认就是false,可不写ReloadOnChange = true,//同上
};
config.Add(autofacJsonConfigSource);
ConfigurationModule module = new ConfigurationModule(config.Build());
containerBuilder.RegisterModule(module);
IContainer container = containerBuilder.Build();
IPhone phone1 = container.Resolve<IPhone>();
IPhone phone2 = container.Resolve<IPhone>();
bool isflg1 = object.ReferenceEquals(phone1, phone2);
Console.WriteLine($"配置文件注册:phone1==phone2=>{isflg1}");

(4)运行结果

配置文件注册:phone1==phone2=>True

7、支持AOP切面编程

可以在不修改方法的前提下,在方法前后添加公共逻辑,日志,异常,缓存等

(1)nuget引入程序集

Castle.Core
Autofac.Extras.DynamicProxy

(2)自定义一个切面类实现IInterceptor接口

public class CustomInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){Console.WriteLine("方法执行前。。。");//执行当前方法invocation.Proceed();Console.WriteLine("方法执行后。。。");}
}

(3)在抽象/实现类上添加特性标记

[Intercept(typeof(CustomInterceptor))]
public interface IPhone
{string ShowName();
}
//实现类虚方法
public class Honer : IPhone
{public virtual string ShowName(){Console.WriteLine("Honer");return "Honer";}
}

(4)在容器中注册关系创建对象

  • EnableInterfaceInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableInterfaceInterceptors + 特性标记到实现类上,标记的类就支持AOP
  • EnableClassInterceptors,要支持AOP的方法必须要是用virtual虚方法
  • EnableClassInterceptors + 特性标记在抽象上,所有实现类都支持AOP
  • EnableClassInterceptors + 特性标记到实现类上,标记的类就支持AOP

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().As<IPhone>().EnableInterfaceInterceptors();
containerBuilder.RegisterType(typeof(CustomInterceptor));
IContainer container = containerBuilder.Build();
IPhone phone = container.Resolve<IPhone>();
phone.ShowName();

(5)运行结果

方法执行前。。。
Honer
方法执行后。。。

8、单抽象多实现问题

(1)在容器中注册关系创建对象

注册的时候不标记名字,后注册的会覆盖先注册的
注册的时候标记下名字,创建对象的时候用名称来区分

ContainerBuilder containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<Honer>().Named<IPhone>("Honer");
containerBuilder.RegisterType<Huawei>().Named<IPhone>("Huawei");
IContainer container = containerBuilder.Build();
IPhone honer = container.ResolveNamed<IPhone>("Honer");
IPhone huawei = container.ResolveNamed<IPhone>("Huawei");
honer.ShowName();
huawei.ShowName();

(2)运行结果

Honer
Huawei

9、集成到Asp.NetCore5框架

(1)nuget引入程序集

Autofac
Autofac.Extensions.DependencyInjection

(2)定义实现类和抽象

public class UserService : IUserService
{    private IUserRepository UserRepositoryCtor { get; set; }public UserService(IUserRepository userRepository){UserRepositoryCtor = userRepository;}    public string Login(string username, string password){return "登录成功";}
}

(3)添加控制器和页面

public class FourthController : Controller
{private IUserService _userService;public FourthController(IUserService userService){this._userService = userService;}public IActionResult Index(){object result = this._userService.Login("username", "password");return View(result);}
}

@model String
<h2>this is fourth index...</h2>
<h2>@Model</h2>

(4)在Program替换容器工厂

public class Program
{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).UseServiceProviderFactory(new AutofacServiceProviderFactory());
}

(5)在Startup类的ConfigureServices方法中替换创建控制器的类

//控制器默认是有IControllerActivator创建的,替换成由容器创建
services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

(6)注册抽象和实现的关系

Startup类中专门增加一个方法ConfigureContainer,用于注册抽象和实现,可以把这些注册信息进行模块化封装到AutofacModule

当抽象类和实现非常多的时候,可以将整个dll注册,特殊的关系可以写在后面覆盖前面的注册关系。

/// <summary>
/// Autofac专用:注册抽象和细节之间的关系,使用autofac后原来内置注册的关系要注释掉
/// Autofac和ServiceCollection是二者并存的,Autofac会接管ServiceCollection的一切
/// </summary>
/// <param name="builder"></param>
public void ConfigureContainer(ContainerBuilder builder)
{builder.RegisterModule<AutofacModule>();
}

public class AutofacModule : Module
{/// <summary>/// 重写Autofac管道中的Load方法,在这里注入注册的内容/// </summary>/// <param name="builder"></param>protected override void Load(ContainerBuilder builder){//注册抽象与实现builder.RegisterType<UserRepository>().As<IUserRepository>();builder.RegisterType<UserService>().As<IUserService>();//注册所有控制器类var controllersTypesInAssembly = typeof(Startup).Assembly.GetExportedTypes().Where(type => typeof(ControllerBase).IsAssignableFrom(type)).ToArray();//实现属性注入,这边无法实现方法注入builder.RegisterTypes(controllersTypesInAssembly).PropertiesAutowired();}
}

(7)运行结果

image-20220617130527205

image-20220509140121017

(8)在StartupConfigure方法中用容器创建对象

using (var container = host.Services.CreateScope())
{IUserService userService = container.ServiceProvider.GetService<IUserService>();
}

image-20220617131016831

(9)单抽象多实现集成到框架

注入的时候通过构造函数或者属性注入autofac上下文实例,再根据名称创建对应实例。

定义单抽象和多实例类

//抽象
public interface ITestService
{string Show();
}
//实现1
public class TestServiceA : ITestService
{public string Show(){return "TestServiceA";}
}
//实现2
public class TestServiceB : ITestService
{public string Show(){return "TestServiceB";}
}

AutofacModule注册抽象和实现的关系

//单抽象多实现注册
builder.RegisterType<TestServiceA>().Named<ITestService>("a");
builder.RegisterType<TestServiceB>().Named<ITestService>("b");

添加控制器和页面

public class FifthController : Controller
{private IComponentContext _componentContext;public FifthController(IComponentContext componentContext){this._componentContext = componentContext;}public IActionResult Index(){ITestService testServiceA = _componentContext.ResolveNamed<ITestService>("a");ITestService testServiceB = _componentContext.ResolveNamed<ITestService>("b");object result = $"{testServiceA.Show()}--{testServiceB.Show()}";return View(result);}
}

@model String
<h2>this is Fifth index...</h2>
<h2>@Model</h2>

运行结果

image-20220510102820041


---------------------
作者:李宥小哥
来源:CSDN
原文:https://blog.csdn.net/liyou123456789/article/details/125331813
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/283708.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

与ObjectDataSource共舞

4&#xff0c;ORM组件XCode&#xff08;与ObjectDataSource共舞&#xff09; XCode为了能更方便的解决大部分问题&#xff0c;不得不“屈身”于ObjectDataSource。 先上一个经典例子&#xff08;ObjectDataSourceGridView&#xff09;&#xff08;ObjectDataSource&#xff0…

ASP.NET Core 3.1中使用JWT身份认证

文章目录 0、引言1、关于Authentication与Authorization2、整个认证流程是怎样的&#xff1f;3、开始JWT身份认证 3.1 安装JwtBearer包3.2 安装Swashbuckle.AspNetCore包3.3 添加身份认证相关服务到容器中3.4 添加Swagger服务到容器中3.5 将身份认证加入到管道中3.6 将swagger加…

《ASP.NET Core 6框架揭秘》实例演示[10]:Options基本编程模式

依赖注入使我们可以将依赖的功能定义成服务&#xff0c;最终以一种松耦合的形式注入消费该功能的组件或者服务中。除了可以采用依赖注入的形式消费承载某种功能的服务&#xff0c;还可以采用相同的方式消费承载配置数据的Options对象&#xff0c;这篇文章演示几种典型的编程模式…

实现仿简书选取内容生成分享图片效果

前几天脑子里忽然闪过简书的图片分享效果&#xff0c;感觉很简洁也很漂亮&#xff0c;想着能不能用自己方式实现一下呢&#xff0c;于是今天就有了这篇文章。好了&#xff0c;先看下效果图吧&#xff1a; 项目地址: https://github.com/zhangke301... 欢迎star、issues~ 实现这…

千万级可观测数据采集器--iLogtail代码完整开源

2022年6月29日&#xff0c;阿里云iLogtail开源后迎来首次重大更新&#xff0c;正式发布完整功能的iLogtail社区版。本次更新开源全部C核心代码&#xff0c;该版本在内核能力上首次对齐企业版&#xff0c;开发者可以构建出与企业版性能相当的iLogtail云原生可观测性数据采集器。…

Java8新特性--CompletableFuture

并发与并行 Java 5并发库主要关注于异步任务的处理&#xff0c;它采用了这样一种模式&#xff0c;producer线程创建任务并且利用阻塞队列将其传递给任务的consumer。这种模型在Java 7和8中进一步发展&#xff0c;并且开始支持另外一种风格的任务执行&#xff0c;那就是将任务的…

用 MAUI 在Windows 和 Linux 绘制 PPT 图表

我在做一个图表工具软件&#xff0c;这个软件使用 MAUI 开发。我的需求是图表的内容需要和 PPT 的图表对接&#xff0c;需要用到 OpenXML 解析 PPT 内容&#xff0c;读取到 PPT 图表元素的内容&#xff0c;接着使用 MAUI 渲染层绘制图表元素。图表工具软件需要在 Windows 平台和…

聊聊接口性能优化的11个小技巧

前言 接口性能优化对于从事后端开发的同学来说&#xff0c;肯定再熟悉不过了&#xff0c;因为它是一个跟开发语言无关的公共问题。 该问题说简单也简单&#xff0c;说复杂也复杂。 有时候&#xff0c;只需加个索引就能解决问题。 有时候&#xff0c;需要做代码重构。 有时…

Java中ArrayList,LinkedList,Vector三者的异同点及其使用场景和ArrayList的一些常用方法

相同点&#xff1a;三者存储的都是有序&#xff0c;可重复的数据。 异&#xff1a; ①&#xff1a;ArrayList底层存储类型是Object数组&#xff0c;而LinkedList底层是双向链表 ②&#xff1a;ArrayList和Vector调用创建空参构造器创建对象时&#xff0c;默认的size是10&…

第二百四十六节,Bootstrap弹出框和警告框插件

Bootstrap弹出框和警告框插件 学习要点&#xff1a; 1.弹出框 2.警告框 本节课我们主要学习一下 Bootstrap 中的弹出框和警告框插件。 一&#xff0e;弹出框 弹出框即点击一个元素弹出一个包含标题和内容的容器。 基本用法 注意&#xff1a;必须在js结合popover()方法使用 da…

Intellij IDEA2017 的控制台里不识别maven命令问题处理

2019独角兽企业重金招聘Python工程师标准>>> cmd里运行 mvn -v可以显示出maven的版本信息&#xff0c;可是在IDEA的控制台里却提示不识别maven命令&#xff0c;此情况以管理员的身份运行IDEA即可。 转载于:https://my.oschina.net/u/2364025/blog/1788797

使用IDEA 提交代码到svn

2019独角兽企业重金招聘Python工程师标准>>> 新手第一次使用教程&#xff1a; 一、安装svn TortoiseSVN是个客户端&#xff0c;需要安装VisualSVN服务端。 二、IDEA配置&#xff08;Ctrl alt S&#xff09; 需要配置服务端svn.exe文件。 三、上传代码 svn路径&…

如何在 BackgroundService 获取 ASP.NET Core 启动地址

前言上次&#xff0c;我们介绍了《如何获取 ASP.NET Core 启动地址》。但是&#xff0c;如果要在 BackgroundService 中获取启动地址可不那么容易&#xff0c;因为 BackgroundService 在 app 启动前就开始执行了:var builder WebApplication.CreateBuilder(args); builder.Ser…

016-Spring Boot JDBC

一、数据源装配 通过查看代码可知&#xff0c;默认已装配了数据源和JdbcTemplate System.out.println(context.getBean(DataSource.class)); System.out.println(context.getBean(JdbcTemplate.class)); 1.1、环境搭建 主要是pom引用&#xff1a;spring-boot-starter-jdbc、增加…

分库分表和 NewSQL 到底怎么选?

文章来源&#xff1a;【公众号&#xff1a;CoderW】 目录 背景 分表 分库 分库分表的成本 NewSQL NewSQL 平滑接入方案 NewSQL 真的有那么好吗&#xff1f; NewSQL 的应用 分库分表和 NewSQL 到底怎么选&#xff1f; 背景 曾几何时&#xff0c;“并发高就分库&#xff…

jQuery/javascript实现简单网页计算器

1 <html>2 <head>3 <meta charset"utf-8">4 <title>jQuery实现</title>5 <script src"jquery.js"></script>6 7 <style type"text/css">8 table{background-color:pink;width:300px;height…

雷军招人反被3句话问懵:当我在面试牛人的时候,牛人也在面试我

来 源&#xff5c;环球人力资源智库&#xff08;GHRlib&#xff09; 作 者&#xff5c;Black “你做过手机吗&#xff1f;” “没做过。” “你认识中移动老总王建宙吗&#xff1f;” “不认识。” “你认识富士康老板郭台铭吗&#xff1f;” “我认识他&#xff0c;他不认识我…

C# 11 中的 required members

C# 11 中的 required membersIntro在 C# 11 中引入了一个新的特性 —— Required Members&#xff0c;引入了一个新的 required 关键词&#xff0c;可以用来表示字段或者属性在类型初始化的时候必须要进行初始化&#xff0c;这一特性也进一步的改进了可空引用类型的用法。Sampl…

互联网大佬简史:马云/雷军/罗永浩/刘强东...

燃财经&#xff08;ID:rancaijing&#xff09;原创 作者 | 杜枫 编辑 | 魏佳中国互联网的发展&#xff0c;是一部由大佬撑起的奋斗史&#xff0c;也是一部由大佬主演的打脸史。和传统行业不同&#xff0c;互联网行业日新月异&#xff0c;从业者趋于年轻。马云唱起了摇滚&#x…

Windows 11 新版 22621.575 和 22622.575 推送:照片、URL、文件资源管理器

面向 Beta 频道的 Windows 预览体验成员&#xff0c;微软推送了 Windows 11 预览版 Build 22621.575 和 22622.575。 目前 Beta 频道 Windows 11 预览版分为两组进行测试&#xff0c;通过两组 Windows 预览体验成员的使用数据和反馈&#xff0c;以更好的测试新功能的可靠性。Wi…