Unity——VContainer的依赖注入

一、IOC控制反转和DI依赖倒置

1、IOC框架核心原理是依赖倒置原则

C#设计模式的六大原则

使用这种思想方式,可以让我们无需关心对象的生成方式,只需要告诉容器我需要的对象即可,而告诉容器我需要对象的方式就叫做DI(依赖注入)

 今天主要想研究一下DI(依赖注入),这里我选了VContainer

地址:https://github.com/hadashiA/VContainer

文档地址:https://vcontainer.hadashikick.jp/

 二、VContainer介绍

 由于我们使用的是Unity,而主要的Mono不支持构造函数。所以我们这里选择注入方式主要是特性注入和方法注入

  三、VContainer案例

(1)简单方法注入:

1、注册类型

public class GameLifetimeScope : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        builder.RegisterEntryPoint<ActorPresenter>();
    }
}

2、方法注入

这里实现接口 IStartableITickable。它是不依赖于Mono的接口,因此性能上更好,另一方面,IStartable与Mono的Start,ITickable与Mono的Update都是相同的。

public class ActorPresenter : IStartable,ITickable
{
    public void Start()
    {
        Debug.Log("Start ActorPresenter");
    }

    public void Tick()
    {
        Debug.Log("Update ActorPresenter");
    }
}

(2)基础MVC功能:

Model层

public class UIModel
{
    public void Hello() 
    {
        Debug.Log("Hello World");
    }
}

View层

public class UIView : MonoBehaviour
{
    public Button button;
}

 Control层

public class UIControl : IStartable
{
    readonly UIModel _model;
    readonly UIView _view;

    public UIControl(UIModel model)
    {
        this._model = model;
    }

    public UIControl(UIModel model, UIView view)
    {
        this._model = model;
        this._view = view;
    }

    public void Start()
    {
        _view.button.onClick.AddListener(() => _model.Hello());
    }
}

通过这样做,我们成功地分离了领域控制/控制流/显示组件

在VContainter中,记得注册

public class GameLifetimeScope : LifetimeScope
{
    public UIView helloScreen;
    protected override void Configure(IContainerBuilder builder)
    {
        builder.RegisterEntryPoint<UIControl>();
        builder.Register<UIModel>(Lifetime.Singleton);
        builder.RegisterComponent(helloScreen);
    }
}

(3)构造注入

        构造函数里,只需要写一个需要依赖注入的函数,成员变量里就可以随时获得对象。如下例子ClassB构造函数的参数是ClassA,我们的classA变量就可以随时使用

class ClassB : IStartable,ITickable
{
    readonly ClassA a;
    public ClassB(ClassA a)
    {
        Debug.Log("ClassA构造函数注入");
        this.a = a;
    }

    public void Start()
    {
        a.Start();
    }

    public void Tick()
    {
        a.Update();
    }
}
class ClassA
{
    public ClassA()
    {
        Debug.Log("ClassA构造");
    }

    public void Start()
    {
        Debug.Log("Start");
    }
    public void Update() 
    {
        Debug.Log("Update");
    }
}

public class GameLifetimeScope : LifetimeScope
{
    //public UIView helloScreen;

    protected override void Configure(IContainerBuilder builder)
    {

        builder.RegisterEntryPoint<ClassB>();
        builder.Register<ClassA>(Lifetime.Singleton);
    }
}
(4)方法注入(其他的和上边一样)
class ClassB : IStartable,ITickable
{
    private ClassA a;

    [Inject]
    public void GetClassA(ClassA a) 
    {
        Debug.Log("方法注入");
        this.a = a;
    }

    public void Start()
    {
        a.Start();
    }

    public void Tick()
    {
        a.Update();
    }
}
(5)字段/属性注入
class ClassB : IStartable,ITickable
{
    [Inject]
    private ClassA a;

    public void Start()
    {
        a.Start();
    }

    public void Tick()
    {
        a.Update();
    }
}

3、注册接口

public class GameLifetimeScople : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        //接口
        builder.Register<ILogger, Logger>(Lifetime.Singleton);
        builder.RegisterEntryPoint<LoggerEntryPoint>();
    }
}
interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message)
    {
        Debug.Log(message);
    }
}
public class LoggerEntryPoint : IStartable
{
    [Inject] private ILogger logger;
    public void Start()
    {
        logger.Log("哈哈哈");
    }
}

4、注册工厂

public class GameLifetimeScople : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        //工厂
        builder.RegisterEntryPoint<LoggerEntryPoint>();
        builder.RegisterFactory<ILogger>(() => new Logger());
    }
}
public class Logger : ILogger
{
    public void Log(string message)
    {
        Debug.Log(message);
    }
}
public class LoggerEntryPoint : IStartable
{
    private ILogger logger;
    [Inject]
    public LoggerEntryPoint(Func<ILogger> loggerFactory)
    {
        logger = loggerFactory.Invoke();
    }
    public void Start()
    {
        logger.Log("哈哈哈");
    }
}

带参

public class GameLifetimeScople : LifetimeScope
{
    protected override void Configure(IContainerBuilder builder)
    {
        //工厂
        builder.RegisterEntryPoint<LoggerEntryPoint>();
        builder.RegisterFactory<string, ILogger>((value) => new Logger(value));
    }
}
using VContainer.Unity;
using VContainer;
using UnityEngine;
using System;
public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public Logger(string value)
    {
        Debug.Log($"实例化:{value}");
    }
    public void Log(string message)
    {
        Debug.Log(message);
    }
}
public class LoggerEntryPoint : IStartable
{
    [Inject]
    public LoggerEntryPoint(Func<string, ILogger> loggerFactory)
    {
        loggerFactory.Invoke("第一个对象").Log("哈哈哈");
        loggerFactory.Invoke("第二个对象").Log("啦啦啦");
    }

    public void Start()
    {
        
    }
}

4、RegisterInstance

    protected override void Configure(IContainerBuilder builder)
    {
        builder.RegisterEntryPoint<LoggerEntryPoint>();
        var logger = new Logger();
        builder.RegisterInstance(logger);

    }
public interface ILogger
{
    void Log(string message);
}

public class Logger : ILogger
{
    public void Log(string message)
    {
        Debug.Log(message);
    }
}
public class LoggerEntryPoint : IStartable
{
    public LoggerEntryPoint(Logger logger)
    {
        logger.Log("哈哈哈");        
    }

    public void Start()
    {
        
    }
}

5、RegisterComponent

    private TestMonoBehaviour testMonoBehaviour;

    protected override void Configure(IContainerBuilder builder)
    {
        testMonoBehaviour = GetComponent<TestMonoBehaviour>();
        builder.RegisterEntryPoint<LoggerEntryPoint>();
        builder.RegisterComponent(testMonoBehaviour);
    }
public class LoggerEntryPoint : IStartable
{
    public LoggerEntryPoint(TestMonoBehaviour testMonoBehaviour)
    {
        testMonoBehaviour.Log("11111111");        
    }

    public void Start()
    {
        
    }
}

6、不依赖EntryPoint

   builder.Register<Logger>(Lifetime.Singleton);
        builder.RegisterBuildCallback(objectResolver =>
        {
            objectResolver.Resolve<Logger>();
        });
public class Logger
{
    public Logger()
    {
        Debug.Log("hahhah");
    }
}

如果经常这样使用,可以拓展

public static class ObjectResolverExtensions
{
    public static RegistrationBuilder RegisterPlainEntryPoint<T>(this IContainerBuilder builder, Lifetime lifetime = Lifetime.Singleton)
    {
        builder.RegisterBuildCallback(objectResolver => objectResolver.Resolve<T>());
        return builder.Register<T>(lifetime);
    }
}
 builder.RegisterPlainEntryPoint<Logger>();
public class Logger
{
    public Logger()
    {
        Debug.Log("啦啦啦");
    }
}

如果有此扩展方法,则可以使用一行调用与以前相同的 Register 和 RegisterBuildCallback。builder.RegisterPlainEntryPoint<EntryPointSample>();

7、处理EntryPoint的异常情况

    builder.RegisterEntryPointExceptionHandler(e =>
    {
        Debug.LogException(e);
    });

生命周期:

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值