解决 args 变量没有赋值导致的参数传递失败的问题。by Soar360
大石头 编写于 2023-09-09 07:16:48
X
using System;
using System.Collections.Generic;
using System.Linq;
using NewLife.Caching;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using Xunit;

namespace XUnitTest.Model;

public class ObjectContainerTests
{
    [Fact]
    public void Current()
    {
        var ioc = ObjectContainer.Current;
        var provider = ObjectContainer.Provider;

        var ioc2 = provider.GetValue("Container") as IObjectContainer;
        Assert.NotNull(ioc2);

        Assert.Equal(ioc, ioc2);
    }

    [Fact]
    public void Add()
    {
        var ioc = new ObjectContainer();
        ioc.Add(new ServiceDescriptor { ServiceType = typeof(MemoryCache) });
        ioc.TryAdd(new ServiceDescriptor { ServiceType = typeof(MemoryCache) });

        Assert.Equal(1, ioc.Count);

        var services = ioc.GetValue("_list") as IList<IObject>;
        Assert.Equal(1, services.Count);
        Assert.Equal(typeof(MemoryCache), services[0].ServiceType);
        Assert.Null(services[0].ImplementationType);
        Assert.Equal(ObjectLifetime.Singleton, services[0].Lifetime);
    }

    [Fact]
    public void Register()
    {
        var ioc = new ObjectContainer();
        ioc.Register(typeof(MemoryCache), null, null);
        ioc.Register(typeof(ICache), typeof(MemoryCache), null);

        Assert.Equal(2, ioc.Count);
    }

    [Fact]
    public void Resolve()
    {
        var ioc = new ObjectContainer();
        ioc.Register(typeof(MemoryCache), null, null);
        ioc.Register(typeof(ICache), typeof(MemoryCache), null);

        var mc = ioc.Resolve(typeof(MemoryCache));
        Assert.NotNull(mc);

        //var rds = ioc.Resolve(typeof(Redis));
        //Assert.NotNull(rds);
        //var rds2 = ioc.Resolve(typeof(Redis));
        //Assert.NotEqual(rds, rds2);

        var cache = ioc.Resolve(typeof(ICache));
        Assert.NotNull(cache);
    }

    [Fact]
    public void ResolveOrder()
    {
        var services = ObjectContainer.Current;
        services.AddSingleton<ICache, MemoryCache>();
        services.AddSingleton<ICache, MyCache>();

        var provider = services.BuildServiceProvider();
        var cache = provider.GetService<ICache>();
        Assert.Equal(typeof(MyCache), cache.GetType());

        var cs = provider.GetServices<ICache>().ToArray();
        Assert.Equal(2, cs.Length);
        Assert.Equal(typeof(MyCache), cs[0].GetType());
        Assert.Equal(typeof(MemoryCache), cs[1].GetType());
    }

    class MyCache : MemoryCache { }

    [Fact]
    public void AddSingleton()
    {
        var ioc = new ObjectContainer();
        var services = ioc.Services;

        ioc.AddSingleton<ICache, MemoryCache>();
        Assert.Equal(1, ioc.Count);
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        ioc.AddSingleton<ICache>(p => new MemoryCache());
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        Assert.Equal(2, services.Count);
        Assert.Equal(ObjectLifetime.Singleton, services[0].Lifetime);

        var serviceProvider = ioc.BuildServiceProvider();
        var obj = serviceProvider.GetService<ICache>();
        Assert.True(obj is MemoryCache);

        var obj2 = serviceProvider.GetService<ICache>();
        Assert.Equal(obj, obj2);

        var objs = serviceProvider.GetServices<ICache>().ToList();
        Assert.Equal(2, objs.Count);
        Assert.Equal(obj, objs[0]);
        Assert.NotEqual(obj, objs[1]);
        Assert.NotEqual(objs[0], objs[1]);
    }

    [Fact]
    public void AddScoped()
    {
        var ioc = new ObjectContainer();
        var services = ioc.Services;

        ioc.AddScoped<ICache, MemoryCache>();
        Assert.Equal(1, ioc.Count);
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        ioc.AddScoped<ICache>(p => new MemoryCache());
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        Assert.Equal(2, services.Count);
        Assert.Equal(ObjectLifetime.Scoped, services[0].Lifetime);

        var root = ioc.BuildServiceProvider();
        {
            var serviceProvider = root;
            var obj = serviceProvider.GetService<ICache>();
            Assert.True(obj is MemoryCache);

            var obj2 = serviceProvider.GetService<ICache>();
            Assert.NotEqual(obj, obj2);

            var objs = serviceProvider.GetServices<ICache>().ToList();
            Assert.Equal(2, objs.Count);
            Assert.NotEqual(obj, objs[0]);
            Assert.NotEqual(obj, objs[1]);
            Assert.NotEqual(objs[0], objs[1]);
        }

        {
            using var scope = root.CreateScope();
            var serviceProvider = scope.ServiceProvider;
            var obj = serviceProvider.GetService<ICache>();
            Assert.True(obj is MemoryCache);

            var instance = root.GetService<ICache>();
            Assert.NotEqual(obj, instance);

            var obj2 = serviceProvider.GetService<ICache>();
            Assert.Equal(obj, obj2);
            Assert.NotEqual(obj2, instance);

            var objs = serviceProvider.GetServices<ICache>().ToList();
            Assert.Equal(2, objs.Count);
            Assert.NotEqual(obj, objs[0]);
            Assert.NotEqual(obj, objs[1]);
            Assert.NotEqual(objs[0], objs[1]);
        }

        {
            var serviceProvider = root;
            var obj = serviceProvider.GetService<ICache>();
            Assert.True(obj is MemoryCache);

            var obj2 = serviceProvider.GetService<ICache>();
            Assert.NotEqual(obj, obj2);

            var objs = serviceProvider.GetServices<ICache>().ToList();
            Assert.Equal(2, objs.Count);
            Assert.NotEqual(obj, objs[0]);
            Assert.NotEqual(obj, objs[1]);
            Assert.NotEqual(objs[0], objs[1]);
        }
    }

    [Fact]
    public void AddTransient()
    {
        var ioc = new ObjectContainer();
        var services = ioc.Services;

        ioc.AddTransient<ICache, MemoryCache>();
        Assert.Equal(1, ioc.Count);
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        ioc.AddTransient<ICache>(p => new MemoryCache());
        Assert.True(ioc.Resolve<ICache>() is MemoryCache);

        Assert.Equal(2, services.Count);
        Assert.Equal(ObjectLifetime.Transient, services[0].Lifetime);

        var serviceProvider = ioc.BuildServiceProvider();
        var obj = serviceProvider.GetService<ICache>();
        Assert.True(obj is MemoryCache);

        var obj2 = serviceProvider.GetService<ICache>();
        Assert.NotEqual(obj, obj2);

        var objs = serviceProvider.GetServices<ICache>().ToList();
        Assert.Equal(2, objs.Count);
        Assert.NotEqual(obj, objs[0]);
        Assert.NotEqual(obj, objs[1]);
        Assert.NotEqual(objs[0], objs[1]);
    }

    [Fact]
    public void BuildServiceProvider()
    {
        var ioc = new ObjectContainer();

        ioc.AddTransient<ICache, MemoryCache>();

        var provider = ioc.BuildServiceProvider();

        var cache = provider.GetService(typeof(ICache));
        var cache2 = provider.GetService(typeof(ICache));
        Assert.NotNull(cache);
        Assert.NotNull(cache2);
        Assert.NotEqual(cache, cache2);
    }

    [Fact]
    public void TestMutilConstructor()
    {
        {
            var ioc = new ObjectContainer();
            ioc.AddSingleton<ICache, MemoryCache>();
            ioc.AddTransient<MyService>();

            var svc = ioc.Resolve<MyService>();
            Assert.Equal(1, svc.Kind);
        }

        {
            var ioc = new ObjectContainer();
            ioc.AddSingleton<MemoryCache>();
            ioc.AddTransient<MyService>();

            var svc = ioc.Resolve<MyService>();
            Assert.Equal(2, svc.Kind);
        }

        {
            var ioc = new ObjectContainer();
            ioc.AddSingleton<ICache, MemoryCache>();
            ioc.AddTransient<MyService>();

            var svc = ioc.Resolve<MyService>();
            Assert.Equal(1, svc.Kind);
        }

        {
            var ioc = new ObjectContainer();
            ioc.AddSingleton<ICache, MemoryCache>();
            ioc.AddTransient<MyService>();

            var svc = ioc.Resolve<MyService>();
            Assert.Equal(1, svc.Kind);
        }

        {
            var ioc = new ObjectContainer();
            ioc.AddSingleton<ICache, MemoryCache>();
            ioc.AddSingleton<ILog>(XTrace.Log);
            ioc.AddTransient<MyService>();

            var svc = ioc.Resolve<MyService>();
            Assert.Equal(3, svc.Kind);
        }
    }

    private class MyService
    {
        public Int32 Kind { get; set; }

        public MyService() => Kind = 1;

        public MyService(MemoryCache redis) => Kind = 2;

        public MyService(ICache cache, ILog log) => Kind = 3;
    }

    //[Fact]
    //public void AddApiHttpClient()
    //{
    //    var ioc = new ObjectContainer();

    //    var config = new ConfigProvider();
    //    config["orderService"] = "3*http://127.0.0.1:1234,5*http://10.0.0.1:1234";
    //    ioc.AddSingleton<IConfigProvider>(config);
    //    ioc.AddSingleton<IApiClient>(provider => new ApiHttpClient(provider, "orderService"));

    //    var prv = ioc.BuildServiceProvider();

    //    var client = prv.GetService<IApiClient>() as ApiHttpClient;
    //    var ss = client.Services;
    //    Assert.Equal(2, ss.Count);
    //    Assert.Equal(3, ss[0].Weight);
    //    Assert.Equal("http://127.0.0.1:1234/", ss[0].Address + "");
    //    Assert.Equal(5, ss[1].Weight);
    //    Assert.Equal("http://10.0.0.1:1234/", ss[1].Address + "");

    //    // 改变无关配置,不影响对象属性
    //    config["orderRedis"] = "server=10.0.0.1:6379;password=word;db=13";
    //    config.SaveAll();
    //    Assert.Equal(ss, client.Services);

    //    // 改变配置数据,影响对象属性
    //    config["orderService"] = "3*http://127.0.0.1:1234,7*http://192.168.0.1:1234,5*http://10.0.0.1:1234";
    //    config.SaveAll();

    //    Assert.NotEqual(ss, client.Services);
    //    ss = client.Services;
    //    Assert.Equal(3, ss.Count);
    //    Assert.Equal(3, ss[0].Weight);
    //    Assert.Equal("http://127.0.0.1:1234/", ss[0].Address + "");
    //    Assert.Equal(7, ss[1].Weight);
    //    Assert.Equal("http://192.168.0.1:1234/", ss[1].Address + "");
    //    Assert.Equal(5, ss[2].Weight);
    //    Assert.Equal("http://10.0.0.1:1234/", ss[2].Address + "");
    //}
}