如何在C#项目中(特别是Unity游戏)模仿springboot编写IoC依赖注入容器

这两天我用Unity写游戏,特别需要一个IoC(控制反转)容器来简化我的代码逻辑,达到业务之间解耦的效果。

我尝试了许多包括.NET自带的依赖注入(DI)容器,但使用起来都不太符合我的代码习惯。

比如说,如果我有接口类IMyService和实现类MyService,想要通过.NET的IoC依赖注入容器,我就得写一个这样的配置类来绑定服务和接口:

public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IMyService, MyService>();
}

这样写是不是很蠢?如果你写过Springboot,你应该知道,这种情况下在实现类类名上方打一个@Service注解就可以解决问题了。

说巧不巧,C#也有一个叫特性的东西,跟Java的注解几乎是一码事。因此我决定自行编写IoC容器,对Springboot进行拙劣但不失乐趣的模仿。


我们先针对非Unity游戏进行操作。

我创建了一个解决方案,在解决方案下方建立了一个控制台项目ConsoleApp1和一个类库项目EasyInject,分别用来进行依赖注入测试和编写IoC容器。

在EasyInject/Attributes下,我建立了两个特性类,分别叫AutowiredAttribute和ComponentAttribute,前者用于打在成员变量字段前进行字段注入,后者用于标记这个类应该被视作类似于Bean的东西记录在IoC容器当中。代码如下:

namespace EasyInject.Attributes;

[AttributeUsage(AttributeTargets.Field)]
public class AutowiredAttribute : Attribute
{
}
namespace EasyInject.Attributes;

[AttributeUsage(AttributeTargets.Class)]
public class ComponentAttribute : Attribute
{
}

现在我们就可以编写IoC容器了。

先把代码放上来,然后我们一行行讲我的思路:

using System.Reflection;
using EasyInject.Attributes;

namespace EasyInject;

public class MyIoC
{
    private readonly Dictionary<Type, object> _services = new();
    
    public MyIoC()
    {
        // 扫描所有程序集中打了Component特性的类
        var types = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(a => a.GetTypes())
            .Where(t => t.GetCustomAttributes(typeof(ComponentAttribute), true).Length > 0).ToList();
        
        // 先进行实例化(包括构造函数的依赖注入)
        while (types.Count > 0)
        {
            for (var i = 0; i < types.Count; i++)
            {
                var type = types[i];
                // 获取构造函数
                var constructors = type.GetConstructors();
                // 实例
                object? instance = null;

                // 遍历构造函数,找到可以实例化的构造函数
                foreach (var constructor in constructors)
                {
                    // 获取构造函数的参数
                    var parameters = constructor.GetParameters();
                    // 构造函数的参数实例
                    var parameterInstances = new object[parameters.Length];

                    for (var j = 0; j < parameters.Length; j++)
                    {
                        var parameterType = parameters[j].Parameter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值