当前位置: 首页 > news >正文

.NET IoC 容器(三)Autofac

目录

  • .NET IoC 容器(三)Autofac
    • Autofac
    • Nuget 安装
    • 实现DI
      • 定义接口
      • 定义实现类
      • 依赖注入
    • 注入方式
      • 构造函数注入 | 属性注入 | 方法注入
      • 注入实现
    • 接口注册
      • 重复注册
      • 指定参数注册
    • 生命周期
      • 默认生命周期
      • 单例生命周期
      • 每个周期范围一个生命周期
    • 依赖配置
      • Nuget
      • 配置文件
    • AOP
      • Nuget安装
      • 定义接口、实现类
      • 定义切面
      • 容器配置
    • 参考资料

.NET IoC 容器(三)Autofac

Autofac

Autofac 是一个用于 .NET 应用程序的依赖注入 (Dependency Injection, DI) 容器。它帮助开发人员管理对象的创建和生命周期,使得依赖项的注入更加灵活和可维护。以下是 Autofac 的主要功能和特性概述:

依赖注入 (Dependency Injection)

Autofac 允许你通过构造函数、属性或方法注入依赖项。这样,你可以轻松地将对象的依赖关系传递给需要它们的类,从而提高代码的可测试性和可维护性。

模块化设计 (Modular Design)

Autofac 支持模块化设计,可以将相关的依赖项注册逻辑分组到模块中。这使得大型应用程序的配置更加简洁和易于管理。

生命周期管理 (Lifecycle Management)

Autofac 提供多种对象生命周期管理方式,例如单例 (Singleton)、每次请求 (Instance Per Dependency)、每个生命周期范围 (Instance Per Lifetime Scope) 等,允许你精确控制对象的创建和销毁时机。

注册与解析 (Registration and Resolution)

Autofac 通过流畅的 API 提供了多种注册组件的方式。你可以注册类型、实例、工厂方法,甚至通过扫描程序集自动注册组件。此外,Autofac 的解析功能支持构造函数参数注入、命名参数注入等高级特性。

支持 AOP (Aspect-Oriented Programming)

Autofac 与 AOP 框架(如 Castle Windsor)集成,支持横切关注点(如日志记录、事务管理)的处理,从而使业务逻辑代码更加简洁。

集成支持

Autofac 与许多流行的 .NET 库和框架集成良好,包括 ASP.NET Core、WCF、Web API、MVC 等。通过这些集成,Autofac 可以轻松地管理 web 应用程序中的依赖项。

扩展性

Autofac 具有很高的扩展性,可以通过自定义注册源、生命周期、解析器等方式扩展其功能,以满足特定应用的需求。

Nuget 安装

在这里插入图片描述

实现DI

定义接口

internal interface IComputer
{
}
internal interface IKeyboard
{
}
internal interface IMouse
{
}
internal interface IPerson
{IComputer Computer { get; set; }IKeyboard Keyboard { get; set; }IMouse Mouse { get; set; }void Work();
}

定义实现类

internal class ConstructBase
{public ConstructBase() {Console.WriteLine($"{this.GetType().Name} - 被构造了");}
}
internal class LenovoComputer : ConstructBase, IComputer
{public LenovoComputer() : base() { }
}
internal class TogarKeyboard : ConstructBase, IKeyboard
{public TogarKeyboard() : base() { }
}
internal class LogitechMouse : ConstructBase, IMouse
{public LogitechMouse() : base() { }
}
internal class Programmer : ConstructBase, IPerson
{public IComputer Computer { get; set; }public IKeyboard Keyboard { get; set; }public IMouse Mouse { get; set; }public Programmer(IComputer computer, IKeyboard keyboard, IMouse mouse) : base(){Computer = computer;Keyboard = keyboard;Mouse = mouse;}public void Work(){Console.WriteLine("Programmers are building software...");}
}

依赖注入

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Programmer>().As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

注入方式

构造函数注入 | 属性注入 | 方法注入

定义特性用来筛选属性注入

public class InjectPropertyAttribute : Attribute
{}

定义实现类

public class Gamer : ConstructBase, IPerson
{public IComputer Computer { get; set; }[InjectProperty]public IKeyboard Keyboard { get; set; }public IMouse Mouse { get; set; }public Gamer(IComputer computer) : base(){Computer = computer;}public void Inject(IMouse mouse){Mouse = mouse;}public void Work(){Console.WriteLine("The player is playing...");}
}

注入实现

// 注入顺序(与编码顺序无关):构造函数注入 > 属性注入 > 方法注入
var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()// 方法注入.OnActivating(e =>{IMouse mouse = e.Context.Resolve<IMouse>();e.Instance.Inject(mouse);})// 属性注入.PropertiesAutowired((g, o) => g.Name == "Keyboard")// 构造函数注入.UsingConstructor(typeof(IComputer)).As<IPerson>();
var container = builder.Build();
IPerson gamer = container.Resolve<IPerson>();
gamer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
The player is playing...

结果

注入顺序:构造函数注入 > 属性注入 > 方法注入

接口注册

重复注册

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Programmer>().As<IPerson>();
builder.RegisterType<Gamer>()// 方法注入.OnActivating(e =>{IMouse mouse = e.Context.Resolve<IMouse>();e.Instance.Inject(mouse);})// 属性注入.PropertiesAutowired((g, o) => g.Name == "Keyboard")// 构造函数注入.UsingConstructor(typeof(IComputer)).As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
The player is playing...

调换Gamer和Programmer的注册顺序:

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()// 方法注入.OnActivating(e =>{IMouse mouse = e.Context.Resolve<IMouse>();e.Instance.Inject(mouse);})// 属性注入.PropertiesAutowired((g, o) => g.Name == "Keyboard")// 构造函数注入.UsingConstructor(typeof(IComputer)).As<IPerson>();
builder.RegisterType<Programmer>().As<IPerson>();
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

结论

同一接口多次注册时,后注册的会覆盖前面注册的,若需要实现多重注册,需要指定名称

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
builder.RegisterType<TogarKeyboard>().As<IKeyboard>();
builder.RegisterType<LogitechMouse>().As<IMouse>();
builder.RegisterType<Gamer>()// 方法注入.OnActivating(e =>{IMouse mouse = e.Context.Resolve<IMouse>();e.Instance.Inject(mouse);})// 属性注入.PropertiesAutowired((g, o) => g.Name == "Keyboard")// 构造函数注入.UsingConstructor(typeof(IComputer)).Named<IPerson>("person");
builder.RegisterType<Programmer>().Named<IPerson>("programmer");
var container = builder.Build();
IPerson programmer = container.ResolveNamed<IPerson>("programmer");
IPerson person = container.ResolveNamed<IPerson>("person");
programmer.Work();
person.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.Gamer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Programmers are building software...
The player is playing...

指定参数注册

修改接口

internal interface IMouse
{string Type { get; set; }
}

修改实现类

internal class LogitechMouse : ConstructBase, IMouse
{public LogitechMouse() : base() { }public LogitechMouse(string type) : base(){Type = type;}public string Type { get; set; }
}

注入

var builder = new ContainerBuilder();
builder.RegisterType<LogitechMouse>().WithParameter("type","502").As<IMouse>();
var container = builder.Build();
IMouse mouse = container.Resolve<IMouse>();
Console.WriteLine("mouse type: " + mouse.Type);

输出

Zhy.IoC.Autofac.LogitechMouse - 被构造了
mouse type: 502

生命周期

Instance Per Dependency(默认) 每次请求组件时都会创建一个新的实例。这是默认的生命周期管理模式。

builder.RegisterType<MyService>().As<IMyService>();

Singleton 在整个容器生命周期内,只有一个实例。

builder.RegisterType<MyService>().As<IMyService>().SingleInstance();

Instance Per Lifetime Scope 在每个生命周期范围内,共享一个实例。每个生命周期范围都会创建一个新的实例,但在该范围内共享该实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();

Instance Per Matching Lifetime Scope 在特定的生命周期范围内共享实例,需要指定标记。

builder.RegisterType<MyService>().As<IMyService>().InstancePerMatchingLifetimeScope("my-scope");

Instance Per Request 通常用于 web 应用程序,在每个 HTTP 请求期间共享一个实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerRequest();

Externally Owned 组件由外部代码管理生命周期,Autofac 不会在容器释放时释放该实例。

builder.RegisterType<MyService>().As<IMyService>().ExternallyOwned();

Instance Per Dependency 每次依赖请求时都会创建一个新实例。

builder.RegisterType<MyService>().As<IMyService>().InstancePerDependency();

默认生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 22687807
computer0 == computer1: False

单例生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>().SingleInstance();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
IComputer computer1 = container.Resolve<IComputer>();
Console.WriteLine("computer0: " + computer0.GetHashCode());
Console.WriteLine("computer1: " + computer1.GetHashCode());
Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 32347029
computer0 == computer1: True

每个周期范围一个生命周期

var builder = new ContainerBuilder();
builder.RegisterType<LenovoComputer>().As<IComputer>().InstancePerLifetimeScope();
var container = builder.Build();
IComputer computer0 = container.Resolve<IComputer>();
using (var scope = container.BeginLifetimeScope())
{IComputer computer1 = scope.Resolve<IComputer>();IComputer computer2 = scope.Resolve<IComputer>();Console.WriteLine("computer0: " + computer0.GetHashCode());Console.WriteLine("computer1: " + computer1.GetHashCode());Console.WriteLine("computer2: " + computer2.GetHashCode());Console.WriteLine($"computer0 == computer1: {computer0 == computer1}");Console.WriteLine($"computer1 == computer2: {computer1 == computer2}");
}

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.LenovoComputer - 被构造了
computer0: 32347029
computer1: 22687807
computer2: 22687807
computer0 == computer1: False
computer1 == computer2: True

依赖配置

Nuget

在这里插入图片描述

配置文件

Json

{"components": [{"type": "Zhy.IoC.Autofac.LenovoComputer,Zhy.IoC.Autofac","services": [{"type": "Zhy.IoC.Core.IComputer,Zhy.IoC.Core"}],"autoActivate": true,"instanceScope": "singleinstance"},{"type": "Zhy.IoC.Autofac.TogarKeyboard,Zhy.IoC.Autofac","services": [{"type": "Zhy.IoC.Core.IKeyboard,Zhy.IoC.Core"}],"autoActivate": true,"instanceScope": "singleinstance"},{"type": "Zhy.IoC.Autofac.LogitechMouse,Zhy.IoC.Autofac","services": [{"type": "Zhy.IoC.Core.IMouse,Zhy.IoC.Core"}],"parameters": {"places": 4},"autoActivate": true,"instanceScope": "singleinstance"},{"type": "Zhy.IoC.Autofac.Programmer,Zhy.IoC.Autofac","services": [{"type": "Zhy.IoC.Core.IPerson,Zhy.IoC.Core"}],"autoActivate": true,"instanceScope": "singleinstance"}]
}

XML

<?xml version="1.0" encoding="utf-8" ?>
<autofac><components name="0"><type>Zhy.IoC.Autofac.LenovoComputer,Zhy.IoC.Autofac</type><services name="0" type="Zhy.IoC.Core.IComputer,Zhy.IoC.Core" /></components><components name="1"><type>Zhy.IoC.Autofac.TogarKeyboard,Zhy.IoC.Autofac</type><services name="0" type="Zhy.IoC.Core.IKeyboard,Zhy.IoC.Core" /></components><components name="2"><type>Zhy.IoC.Autofac.LogitechMouse,Zhy.IoC.Autofac</type><services name="0" type="Zhy.IoC.Core.IMouse,Zhy.IoC.Core" /></components><components name="3"><type>Zhy.IoC.Autofac.Programmer,Zhy.IoC.Autofac</type><services name="0" type="Zhy.IoC.Core.IPerson,Zhy.IoC.Core" /></components>
</autofac>

调用

var config = new ConfigurationBuilder();
config.AddJsonFile("DI-Autofac.json");
// config.AddXmlFile("DI-Autofac.xml");
var module = new ConfigurationModule(config.Build());
var builder = new ContainerBuilder();
builder.RegisterModule(module);
var container = builder.Build();
IPerson programmer = container.Resolve<IPerson>();
programmer.Work();

输出

Zhy.IoC.Autofac.LenovoComputer - 被构造了
Zhy.IoC.Autofac.TogarKeyboard - 被构造了
Zhy.IoC.Autofac.LogitechMouse - 被构造了
Zhy.IoC.Autofac.Programmer - 被构造了
Programmers are building software...

AOP

Nuget安装

在这里插入图片描述

定义接口、实现类

public interface IMyService
{void DoWork();
}
public void DoWork()
{Console.WriteLine("Doing work...");
}

定义切面

using Castle.DynamicProxy;public class LoggingInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){Console.WriteLine($"Invoking method {invocation.Method.Name} at {DateTime.Now}");invocation.Proceed();Console.WriteLine($"Method {invocation.Method.Name} has completed at {DateTime.Now}");}
}

容器配置

var builder = new ContainerBuilder();
builder.Register(c => new LoggingInterceptor());
builder.RegisterType<MyService>().As<IMyService>().EnableInterfaceInterceptors().InterceptedBy(typeof(LoggingInterceptor));
var container = builder.Build();
var service = container.Resolve<IMyService>();
service.DoWork();

输出

Invoking method DoWork at 2024/5/30 16:49:34
Doing work...
Method DoWork has completed at 2024/5/30 16:49:34

参考资料

IOC容器之Unity与AutoFac_unity autofac-CSDN博客

Autofac/src/Autofac at develop · autofac/Autofac (github.com)

控制容器的反转和依赖关系注入模式 (martinfowler.com)

相关文章:

.NET IoC 容器(三)Autofac

目录 .NET IoC 容器&#xff08;三&#xff09;AutofacAutofacNuget 安装实现DI定义接口定义实现类依赖注入 注入方式构造函数注入 | 属性注入 | 方法注入注入实现 接口注册重复注册指定参数注册 生命周期默认生命周期单例生命周期每个周期范围一个生命周期 依赖配置Nuget配置文…...

Day44 动态规划part04

背包问题 01背包问题&#xff1a;每件物品只能用一次完全背包问题&#xff1a;每件物品可以使用无数次 01背包问题 暴力解法&#xff1a;每一件物品其实只有两个状态&#xff0c;取或者不取&#xff0c;所以可以使用回溯法搜索出所有的情况&#xff0c;那么时间复杂度就是 o…...

html期末复习速览

一.基础标签 1.段落标签<p></p> 特点&#xff1a;分段分割 2.标题标签<h1></h1>……<h6></h6> 特点&#xff1a;文字加粗&#xff0c;单独占一行 3.换行标签<br /> 特点&#xff1a;单标签&#xff0c;强制换行 二.文本格式化…...

CTFHUB-信息泄露-目录遍历和PHPINFO

目录 目录遍历 PHPINFO 目录遍历 很简单&#xff0c;挨着把每个目录都点开看一下 发现2目录下有个 flag.txt 文件&#xff0c;点开发现了本关的flag PHPINFO 这关也很简单&#xff0c;进来之后是一个phpinfo页面&#xff0c;按 CTRL F键打开查询&#xff0c;输入flag&#…...

面向Java程序员的Go工程开发入门流程

对于一个像我这样没有go背景的java程序员来说&#xff0c;使用go开发一个可用的程序的速度是肉眼可见的缓慢。 其难点不在于go语言本身&#xff0c;而是搭建整个工程链路的过程&#xff0c;即所谓的“配环境”。 本文主要讲述如何配出一个适合go开发的环境&#xff0c;以免有同…...

vue3开发高德地图

在vue3的index.html 使用动态注入地址名和key <html lang"en"><head><meta charset"UTF-8" /><link rel"icon" type"image/svgxml" href"/vite.svg" /><meta name"viewport" conten…...

通过DLL方式链接glfw3.dll

主要是CMakeLists.txt文件变化 cmake_minimum_required(VERSION 3.10) project(glfwTest) set(CMAKE_CXX_STANDARD 11) aux_source_directory(. SRC_SOURCES) set(GLFW_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include) set(GLFW_LIBRARY_DIR ${CMAKE_SOURCE_DIR}/lib/glfw) add_ex…...

Python自然语言处理(NLP)库之NLTK使用详解

概要 自然语言处理(NLP)是人工智能和计算机科学中的一个重要领域,涉及对人类语言的计算机理解和处理。Python的自然语言工具包(NLTK,Natural Language Toolkit)是一个功能强大的NLP库,提供了丰富的工具和数据集,帮助开发者进行各种NLP任务,如分词、词性标注、命名实体…...

sqoop操作

介绍 sqoop是隶属于Apache旗下的, 最早是属于cloudera公司的,是一个用户进行数据的导入导出的工具, 主要是将关系型的数据库(MySQL, oracle...)导入到hadoop生态圈(HDFS,HIVE,Hbase...) , 以及将hadoop生态圈数据导出到关系型数据库中 操作 将数据从mysql中导入到HDFS中 1.全量…...

【Qt秘籍】[002]-开始你的Qt之旅-下载

一、Qt的开发工具有哪些&#xff1f; Qt的开发工具概述Qt支持多种开发工具&#xff0c;其中最常见的开发工具是 1.QtCreator 【易上手/有少量bug/适合新手】 2.VisualStudio 【功能强大/易出错/需要更多额外配置】 3.Eclipse 【清朝老兵IDE/不建议使用】 【注意&#xff1…...

【自动驾驶】点与向量从ego系转odometry系

1.点从ego系转odometry系(ego -> odometry) struct Point {float x;float y;float angle; }; Point trans; // is the odom to ego transform Point odom_coord; is the odom coord Point ego_coord; is the ego coordfloat odom_coord.x = (ego_coord.x - trans.x) * st…...

jsmug:一个针对JSON Smuggling技术的测试PoC环境

关于jsmug jsmug是一个代码简单但功能强大的JSON Smuggling技术环境PoC&#xff0c;该工具可以帮助广大研究人员深入学习和理解JSON Smuggling技术&#xff0c;并辅助提升Web应用程序的安全性。 背景内容 JSON Smuggling技术可以利用目标JSON文档中一些“不重要”的字节数据实…...

Qt 控件提升

什么是控件提升&#xff08;Widget Promotion&#xff09; 控件提升是一个在Qt编程中常见但容易被忽视的概念。简单来说&#xff0c;控件提升就是将一个基础控件&#xff08;Base Widget&#xff09;转换为一个更特定、更复杂的自定义控件&#xff08;Custom Widget&#xff09…...

封装一个websocket,支持断网重连、心跳检测,拿来开箱即用

封装一个websocket&#xff0c;支持断网重连、心跳检测 代码封装 编写 WebSocketClient.js import { EventDispatcher } from ./dispatcherexport class WebSocketClient extends EventDispatcher {constructor(url) {console.log(url, urlurl)super()this.url url}// #soc…...

推荐一款开源电子签章/电子合同系统

文章目录 前言一、项目介绍二、项目地址三、技术架构四、代码结构介绍五、功能模块六、功能界面首页面手写签名面板电子印章制作数字证书生成 总结 前言 大家好&#xff01;我是智航云科技&#xff0c;今天为大家分享一个免费开源的电子签字系统。 一、项目介绍 开放签电子签…...

Qt Creator(Qt 6.6)拷贝一行

Edit - Preference - Environment&#xff1a; 可看到&#xff0c;拷贝一行的快捷键是&#xff1a; ctrl Ins...

红队内网攻防渗透:内网渗透之数据库权限提升技术

红队内网攻防渗透 1. 内网权限提升技术1.1 数据库权限提升技术1.1.1 数据库提权流程1.1.1.1 先获取到数据库用户密码1.1.1.2 利用数据库提权工具进行连接1.1.1.3 利用建立代理解决不支持外联1.1.1.4 利用数据库提权的条件及技术1.1.2 Web到Win-数据库提权-MSSQL1.1.3 Web到Win-…...

从0开始制作微信小程序

目录 前言 正文 需要事先准备的 需要事先掌握的 什么是uniapp 平台应用的分类方式 什么是TypeScript 创建项目 项目文件作用 源码地址 尾声 &#x1f52d; Hi,I’m Pleasure1234&#x1f331; I’m currently learning Vue.js,SpringBoot,Computer Security and so on.&#x1…...

Linux学习笔记:日志文件的编写

日志文件Log.hpp 日志文件的作用简单的日志文件编写 日志文件的作用 日志文件可以很好的帮我们显示出程序运行的信息,例如,进程pid,运行时间,运行状况等,通过日志记录程序的执行路径、变量值、函数调用等&#xff0c;可以帮助我们快速定位和修复代码中的错误。 简单的日志文件…...

为什么要保持方差为1

1.数值稳定性&#xff1a; 在机器学习和深度学习中&#xff0c;维持激活函数输入的方差在一个合理范围内&#xff08;如1&#xff09;是很重要的&#xff0c;这有助于防止在训练过程中发生梯度消失或梯度爆炸的问题。如果方差过大或过小&#xff0c;经过多层网络后输出结果的方…...

Wpf 使用 Prism 实战开发Day31

登录数据绑定 1.首先在LoginViewModel 登录逻辑处理类中&#xff0c;创建登录要绑定属性和命令 public class LoginViewModel : BindableBase, IDialogAware {public LoginViewModel(){ExecuteCommand new DelegateCommand<string>(Execure);}public string Title { ge…...

Linux权限提升二

#应用场景&#xff1a; 获取到Web权限或普通用户在Linux服务器上时进行的SUID&SUDO提权 SUID (Set owner User ID up on execution)是给予文件的一个特殊类型的文件权限。在Linux/Unix中&#xff0c;当一个程序运行的时候&#xff0c;程序将从登录用户处继承权限。SUID被定…...

[AI OpenAI] 推出ChatGPT Edu

一种负担得起的解决方案&#xff0c;帮助大学将AI负责任地引入校园。 我们宣布推出ChatGPT Edu&#xff0c;这是一个专为大学设计的ChatGPT版本&#xff0c;旨在负责任地向学生、教职员工、研究人员和校园运营部署AI。ChatGPT Edu由GPT-4o提供支持&#xff0c;能够跨文本和视觉…...

HTML5+CSS3回顾总结

一、HTML5新特性 1.语义化标签 <header> 头部标签<nav> 导航标签<article> 内容标签<section> 定义文档某个区域<aside> 侧边栏标签<footer> 尾部标签 2.多媒体标签 2.1视频标签vedio 》常规写法&#xff08;尽量都使用mp4&#xff0…...

AI推介-多模态视觉语言模型VLMs论文速览(arXiv方向):2024.05.01-2024.05.10

文章目录~ 1.Pseudo-Prompt Generating in Pre-trained Vision-Language Models for Multi-Label Medical Image Classification2.VLSM-Adapter: Finetuning Vision-Language Segmentation Efficiently with Lightweight Blocks3.Memory-Space Visual Prompting for Efficient …...

Python 点云生成高程模型图(DSM)

点云生成高程模型图 一、什么是DSM?二、python代码三、结果可视化一、什么是DSM? DSM(Digital Surface Model)是一种数字高程模型,通常用于描述地表地形的数字化表示。它是由一系列离散的高程数据点组成的三维地形模型,其中每个点都具有其相应的高程值。   DSM主要用于…...

[第五空间 2021]WebFTP

题目是WebFTP 通过标签可以看出git泄露(git泄露是指开发人员利用git进行版本控制) 通过网上了解WebFTP的源码账号admin 密码admin888 进去之后正常思路是我们利用/.git 在githack里面进行复现 查看log看看有没有flag 但是经过我们查询之后不是这样子 通过一段时间摸索在phpinf…...

SQL—DQL(数据查询语言)之小结

一、引言 在前面我们已经学习完了所有的关于DQL&#xff08;数据查询语言&#xff09;的基础语法块部分&#xff0c;现在对DQL语句所涉及的语法&#xff0c;以及需要注意的事项做一个简单的总结。 二、DQL语句 1、基础查询 注意&#xff1a; 基础查询的语法是&#xff1a;SELE…...

找回xmind文件办法:一切意外均可找回(误删/重启关机等)

我周三编辑完&#xff0c;周四下午评审完用例忘记保存 结果到了快乐星期五&#xff0c;由于是周五我太开心了...早上到公司后觉得电脑卡&#xff0c;直接点了重启啥都没保存啊啊啊啊啊 准备上传测试用例时才想起来我的用例找不见了&#xff01;&#xff01;&#xff01;&…...

微信小程序 npm构建+vant-weaap安装

微信小程序&#xff1a;工具-npm构建 报错 解决&#xff1a; 1、新建miniprogram文件后&#xff0c;直接进入到miniprogram目录&#xff0c;再次执行下面两个命令&#xff0c;然后再构建npm成功 npm init -y npm install express&#xff08;Node js后端Express开发&#xff…...

【LeetCode 63】 不同路径 II

1. 题目 2. 分析 这道题比较典型&#xff0c;跟最小路径和 是同样的思想。比较简单。 3. 代码 class Solution:def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:row len(obstacleGrid)col len(obstacleGrid[-1]) dp [[0] *(col) f…...

OpenAI助手API接入-问答对自动生成

支持GPT-3.5-Turbo, GPT-4o, GPT-4-Turbo import json import openai from pathlib import Path import os client openai.OpenAI(base_urlbase_url, api_keyapi_key) file client.files.create( fileopen("H3.pdf", "rb"), purposeassistants ) …...

9. C++通过epoll+fork的方式实现高性能网络服务器

epollfork 实现高性能网络服务器 一般在服务器上&#xff0c;CPU是多核的&#xff0c;上述epoll实现方式只使用了其中的一个核&#xff0c;造成了资源的大量浪费。因此我们可以将epoll和fork结合来实现更高性能的网络服务器。 创建子进程函数–fork( ) 要了解线程我们先来了解…...

【Mac】XMind for mac(XMind思维导图)v24.04.10311软件介绍和安装教程

软件介绍 XMind for Mac是一款功能强大的思维导图软件。它具有以下主要特点&#xff1a; 1.多样化的思维导图功能&#xff1a;XMind for Mac提供了丰富的思维导图编辑功能&#xff0c;用户可以创建各种类型的思维导图&#xff0c;包括组织结构图、逻辑图、时间轴图等&#xf…...

使用 Django ORM 进行数据库操作

文章目录 创建Django项目和应用定义模型查询数据更新和删除数据总结与进阶聚合和注解跨模型查询原始SQL查询 Django是一个流行的Web应用程序框架&#xff0c;它提供了一个强大且易于使用的对象关系映射&#xff08;ORM&#xff09;工具&#xff0c;用于与数据库进行交互。在本文…...

行为型设计模式之模板模式

文章目录 概述原理结构图实现 小结 概述 模板方法模式(template method pattern)原始定义是&#xff1a;在操作中定义算法的框架&#xff0c;将一些步骤推迟到子类中。模板方法让子类在不改变算法结构的情况下重新定义算法的某些步骤。 模板方法中的算法可以理解为广义上的业…...

大泽动力车载柴油发电机的特点和优势有哪些

大泽动力车载柴油发电机具有一系列显著的特点和优势&#xff0c;以下是对其的详细介绍&#xff1a; 低噪音性能&#xff1a;大泽动力车载柴油发电机具备明显的低噪音性能&#xff0c;其噪音限值在距离机组7米处测得为70dB(A)&#xff0c;这为用户提供了一个相对安静的工作环境…...

基于 IP 的 DDOS 攻击实验

一、介绍 基于IP的分布式拒绝服务&#xff08;Distributed Denial of Service, DDoS&#xff09;攻击是一种利用大量受控设备&#xff08;通常是僵尸网络&#xff09;向目标系统发送大量请求或数据包&#xff0c;以耗尽目标系统的资源&#xff0c;导致其无法正常提供服务的攻击…...

GPT-4o如何重塑AI未来!

如何评价GPT-4o? 简介&#xff1a;最近&#xff0c;GPT-4o横空出世。对GPT-4o这一人工智能技术进行评价&#xff0c;包括版本间的对比分析、GPT-4o的技术能力以及个人感受等。 GPT-4o似乎是一个针对GPT-4模型进行优化的版本&#xff0c;它在性能、准确性、资源效率以及安全和…...

window本地域名映射修改

位置 C:\Windows\System32\drivers\etc 文件名 hosts 修改方法 复制一份到桌面 修改桌面的文件 # 前面为ip 后面为域名&#xff0c;域名-》ip的映射 127.0.0.1 link.com最后将修改后的文件保存&#xff0c;复制到C:\Windows\System32\drivers\etc替换...

【退役之重学】为什么要加入多级缓存

一、为什么 加入多级缓存是为了提高数据访问的效率和性能 二、怎么做 在多级访问系统中&#xff0c;数据首先会被存储在速度最快的 L1 缓存中&#xff0c;如果数据在 L1 缓存中未命中&#xff0c;则会继续在 L2 缓存 和 L3 缓存中查找&#xff0c;如果在所有缓存中都未命中&…...

Redis常用命令大全

目录 1、五大数据类型的基本命令 1.1 字符串 1.2 列表 1.3 哈希 1.4 集合 1.5 有序集合 2、与key相关 2.1 查看redis数据的类型 2.2 查看当前redis库中的所有key命令 3、除了五大数据类型外常见命令 3.1 键操作 3.2 服务器操作 3.3 连接操作 3.4 发布/订阅 3.5 事…...

HttpSecurity 是如何组装过滤器链的

有小伙伴们问到这个问题&#xff0c;简单写篇文章和大伙聊一下。 一 SecurityFilterChain 首先大伙都知道&#xff0c;Spring Security 里边的一堆功能都是通过 Filter 来实现的&#xff0c;无论是认证、RememberMe Login、会话管理、CSRF 处理等等&#xff0c;各种功能都是通…...

STM32 入门教程(江科大教材)#笔记2

3-4按键控制LED /** LED.c**/ #include "stm32f10x.h" // Device headervoid LED_Init(void) {/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_I…...

python zip()函数(将多个可迭代对象的元素配对,创建一个元组的迭代器)zip_longest()

文章目录 Python zip() 函数深入解析基本用法函数原型基础示例 处理不同长度的迭代器高级用法多个迭代器使用 zip() 与 dict()解压序列 注意事项内存效率&#xff1a;zip() 返回的是一个迭代器&#xff0c;这意味着直到迭代发生前&#xff0c;元素不会被消耗。这使得 zip() 特别…...

React.forwardRef 使用

React.forwardRef 是一个React提供的高阶组件函数&#xff0c;用于向函数组件传递ref。在函数组件中无法直接访问ref&#xff0c;如果需要在函数组件中操作子组件的DOM元素或组件实例&#xff0c;就可以使用React.forwardRef来转发ref给子组件。 当使用React.forwardRef包裹一…...

C# 中的值类型与引用类型:内存大小解析

在 C# 中&#xff0c;类型可以被归类为值类型或引用类型&#xff0c;它们在内存中的存储和管理方式不同。了解这些差异对于优化程序性能和资源管理至关重要。 值类型 (Value Types) 值类型包括所有内置的数值类型&#xff08;如 int, double 等&#xff09;、char 类型、bool…...

object对象列表使用sorted函数按照对象的某个字段排序

在Python中&#xff0c;如果你想要根据列表中对象的某个属性&#xff08;比如create_time&#xff09;来进行逆序排序&#xff0c;你可以使用sorted()函数并指定一个key参数。key参数应该是一个函数&#xff0c;该函数接受一个列表元素并返回一个用于排序的值。 假设你的objec…...

【再探】设计模式—中介者模式、观察者模式及模板方法模式

中介者模式让多对多的复杂引用关系变成一对多&#xff0c;同时能通过中间类来封装多个类中的行为&#xff0c;观察者模式在目标状态更新时能自动通知给订阅者&#xff0c;模版方法模式则是控制方法的执行顺序&#xff0c;子类在不改变算法的结构基础上可以扩展功能实现。 1 中…...

vue中使用svg图像

一 、svg图像是什么 SVG&#xff08;可缩放矢量图形&#xff09;是一种图像格式&#xff0c;它以XML文档的形式存在&#xff0c;用以描述图像中的形状、线条、文本和颜色等元素。由于其基于矢量的特性&#xff0c;SVG图像在放大或改变尺寸时能够保持图形质量不受影响。这种格式…...