WPF依賴注入

一、IOC 在 WPF 中的原理

控制反轉(IOC)是一種設計原則,它將對象的創建和依賴關系的管理從對象本身轉移到外部容器(IOC 容器)。在傳統的編程方式中,一個對象如果需要使用另一個對象(即存在依賴關系),通常會在自身內部通過?new?關鍵字等方式直接創建被依賴的對象,這就導致了對象之間的緊密耦合。而在 IOC 模式下,由 IOC 容器負責創建對象,并在對象需要時將其依賴的對象注入進去。這樣,對象只需要關注自身的業務邏輯,而不需要關心依賴對象的創建過程,從而實現了對象之間依賴關系的解耦。

?

在 WPF 應用中,這種解耦可以使視圖、視圖模型和其他組件之間的關系更加清晰和靈活,便于代碼的維護和擴展。例如,視圖模型依賴于數據訪問服務來獲取數據,通過 IOC,數據訪問服務的具體實現可以由 IOC 容器注入到視圖模型中,而不是視圖模型自己去創建數據訪問服務的實例。

二、IOC 在 WPF 中的作用

  1. 降低耦合度:使得組件之間的依賴關系更加松散,一個組件的變化不會輕易影響到其他組件。比如,當數據訪問層的實現從數據庫 A 切換到數據庫 B 時,只需要在 IOC 容器中修改數據訪問服務的注冊配置,而使用該數據訪問服務的業務邏輯組件無需進行修改。
  2. 提高可維護性:由于組件之間的耦合度降低,當需要修改或替換某個組件的依賴時,只需要在 IOC 容器中進行配置修改,而無需在大量的組件代碼中查找和修改與依賴創建相關的代碼。
  3. 增強可測試性:在進行單元測試時,可以方便地使用模擬對象或測試替身替換實際的依賴對象。例如,在測試視圖模型時,可以注入一個模擬的數據訪問服務,返回預設的數據,使單元測試更加獨立和簡單,不受實際依賴對象的影響。
  4. 實現依賴注入:可以在對象創建時將其依賴的對象自動注入,簡化對象的初始化過程。對象在設計時只需要定義好依賴關系(通常通過構造函數、屬性或方法參數來體現),IOC 容器會負責在合適的時機將依賴對象傳遞給它。

三、IOC 在 WPF 中的優劣勢

  1. 優勢
    1. 靈活性高:可以根據不同的需求或環境,動態地切換依賴對象的實現。例如,在開發環境中使用模擬的服務進行測試,而在生產環境中切換到實際的服務實現。
    2. 代碼復用性好:由于依賴關系的解耦,組件可以更容易地在不同的項目或模塊中復用。一個組件只依賴于抽象的接口或抽象類,只要提供符合接口定義的實現,就可以在不同的上下文中使用該組件。
    3. 易于擴展:添加新的功能或依賴時,對現有代碼的影響較小,只需要在 IOC 容器中進行相應的配置。例如,添加一個新的日志服務,只需要在 IOC 容器中注冊該日志服務的實現,并在需要使用日志服務的組件中注入它,而不需要對其他組件進行大規模的修改。
  2. 劣勢
    1. 學習成本較高:理解和使用 IOC 需要一定的學習成本,尤其是對于初學者來說,需要掌握相關的概念(如依賴注入、控制反轉)和技術(如如何配置 IOC 容器、如何進行依賴注入)。
    2. 配置復雜:在大型項目中,IOC 容器的配置可能會變得復雜,需要仔細管理和維護,否則可能會導致難以調試的問題。例如,當存在大量的依賴關系和不同的對象生命周期管理時,配置不當可能會導致對象創建錯誤或依賴關系混亂。

四、IOC 在 WPF 中的寫法要求

  1. 定義接口或抽象類:首先要明確組件之間的依賴關系,定義好接口或抽象類,作為依賴的契約。接口或抽象類應該清晰地定義出所提供的功能和行為,例如定義一個?ICustomerService?接口,其中聲明獲取客戶信息、保存客戶信息等方法。
  2. 實現具體類:針對每個接口或抽象類,編寫具體的實現類,實現接口中定義的方法或屬性。例如,實現?ICustomerService?接口的?SqlCustomerService?類,在其中實現從數據庫中獲取和保存客戶信息的具體邏輯。
  3. 創建 IOC 容器:編寫一個簡單的 IOC 容器類,用于管理對象的注冊和解析。通常使用字典來存儲接口和實現類的映射關系。容器類應該提供注冊接口和實現類映射關系的方法(如?Register?方法),以及根據接口解析出對應實現類實例的方法(如?Resolve?方法)。
  4. 注冊映射關系:在 IOC 容器中,將接口和對應的實現類進行注冊,建立它們之間的映射關系。可以使用泛型方法來實現注冊,例如?Register<TInterface, TImplementation>(),其中?TInterface?是接口類型,TImplementation?是實現類類型。
  5. 進行依賴注入:在需要使用依賴對象的組件中,通過構造函數、屬性或方法注入依賴對象。在創建組件實例時,從 IOC 容器中獲取相應的依賴對象并進行注入。例如,在視圖模型的構造函數中接收依賴的服務對象,或者通過屬性設置依賴對象。

五、IOC 在 WPF 中的應用場景

  1. 業務邏輯層與數據訪問層的解耦:在 WPF 應用中,業務邏輯層通常依賴數據訪問層來獲取和存儲數據。通過 IOC,可以將數據訪問層的具體實現(如數據庫訪問類)注入到業務邏輯層中,使業務邏輯層與具體的數據訪問技術(如 SQL Server、MySQL 等)解耦。這樣,當需要更換數據庫或數據訪問方式時,只需要在 IOC 容器中修改數據訪問服務的注冊配置,而業務邏輯組件無需修改。
  2. 視圖模型與服務的注入:視圖模型(ViewModel)通常需要依賴一些服務(如網絡服務、日志服務、消息推送服務等)來完成其功能。使用 IOC 可以將這些服務注入到視圖模型中,提高視圖模型的可測試性和可維護性。例如,在視圖模型中注入日志服務,以便在處理業務邏輯時記錄相關信息,而在測試視圖模型時可以注入模擬的日志服務,避免實際的日志輸出影響測試結果。
  3. 多語言支持:可以將不同語言的資源文件加載邏輯封裝成服務,通過 IOC 注入到視圖中,實現多語言的切換和支持。例如,創建一個?ILanguageService?接口,實現類負責根據用戶設置加載相應語言的資源文件,并將其注入到視圖中,從而實現視圖的多語言顯示。
  4. 插件式架構:當應用程序需要實現插件式架構時,IOC 可以幫助管理插件的依賴關系。插件可以通過接口來定義其功能,然后在 IOC 容器中注冊插件的實現,使得主應用程序能夠方便地加載和使用插件。主應用程序可以依賴于插件接口,而不需要關心插件的具體實現,從而實現插件的動態插拔和擴展。

六、5 個 IOC 容器示例代碼及解析

示例 1:構造函數注入簡單服務

?

csharp

using?System;using?System.Collections.Generic;using?System.Windows;

// 定義IOC容器類class?SimpleIocContainer{

????// 使用字典存儲接口和對應的創建實例的委托

????private?readonly?Dictionary<Type, Func<object>>?_registrations =?new?Dictionary<Type, Func<object>>();

?

????// 注冊接口和實現類的映射關系

????public?void?Register<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????// 將創建TImplementation實例的委托存入字典,鍵為TInterface的Type對象

????????_registrations[typeof(TInterface)]?=?()?=>?Activator.CreateInstance<TImplementation>();

????}

?

????// 根據接口解析出對應的實現類實例

????public?TInterface?Resolve<TInterface>()

????{

????????if?(_registrations.TryGetValue(typeof(TInterface),?out?var?factory))

????????{

????????????// 如果字典中存在對應的創建委托,則調用委托創建實例并返回

????????????return?(TInterface)factory();

????????}

????????throw?new?Exception($"Type {typeof(TInterface)} is not registered.");

????}}

// 定義服務接口interface?IMessageService{

????string?GetMessage();}

// 實現服務接口class?ConsoleMessageService?:?IMessageService{

????public?string?GetMessage()

????{

????????return?"Hello from ConsoleMessageService!";

????}}

// 視圖模型類,通過構造函數注入服務class?MainViewModel{

????// 保存注入的IMessageService實例

????private?readonly?IMessageService?_messageService;

?

????// 構造函數接收IMessageService實例作為參數,實現依賴注入

????public?MainViewModel(IMessageService?messageService)

????{

????????_messageService =?messageService;

????}

?

????// 視圖模型的方法,調用注入的服務獲取消息

????public?string?GetViewModelMessage()

????{

????????return?_messageService.GetMessage();

????}}

// 主窗口類public?partial?class?MainWindow?:?Window{

????public?MainWindow()

????{

????????InitializeComponent();

?

????????// 創建IOC容器實例

????????var?container =?new?SimpleIocContainer();

????????// 注冊IMessageService接口和ConsoleMessageService實現類的映射關系

????????container.Register<IMessageService, ConsoleMessageService>();

?

????????// 從IOC容器中解析出MainViewModel實例,此時會自動注入已注冊的IMessageService實例

????????var?viewModel =?container.Resolve<MainViewModel>();

????????// 設置窗口的數據上下文為視圖模型實例

????????DataContext =?viewModel;

????}}

?

解析:此示例展示了最基本的構造函數注入方式。SimpleIocContainer?類實現了簡單的 IOC 容器功能,通過?Register?方法注冊接口和實現類的映射,Resolve?方法根據接口解析實例。IMessageService?定義了服務接口,ConsoleMessageService?是其實現類。MainViewModel?通過構造函數接收?IMessageService?實例,實現依賴注入。在主窗口中,創建 IOC 容器,注冊映射關系,解析出視圖模型并設置為數據上下文,從而實現了從容器中獲取依賴并注入到視圖模型的過程。

?

示例 2:屬性注入服務

?

csharp

using?System;using?System.Collections.Generic;using?System.Windows;

class?SimpleIocContainer{

????private?readonly?Dictionary<Type, Func<object>>?_registrations =?new?Dictionary<Type, Func<object>>();

?

????public?void?Register<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????_registrations[typeof(TInterface)]?=?()?=>?Activator.CreateInstance<TImplementation>();

????}

?

????public?TInterface?Resolve<TInterface>()

????{

????????if?(_registrations.TryGetValue(typeof(TInterface),?out?var?factory))

????????{

????????????return?(TInterface)factory();

????????}

????????throw?new?Exception($"Type {typeof(TInterface)} is not registered.");

????}}

interface?ILogger{

????void?Log(string?message);}

class?FileLogger?:?ILogger{

????public?void?Log(string?message)

????{

????????Console.WriteLine($"Logging to file: {message}");

????}}

class?OrderViewModel{

????// 定義可讀寫的屬性來接收注入的ILogger實例

????public?ILogger?Logger {?get;?set;?}

?

????public?void?PlaceOrder()

????{

????????// 在方法中使用注入的Logger實例記錄日志

????????Logger.Log("Order placed successfully.");

????}}

public?partial?class?MainWindow?:?Window{

????public?MainWindow()

????{

????????InitializeComponent();

?

????????var?container =?new?SimpleIocContainer();

????????container.Register<ILogger, FileLogger>();

?

????????var?viewModel =?container.Resolve<OrderViewModel>();

????????// 從IOC容器中解析出ILogger實例,并賦值給視圖模型的Logger屬性,實現屬性注入

????????viewModel.Logger =?container.Resolve<ILogger>();

?

????????DataContext =?viewModel;

????}}

?

解析:該示例使用屬性注入方式。OrderViewModel?定義了一個?Logger?屬性用于接收?ILogger?實例。在主窗口中,創建 IOC 容器并注冊?ILogger?接口和?FileLogger?實現類的映射關系。解析出?OrderViewModel?實例后,再從容器中解析出?ILogger?實例并賦值給視圖模型的?Logger?屬性,從而實現了屬性注入。視圖模型的?PlaceOrder?方法中使用注入的?Logger?實例記錄日志。

?

示例 3:方法注入服務

?

csharp

using?System;using?System.Collections.Generic;using?System.Windows;

class?SimpleIocContainer{

????private?readonly?Dictionary<Type, Func<object>>?_registrations =?new?Dictionary<Type, Func<object>>();

?

????public?void?Register<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????_registrations[typeof(TInterface)]?=?()?=>?Activator.CreateInstance<TImplementation>();

????}

?

????public?TInterface?Resolve<TInterface>()

????{

????????if?(_registrations.TryGetValue(typeof(TInterface),?out?var?factory))

????????{

????????????return?(TInterface)factory();

????????}

????????throw?new?Exception($"Type {typeof(TInterface)} is not registered.");

????}}

interface?IEmailSender{

????void?SendEmail(string?to,?string?subject,?string?body);}

class?SmtpEmailSender?:?IEmailSender{

????public?void?SendEmail(string?to,?string?subject,?string?body)

????{

????????Console.WriteLine($"Sending email to {to}: {subject} - {body}");

????}}

class?CustomerViewModel{

????private?IEmailSender?_emailSender;

?

????// 定義方法用于接收注入的IEmailSender實例

????public?void?SetEmailSender(IEmailSender?emailSender)

????{

????????_emailSender =?emailSender;

????}

?

????public?void?SendWelcomeEmail(string?customerEmail)

????{

????????// 在方法中使用注入的IEmailSender實例發送郵件

????????_emailSender.SendEmail(customerEmail,?"Welcome",?"Thank you for choosing us!");

????}}

public?partial?class?MainWindow?:?Window{

????public?MainWindow()

????{

????????InitializeComponent();

?

????????var?container =?new?SimpleIocContainer();

????????container.Register<IEmailSender, SmtpEmailSender>();

?

????????var?viewModel =?container.Resolve<CustomerViewModel>();

????????// 從IOC容器中解析出IEmailSender實例,并調用視圖模型的SetEmailSender方法進行注入

????????viewModel.SetEmailSender(container.Resolve<IEmailSender>());

?

????????DataContext =?viewModel;

????}}

?

解析:此示例采用方法注入。CustomerViewModel?定義了?SetEmailSender?方法用于接收?IEmailSender?實例。在主窗口中,創建 IOC 容器并注冊?IEmailSender?接口和?SmtpEmailSender?實現類的映射關系。解析出?CustomerViewModel?實例后,從容器中解析出?IEmailSender?實例并調用視圖模型的?SetEmailSender?方法,實現方法注入。視圖模型的?SendWelcomeEmail?方法中使用注入的?IEmailSender?實例發送歡迎郵件。

?

?

案例4

csharp

using?System;using?System.Collections.Generic;using?System.Windows;

class?SimpleIocContainer{

????private?readonly?Dictionary<Type, Func<object>>?_registrations =?new?Dictionary<Type, Func<object>>();

?

????public?void?Register<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????_registrations[typeof(TInterface)]?=?()?=>?Activator.CreateInstance<TImplementation>();

????}

?

????public?TInterface?Resolve<TInterface>()

????{

????????if?(_registrations.TryGetValue(typeof(TInterface),?out?var?factory))

????????{

????????????return?(TInterface)factory();

????????}

????????throw?new?Exception($"Type {typeof(TInterface)} is not registered.");

????}}

interface?IDataAccess{

????string?GetData();}

class?SqlDataAccess?:?IDataAccess{

????public?string?GetData()

????{

????????return?"Data retrieved from SQL database.";

????}}

interface?IBusinessLogic{

????string?ProcessData();}

class?BusinessLogic?:?IBusinessLogic{

????// 保存注入的IDataAccess實例

????private?readonly?IDataAccess?_dataAccess;

?

????// 構造函數接收IDataAccess實例作為參數,實現第一層依賴注入

????public?BusinessLogic(IDataAccess?dataAccess)

????{

????????_dataAccess =?dataAccess;

????}

?

????// 業務邏輯方法,調用注入的IDataAccess實例獲取數據并處理

????public?string?ProcessData()

????{

????????return?$"Processed: {_dataAccess.GetData()}";

????}}

class?MainViewModel{

????// 保存注入的IBusinessLogic實例

????private?readonly?IBusinessLogic?_businessLogic;

?

????// 構造函數接收IBusinessLogic實例作為參數,實現第二層依賴注入

????public?MainViewModel(IBusinessLogic?businessLogic)

????{

????????_businessLogic =?businessLogic;

????}

?

????// 視圖模型的方法,調用注入的IBusinessLogic實例獲取處理后的數據

????public?string?GetViewModelData()

????{

????????return?_businessLogic.ProcessData();

????}}

public?partial?class?MainWindow?:?Window{

????public?MainWindow()

????{

????????InitializeComponent();

?

????????var?container =?new?SimpleIocContainer();

????????// 注冊IDataAccess接口和SqlDataAccess實現類的映射關系

????????container.Register<IDataAccess, SqlDataAccess>();

????????// 注冊IBusinessLogic接口和BusinessLogic實現類的映射關系

????????container.Register<IBusinessLogic, BusinessLogic>();

?

????????// 從IOC容器中解析出MainViewModel實例,此時會自動按照依賴關系

????????// 先解析出BusinessLogic實例,而BusinessLogic實例的創建又會依賴于

????????// 已注冊的SqlDataAccess實例,從而實現多層依賴注入

????????var?viewModel =?container.Resolve<MainViewModel>();

????????DataContext =?viewModel;

????}}

?

解析:此示例展示了多層依賴注入的情況。BusinessLogic?類依賴于?IDataAccess?接口,通過構造函數注入?IDataAccess?實例來獲取數據并進行處理。MainViewModel?類又依賴于?IBusinessLogic?接口,同樣通過構造函數注入?IBusinessLogic?實例。在主窗口中,先在 IOC 容器中分別注冊?IDataAccess?與?SqlDataAccess、IBusinessLogic?與?BusinessLogic?的映射關系。當解析?MainViewModel?實例時,IOC 容器會按照依賴關系,先創建?BusinessLogic?實例,而創建?BusinessLogic?實例時又會去解析并注入?SqlDataAccess?實例,從而實現了多層依賴的正確注入和使用。

?

示例 5:單例模式在 IOC 中的應用

?

csharp

using?System;using?System.Collections.Generic;using?System.Windows;

class?SimpleIocContainer{

????// 存儲接口和對應的創建實例的委托

????private?readonly?Dictionary<Type, Func<object>>?_registrations =?new?Dictionary<Type, Func<object>>();

????// 存儲單例對象,鍵為接口的Type對象,值為單例實例

????private?readonly?Dictionary<Type, object>?_singletons =?new?Dictionary<Type, object>();

?

????// 注冊普通的接口和實現類的映射關系

????public?void?Register<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????_registrations[typeof(TInterface)]?=?()?=>?Activator.CreateInstance<TImplementation>();

????}

?

????// 注冊單例模式的接口和實現類的映射關系

????public?void?RegisterSingleton<TInterface, TImplementation>()?where?TImplementation?:?TInterface

????{

????????_registrations[typeof(TInterface)]?=?()?=>

????????{

????????????// 如果單例字典中不存在該接口對應的實例,則創建一個新的實例并存儲

????????????if?(!_singletons.ContainsKey(typeof(TInterface)))

????????????{

????????????????_singletons[typeof(TInterface)]?=?Activator.CreateInstance<TImplementation>();

????????????}

????????????// 返回已存儲的單例實例

????????????return?_singletons[typeof(TInterface)];

????????};

????}

?

????// 根據接口解析出對應的實現類實例

????public?TInterface?Resolve<TInterface>()

????{

????????if?(_registrations.TryGetValue(typeof(TInterface),?out?var?factory))

????????{

????????????return?(TInterface)factory();

????????}

????????throw?new?Exception($"Type {typeof(TInterface)} is not registered.");

????}}

interface?IConfigurationService{

????string?GetConfigurationValue(string?key);}

class?AppConfigurationService?:?IConfigurationService{

????public?string?GetConfigurationValue(string?key)

????{

????????return?$"Value for {key} from configuration.";

????}}

class?SettingsViewModel{

????// 保存注入的IConfigurationService實例

????private?readonly?IConfigurationService?_configurationService;

?

????// 構造函數接收IConfigurationService實例作為參數,實現依賴注入

????public?SettingsViewModel(IConfigurationService?configurationService)

????{

????????_configurationService =?configurationService;

????}

?

????// 視圖模型的方法,調用注入的IConfigurationService實例獲取配置值

????public?string?GetSettingValue(string?key)

????{

????????return?_configurationService.GetConfigurationValue(key);

????}}

public?partial?class?MainWindow?:?Window{

????public?MainWindow()

????{

????????InitializeComponent();

?

????????var?container =?new?SimpleIocContainer();

????????// 注冊IConfigurationService接口和AppConfigurationService實現類為單例模式

????????container.RegisterSingleton<IConfigurationService, AppConfigurationService>();

?

????????// 從IOC容器中解析出SettingsViewModel實例,此時會注入已注冊為單例的

????????// IConfigurationService實例,保證整個應用中該服務只有一個實例

????????var?viewModel =?container.Resolve<SettingsViewModel>();

????????DataContext =?viewModel;

????}}

解析:該示例演示了在 IOC 容器中實現單例模式。SimpleIocContainer?類增加了一個?_singletons?字典用于存儲單例對象。RegisterSingleton?方法實現了單例注冊邏輯,當解析接口對應的實例時,如果單例字典中不存在該實例,則創建一個新的實例并存儲,以后每次請求該接口的實例時都返回已存儲的單例實例。IConfigurationService?定義了配置服務接口,AppConfigurationService?是其實現類。SettingsViewModel?通過構造函數注入?IConfigurationService?實例。在主窗口中,注冊?IConfigurationService?與?AppConfigurationService?的單例映射關系,解析?SettingsViewModel?實例時會注入單例的配置服務實例,確保在整個應用中該配置服務只有一個實例,避免了重復創建和資源浪費,同時也方便在不同組件中共享相同的配置信息。

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/75861.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75861.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/75861.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【大模型深度學習】如何估算大模型需要的顯存

一、模型參數量 參數量的單位 參數量指的是模型中所有權重和偏置的數量總和。在大模型中&#xff0c;參數量的單位通常以“百萬”&#xff08;M&#xff09;或“億”&#xff08;B&#xff0c;也常說十億&#xff09;來表示。 百萬&#xff08;M&#xff09;&#xff1a;表示…

BUUCTF流量分析題

文章目錄 前言wireshark被嗅探的流量被偷走的文件easycap數據包中的線索秘密文件[安洵杯 2019]Attack (難&#xff0c;沒寫)被劫持的神秘禮物大流量分析&#xff08;一&#xff09;大流量分析&#xff08;二&#xff09;大流量分析&#xff08;三&#xff09;模板模板 前言 CT…

adb檢測不到原來的設備List of devices attached解決辦法

進設備管理器-通用串行總線設備 卸載無法檢測到的設備驅動 重新拔插數據線

mapbox基礎,加載柵格圖片到地圖

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言1.1 ??mapboxgl.Map 地圖對象1.2 ??mapboxgl.Map style屬性1.3 ??raster 柵格圖層 api二、??使用本地載…

復活之我會二分

文章目錄 整數二分模板模板1&#xff1a;滿足條件的第一個數模板2&#xff1a;滿足條件的最后一個數 浮點數二分模板一、Building an Aquarium思路分析具體代碼 二、Tracking Segments思路分析具體代碼 三、Wooden Toy Festival思路分析具體代碼 四、路標設置思路分析具體代碼 …

每日c/c++題 備戰藍橋杯(握手問題)

試題 A: 握手問題 題解 題目描述 小藍組織了一場算法交流會議&#xff0c;共有50人參加。按照慣例&#xff0c;每個人都要與除自己外的其他所有人握手一次。但有7個人彼此之間沒有握手&#xff08;這7人與其他43人正常握手&#xff09;。求實際發生的握手總次數。 解題思路 …

mysql8.0.29 win64下載

mysql win64安裝包 mysql win64安裝包下載 mysql win64安裝包下載 通過網盤分享的文件&#xff1a;mysql 鏈接: https://pan.baidu.com/s/1sEOl-wSVtOG5gfIRdt5MXw?pwdgi7i 提取碼: gi7i

browser-use開源程序使 AI 代理可以訪問網站,自動完成特定的指定任務,告訴您的計算機該做什么,它就會完成它。

一、軟件介紹 文末提供程序和源碼下載 browser-use開源程序使 AI 代理可以訪問網站&#xff0c;自動完成特定的指定任務&#xff0c;瀏覽器使用是將AI代理與瀏覽器連接的最簡單方法。告訴您的計算機該做什么&#xff0c;它就會完成它。 二、快速開始 使用 pip &#xff08;Py…

CAD格式轉換器:Acme CAD Converter

Acme CAD Converter 是一款專業的多功能 CAD 文件管理工具&#xff0c;支持 ?DWG/DXF/DWF 文件查看、批量格式轉換及版本降級?&#xff0c;適用于工程設計、圖紙歸檔等場景?。軟件兼容 AutoCAD R2.5 至 2023 版本文件?&#xff0c;可輸出為 PDF、JPEG、TIFF、SVG 等 20 格式…

vmware虛擬機上Ubuntu或者其他系統無法聯網的解決方法

一、檢查虛擬機是否開啟了網絡服務 打開方式&#xff1a;控制面板->-管理工具--->服務 查找 VMware DHCP Service 和VMware NAT Service &#xff0c;確保這兩個服務已經啟動。如下圖&#xff0c;沒有啟動就點擊啟動。 二、設置網絡類型 我們一般使用前兩種多一些&…

數據結構與算法:基礎與進階

&#x1f31f; 各位看官好&#xff0c;我是maomi_9526&#xff01; &#x1f30d; 種一棵樹最好是十年前&#xff0c;其次是現在&#xff01; &#x1f680; 今天來學習C語言的相關知識。 &#x1f44d; 如果覺得這篇文章有幫助&#xff0c;歡迎您一鍵三連&#xff0c;分享給更…

使用分布式鎖和樂觀鎖解決超賣問題

在電商、秒殺等高并發場景中&#xff0c;“超賣”問題指庫存被過量扣減&#xff0c;導致實際庫存不足。以下是使用 分布式鎖 和 樂觀鎖 解決超賣問題的原理與實現方案&#xff1a; 一、超賣問題的核心原因 多個并發請求同時讀取庫存余量&#xff0c;并在本地計算后發起寫操作&…

盛水最多的容器

本題有兩種解法&#xff0c;一種是暴力解法&#xff0c;直接暴力枚舉出所有的體積比較出最大的即可&#xff0c;但是時間復雜度達到n方。超出了限制&#xff0c;另一種解法就是利用單調性解法&#xff0c;我們著重介紹一下單調性解法。 單調性解法&#xff1a; 體積vh*w&…

操作系統概述(3)

批處理系統 1.單道批處理系統 單道批處理系統是成批地處理作用&#xff0c;并且始終只有一道作業在內存中的系統。優點&#xff1a;提高系統資源的利用率和系統吞吐量。缺點&#xff1a;系統中的資源得不到充分利用。 2.多道批處理系統 引入多道程序設計技術&#xff0c;是…

數字身份DID協議:如何用Solidity編寫去中心化身份合約

本文提出基于以太坊的自主主權身份&#xff08;SSI&#xff09;實現方案&#xff0c;通過擴展ERC-734/ERC-735標準構建鏈上身份核心合約&#xff0c;支持可驗證聲明、多密鑰輪換、屬性隱私保護等特性。設計的三層架構體系將身份控制邏輯與數據存儲分離&#xff0c;在測試網環境…

【目標檢測】【深度學習】【Pytorch版本】YOLOV2模型算法詳解

【目標檢測】【深度學習】【Pytorch版本】YOLOV2模型算法詳解 文章目錄 【目標檢測】【深度學習】【Pytorch版本】YOLOV2模型算法詳解前言YOLOV2的模型結構YOLOV2模型的基本執行流程YOLOV2模型的網絡參數YOLOV2模型的訓練方式 YOLOV2的核心思想前向傳播階段反向傳播階段 總結 前…

第421場周賽:數組的最大因子得分、

Q1、數組的最大因子得分 1、題目描述 給你一個整數數組 nums。 因子得分 定義為數組所有元素的最小公倍數&#xff08;LCM&#xff09;與最大公約數&#xff08;GCD&#xff09;的 乘積。 在 最多 移除一個元素的情況下&#xff0c;返回 nums 的 最大因子得分。 注意&…

機器學習(神經網絡基礎篇)——個人理解篇5(梯度下降中遇到的問題)

在神經網絡訓練中&#xff0c;計算參數的梯度是關鍵步驟。numerical_gradient 方法旨在通過數值微分&#xff08;中心差分法&#xff09;計算損失函數對網絡參數的梯度。然而&#xff0c;該方法的實現存在一個關鍵問題&#xff0c;導致梯度計算錯誤。 1、錯誤代碼示例&#xf…

40常用控件_WindowFrame的影響

window frame 的影響 如果 widget 作為一個窗口(帶有標題欄,最小化,最大化,關閉按鈕),那么在計算尺寸和坐標的 時候就有兩種算法.包含 window frame 和 不包含 window frame. 其中x(),y0,frameGeometry(), pos(),move() 都是按照包含 window frame 的方式來計算 的. 其中 geome…

Nginx搭建API網關服務教程-系統架構優化 API統一管理

超實用&#xff01;用Nginx搭建API網關服務&#xff0c;讓你的系統架構更穩更強大&#xff01;&#x1f680; 親們&#xff0c;今天來給大家種草一個超級實用的API網關搭建方案啦&#xff01;&#x1f440; 在如今的Web系統架構中&#xff0c;一個穩定、高性能、可擴展的API網…