強大的依賴注入框架 StrangeIoC

對於開發者來說,一個好的依賴注入框架會大幅提高代碼的可讀性、可測試性和靈活性。很多框架都只是提供了一個基礎的依賴注入功能,但 StrangeIoC 這個框架的特點就是強大到可以為你的整個應用程序管理依賴和組件。

一、StrangeIoC 框架的概述

StrangeIoC 是用於 Unity3D 遊戲引擎的依賴注入框架,可以幫助 Unity 開發者更好的構建應用程序。這個框架以依賴注入和解耦為目標來設計,主要由三個部分組成:Bind、Injection、CrossContext。

1. Bind

Bind 是這個框架的核心部分,它是為了構建綁定關係的。當你需要將某些類型綁定到另外一些類型時,Bind 就是你需要使用的工具。Bind 是由一個 Binder 類型來掌控的。而 Binder 又用一個 Binding 類來表達綁定信息,它們之間的關係如下圖所示:

![Binder和Binding的關係](pic/binder_binding.png)

在圖中,你可以看到 Binder 中包含了一個 Binding 的字典,Binding 表示了一個綁定關係。對於一個類型來說,它可以綁定到多個 Binding 上,但每個 Binding 只能被一個類型綁定。在使用 Bind 進行綁定時,通常需要指定一個綁定的鍵值,這個鍵值可以是一個類型、字符串或對象等,但必須保證唯一。

2. Injection

Injection 即插入,是這個框架的第二個部分。它主要是通過依賴注入的方式向對象中注入所需的依賴。你可以通過兩種方式來進行注入:屬性注入和構造函數注入。

屬性注入:在類中定義屬性,並用 [Inject] 標記標記需要注入的屬性,StrangeIoC 將會在對象被注入時將綁定的類型實例自動注入到它們的對象中。

“`csharp
public class SomeComponent : MonoBehaviour {
[Inject]
public SomeService SomeService { get; set; }
// …
}
“`

構造函數注入:在類的構造函數中加入依賴參數,並用 [Inject] 標記標記需要注入的參數類型,StrangeIoC 將會在對象被注入時將綁定的類型實例自動注入到它們的對象中。

“`csharp
public class SomeComponent : MonoBehaviour {
private readonly SomeService _someService;

[Inject]
public SomeComponent(SomeService someService) {
_someService = someService;
}
// …
}
“`

3. CrossContext

CrossContext 處理的是跨上下文的依賴關係,在應用程序中設計良好的上下文管理可以大幅度提高應用程序的性能。StrangeIoC 框架為上下文管理提供了很好的支持,當需要處理不同上下文之間的依賴關係時,只需要導入 CrossContext,即可實現上下文間的交互。

二、StrangeIoC 的使用方法

下面我們來看一下 StrangeIoC 的實際使用方法。

1. 安裝

在 Unity 的 Package Manager 中選擇 Add package from git URL 並輸入 git@github.com:strangeioc/strangeioc.git 即可安裝。

2. 綁定類型

在使用 StrangeIoC 進行綁定之前,需要確認以下幾點:

1. 被綁定的類型必須是已經在場景中或預製體中存在的。
2. 綁定是全局的,不同的上下文之間共享綁定關係。
3. 使用構造函數注入時,你需要確保類型的所有依賴都也進行了綁定。

“`csharp
using strange.extensions.context.impl;
using strange.extensions.injector.api;
using UnityEngine;

public class BindToInstanceSample : ContextView
{
private void Awake()
{
var context = new Context(this);
context.injectionBinder.Bind().To();
context.injectionBinder.Bind().To()
.ToSingleton() // ToSingleton 表示單例綁定
.ToName(“Soldier”); // 給綁定關係起個名字
}
}

public class Soldier : ISoldier
{
[Inject] public IWeapon Weapon { get; set; }

public void Attack()
{
Debug.Log($”Using {Weapon.Name} to attack!”);
}
}

public class Knife : IWeapon
{
public string Name => “Knife”;
}
“`

在上面的代碼中,我們將 IWeapon 接口綁定到 Knife 類型上,將 ISoldier 接口綁定到 Soldier 上,並設置了 Soldier 為 Singleton 單例,同時給它起了個名字 Soldier。

3. 注入依賴

在上面的綁定代碼中,使用了屬性注入和構造函數注入兩種方式來注入依賴。

在 PropsInjectionSample 中,我們使用屬性注入方式向 Soldier 對象中注入 IWeapon 對象:

“`csharp
using strange.extensions.context.impl;
using UnityEngine;

public class PropsInjectionSample : ContextView
{
[SerializeField] private Knife knife;

private void Awake()
{
var context = new Context(this);
context.injectionBinder.Bind().To(() => knife).ToSingleton();
context.injectionBinder.Bind().To().ToSingleton();
}
}
“`

在上面的代碼中,將 IWeapon 綁定到 Knife 類型上,並使用 To 方法,將注入對象作為一個函數傳遞,這樣,每次調用 Inject 方法時,將會調用該函數來獲得注入對象。

在 ConstructInjectionSample 類中,我們使用構造函數注入方式向 Soldier 對象中注入 IWeapon 對象:

“`csharp
using strange.extensions.context.impl;
using UnityEngine;

public class ConstructInjectionSample : ContextView
{
[SerializeField] private Knife knife;

private void Awake()
{
var context = new Context(this);
context.injectionBinder.Bind().To(() => knife).ToSingleton();
context.injectionBinder.Bind().To().ToSingleton();
}

private class SoldierWithConstruct : ISoldier
{
private readonly IWeapon _weapon;

public SoldierWithConstruct(IWeapon weapon)
{
_weapon = weapon;
}

public void Attack()
{
Debug.Log($”Using {_weapon.Name} to attack!”);
}
}
}
“`

在上面的代碼中,我們創建了一個新的 SoldierWithConstruct 類,由於 SoldierWithConstruct 存在一個 IWeapon 類型的參數,StrangeIoC 將會使用構造函數注入方式來創建這個對象,並將 IWeapon 對象自動注入進去。

三、StrangeIoC 的高級應用

在正式的應用程序中,你需要更加靈活的控制組件和依賴。下面簡單介紹一下 StrangeIoC 的高級應用。

1. 模塊化開發

由於綁定關係都是全局的,不同模塊之間可能會有命名上的衝突。因此,我們可以使用子綁定器來實現模塊化開發。

“`csharp
using strange.extensions.command.api;
using strange.extensions.command.impl;
using strange.extensions.context.api;
using strange.extensions.context.impl;
using strange.extensions.dispatcher.eventdispatcher.api;
using strange.extensions.dispatcher.eventdispatcher.impl;
using strange.extensions.injector.api;
using strange.extensions.injector.impl;
using UnityEngine;

public class ModuleSample : ContextView
{
public static IInjectionBinder MainBinder;

private void Awake()
{
var context = new Context(this, ContextStartupFlags.MANUAL_LAUNCH);
context.injectionBinder.BinderName = “MainBinder”;
MainBinder = context.injectionBinder;
context.Start();
var subContext = new ModuleContext(this);
subContext.Start();
}

public class CommonBundleInstaller : IInstaller
{
public void Install(IInjectionBinder binder)
{
binder.Bind().To().ToSingleton();
}
}

public class ModuleContext : MVCSContext
{
public ModuleContext(MonoBehaviour view) : base(view, ContextStartupFlags.MANUAL_LAUNCH)
{
}

protected override void mapBindings()
{
injectionBinder.BinderName = “SubBinder”;
injectionBinder.Install(new CommonBundleInstaller());
commandBinder.Bind().To();
}
}

public interface IFoo
{
}

public class Foo : IFoo
{
}

public class SomeEventCommand : EventCommand
{
[Inject] public IFoo Foo { get; set; }

public override void Execute()
{
Debug.Log(“Do something with Foo instance.”);
}
}
}

public class SomeEvent : IEvent
{
}
“`

在上面的例子中,我們定義了一個 CommonBundleInstaller 類,用於安裝一些共享模塊的綁定關係;然後我們定義了一個名為 SubBinder 的 subContext,它是 MVCSContext 的一個派生類,它也有一個自己的綁定器。

2. 自定義命令綁定

在 StrangeIoC 中,命令綁定是用來處理用戶事件的,它們綁定到事件上,並且當事件被觸發時,命令將會被執行。你可以通過自定義命令來擴展 StrangeIoC 的功能。

“`csharp
using strange.extensions.command.impl;
using strange.extensions.context.api;
using strange.extensions.context.impl;
using strange.extensions.dispatcher.eventdispatcher.api;
using strange.extensions.dispatcher.eventdispatcher.impl;
using strange.extensions.injector.api;
using strange.extensions.injector.impl;
using UnityEngine;

public class CustomCommandBindingSample : ContextView
{
private void Awake()
{
var context = new Context(this);
context.commandBinder.Bind().To();
context.dispatcher.Dispatch(new SomeEvent { IntValue = 10 });
}

public class SomeEvent : IEvent
{
public int IntValue { get; set; }
}

public class MultiplyCommand : Command
{
[Inject] public int Multiplier { get; set; } = 3;

public override void Execute()
{
var e = evt.data as SomeEvent;
Debug.Log(e.IntValue * Multiplier);
}
}
}
“`

在上面的例子中,我們定義了一個自定義命令 MultiplyCommand,將 SomeEvent 和 MultiplyCommand 進行綁定綁定。在命令類中,我們可以通過 [Inject] 標記來注入依賴項。由於依賴注入是自動完成的,我們可以在命令類中直接使用注入的對象來進行計算。

3. 自定義綁定提供者

StrangeIoC 默認支持的綁定關係是有限的,例如綁定一個類型到另一個類型需要指定 .To 方法,但是如果你想通過其他的方式來定義綁定關係呢?在 StrangeIoC 中,你可以通過實現 IBindingProvider 接口來自定義綁定關係。

“`csharp
using System;
using strange.extensions.context.impl;
using UnityEngine;

public class CustomBindingProviderSample : ContextView
{
private void Awake()
{
var context = new Context(this);
context.injectionBinder.Unbind();
context.injectionBinder.Bind().ToProvider(new RandomNumberProvider());
var entity = new Entity(context.injectionBinder.GetInstance());
Debug.Log($”Entity instance ID={entity.InstanceId}, value={entity.Value}”);
}

private class Entity
{
public int InstanceId { get; private set; }
public int Value { get; private set; }

public Entity(int value)
{
InstanceId = GetHashCode();
Value = value;
}
}

private class RandomNumberProvider : IBindingProvider
{
public Type GetBindingType()
{
return typeof(int);
}

public object GetBinding(IInjectionBinder binder)
{
return new System.Random().Next(100);
}
}
}
“`

在上面的例子中,我們實現了 IBindingProvider 接口,用於生成隨機數綁定關係。在 Entity 類的構造函數中通過 StrangeIoC 注入的方式注入一個隨機數。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/246903.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 13:18
下一篇 2024-12-12 13:18

相關推薦

  • Ojlat:一款快速開發Web應用程序的框架

    Ojlat是一款用於快速開發Web應用程序的框架。它的主要特點是高效、易用、可擴展且功能齊全。通過Ojlat,開發人員可以輕鬆地構建出高質量的Web應用程序。本文將從多個方面對Oj…

    編程 2025-04-29
  • Zlios——一個多功能的開發框架

    你是否在開發過程中常常遇到同樣的問題,需要不斷去尋找解決方案?你是否想要一個多功能、易於使用的開發框架來解決這些問題?那麼,Zlios就是你需要的框架。 一、簡介 Zlios是一個…

    編程 2025-04-29
  • agavi開發框架

    Agavi是一個基於MVC模式的Web應用程序開發框架,以REST和面向資源的設計為核心思想。本文章將從Agavi的概念、優點、使用方法和實例等方面進行詳細介紹。 一、概念 Aga…

    編程 2025-04-29
  • Python unittest框架用法介紹

    Python unittest框架是Python自帶的一種測試框架,可以用來編寫並運行測試用例。在本文中,我們將從以下幾個方面詳細介紹Python unittest框架的使用方法和…

    編程 2025-04-29
  • com.alipay.sofa.bolt框架

    com.alipay.sofa.bolt框架是一款高性能、輕量級、可擴展的RPC框架。其廣泛被應用於阿里集團內部服務以及阿里雲上的服務。該框架通過NIO支持高並發,同時還內置了多種…

    編程 2025-04-29
  • Python最強大的製圖庫——Matplotlib

    Matplotlib是Python中最強大的數據可視化工具之一,它提供了海量的製圖、繪圖、繪製動畫的功能,通過它可以輕鬆地展示數據的分布、比較和趨勢。下面將從多個方面對Matplo…

    編程 2025-04-29
  • Python range: 強大的迭代器函數

    Python range函數是Python中最常用的內置函數之一。它被廣泛用於for循環的迭代,列表推導式,和其他需要生成一系列數字的應用程序中。在本文中,我們將會詳細介紹Pyth…

    編程 2025-04-29
  • Django框架:從簡介到項目實戰

    本文將從Django的介紹,以及如何搭建Django環境開始,逐步深入到Django模型、視圖、模板、表單,最後通過一個小型項目實戰,進行綜合性的應用,讓讀者獲得更深入的學習。 一…

    編程 2025-04-28
  • LuaEP:一款強大的Lua開發框架

    LuaEP是一個集成了可以快速開發web應用程序所需的組件的Lua開發框架。它以Lua語言為基礎,提供了許多常用接口和庫,使得開發者不需要從頭開始編寫web應用程序,而是專註於業務…

    編程 2025-04-28
  • Java持久層框架的複合主鍵實現

    用Java持久層框架來操作數據庫時,複合主鍵是常見的需求。這篇文章將詳細闡述javax.persistence複合主鍵的實現方式,並提供完整的示例代碼。 一、複合主鍵的定義 複合主…

    編程 2025-04-27

發表回復

登錄後才能評論