Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/CatLib.Core.Tests/CatLib/ApplicationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,111 @@ public void TestRegisterProcessMake()
app.Register(new TestRegisterProcessMakeServiceProvider());
}

public class TestExistedBoostrap : IBootstrap
{
public void Bootstrap()
{

}
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestExistBoostrap()
{
var app = new Application();
var boostrap = new TestExistedBoostrap();
app.Bootstrap(boostrap, boostrap);
}

private static int assertValue = 0;

public class OrderAssertClass : IBootstrap, IServiceProvider
{
private readonly int assert;
public OrderAssertClass(int assert)
{
this.assert = assert;
}

public void Bootstrap()
{
Assert.AreEqual(assert, assertValue++);
}

/// <summary>
/// 服务提供者初始化
/// </summary>
public void Init()
{
Bootstrap();
}

/// <summary>
/// 当注册服务提供者
/// </summary>
public void Register()
{

}
}

public class OrderAssertClassSub : OrderAssertClass
{
public OrderAssertClassSub(int assert)
:base(assert)
{

}
}

[Priority(0)]
public class OrderFirstClass : IBootstrap, IServiceProvider
{
public void Bootstrap()
{
Assert.AreEqual(0, assertValue);
}

/// <summary>
/// 服务提供者初始化
/// </summary>
public void Init()
{
Bootstrap();
}

/// <summary>
/// 当注册服务提供者
/// </summary>
public void Register()
{

}
}

[TestMethod]
public void TestBoostrapOrder()
{
assertValue = 0;
var app = new Application();
app.Bootstrap(new OrderAssertClass(0), new OrderFirstClass(), new OrderAssertClass(1));
Assert.AreEqual(2, assertValue);
}

[TestMethod]
public void TestProviderOrder()
{
assertValue = 0;
var app = new Application();
app.Bootstrap();
app.Register(new OrderAssertClass(0));
app.Register(new OrderFirstClass());
app.Register(new OrderAssertClassSub(1));
app.Init();
Assert.AreEqual(2, assertValue);
}

private Application MakeApplication()
{
var app = new Application();
Expand Down
114 changes: 111 additions & 3 deletions src/CatLib.Core.Tests/Support/Container/GivenDataTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,120 @@ public void CheckGivenIllegalValue()

ExceptionAssert.Throws<ArgumentNullException>(() =>
{
givenData.Given(null);
givenData.Given(string.Empty);
});
ExceptionAssert.Throws<ArgumentNullException>(() =>
}


private class TestGivenClosureClass
{
public string Name { get; set; }
public int Value { get; set; }
public TestGivenClosureClass(string name, int value = 0)
{
givenData.Given(string.Empty);
Name = name;
Value = value;
}
}

[TestMethod]
public void TestGivenClosure()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world")
.Needs<int>().Given(()=> 10);

Assert.AreEqual("hello world", container.Make<TestGivenClosureClass>().Name);
Assert.AreEqual(10, container.Make<TestGivenClosureClass>().Value);
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "ddd");
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue2()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue3()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue4()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
container.Bind<TestGivenClosureClass>().Needs<string>().Given<long>();
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue5()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
container.Bind<TestGivenClosureClass>().Needs<long>().Given<long>();
container.Bind<TestGivenClosureClass>().Needs<string>().Given<long>();
}

[TestMethod]
[ExpectedException(typeof(LogicException))]
public void TestGivenDuplicateValue6()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
container.Bind<TestGivenClosureClass>().Needs<long>().Given(() => "hello world");
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
}

[TestMethod]
[ExpectedException(typeof(AssertException))]
public void TestGivenClosureException()
{
var container = new Container();
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() =>
{
throw new AssertException("hello world");
});

container.Make<TestGivenClosureClass>();
}

private class TestGivenClosureAttrClass
{
[Inject]
public string Name { get; set; }

[Inject]
public int Value { get; set; }
}

[TestMethod]
public void TestGivenAttrClosure()
{
var container = new Container();
container.Bind<TestGivenClosureAttrClass>().Needs<string>().Given(() => "hello world")
.Needs<int>().Given(() => 10);

Assert.AreEqual("hello world", container.Make<TestGivenClosureAttrClass>().Name);
Assert.AreEqual(10, container.Make<TestGivenClosureAttrClass>().Value);
}
}
}
33 changes: 26 additions & 7 deletions src/CatLib.Core/CatLib/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ public enum StartProcess
/// <summary>
/// 服务提供者
/// </summary>
private readonly SortSet<IServiceProvider, int> serviceProviders = new SortSet<IServiceProvider, int>();
private readonly List<KeyValuePair<IServiceProvider, int>> serviceProviders =
new List<KeyValuePair<IServiceProvider, int>>();

/// <summary>
/// 注册服务提供者
Expand Down Expand Up @@ -198,18 +199,31 @@ public virtual void Bootstrap(params IBootstrap[] bootstraps)
Trigger(ApplicationEvents.OnBootstrap, this);
Process = StartProcess.Bootstrapping;

var sorting = new SortSet<IBootstrap, int>();
var sorting = new List<KeyValuePair<IBootstrap, int>>();
var existed = new HashSet<IBootstrap>();

foreach (var bootstrap in bootstraps)
{
if (bootstrap != null)
if (bootstrap == null)
{
sorting.Add(bootstrap, GetPriority(bootstrap.GetType(), nameof(IBootstrap.Bootstrap)));
continue;
}

if (existed.Contains(bootstrap))
{
throw new LogicException($"The bootstrap already exists : {bootstrap}");
}

existed.Add(bootstrap);
sorting.Add(new KeyValuePair<IBootstrap, int>(bootstrap,
GetPriority(bootstrap.GetType(), nameof(IBootstrap.Bootstrap))));
}

foreach (var bootstrap in sorting)
sorting.Sort((left, right) => left.Value.CompareTo(right.Value));

foreach (var kv in sorting)
{
var bootstrap = kv.Key;
var allow = TriggerHalt(ApplicationEvents.Bootstrapping, bootstrap) == null;
if (bootstrap != null && allow)
{
Expand Down Expand Up @@ -250,9 +264,11 @@ protected IEnumerator CoroutineInit()
Trigger(ApplicationEvents.OnInit, this);
Process = StartProcess.Initing;

serviceProviders.Sort((left, right) => left.Value.CompareTo(right.Value));

foreach (var provider in serviceProviders)
{
yield return InitProvider(provider);
yield return InitProvider(provider.Key);
}

inited = true;
Expand Down Expand Up @@ -312,7 +328,10 @@ protected IEnumerator CoroutineRegister(IServiceProvider provider)
{
registering = false;
}
serviceProviders.Add(provider, GetPriority(provider.GetType(), nameof(IServiceProvider.Init)));

serviceProviders.Add(
new KeyValuePair<IServiceProvider, int>(provider,
GetPriority(provider.GetType(), nameof(IServiceProvider.Init))));
serviceProviderTypes.Add(GetProviderBaseType(provider));

if (inited)
Expand Down
47 changes: 46 additions & 1 deletion src/CatLib.Core/Support/Container/Bindable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* Document: http://catlib.io/
*/

using System;
using System.Collections.Generic;

namespace CatLib
Expand All @@ -34,6 +35,12 @@ public abstract class Bindable : IBindable
/// </summary>
private Dictionary<string, string> contextual;

/// <summary>
/// 服务上下文闭包
/// 当前服务需求某个服务时给定的闭包
/// </summary>
private Dictionary<string, Func<object>> contextualClosure;

/// <summary>
/// 同步锁
/// </summary>
Expand Down Expand Up @@ -83,14 +90,38 @@ internal void AddContextual(string needs, string given)
{
contextual = new Dictionary<string, string>();
}
if (contextual.ContainsKey(needs))
if (contextual.ContainsKey(needs)
|| (contextualClosure != null && contextualClosure.ContainsKey(needs)))
{
throw new LogicException($"Needs [{needs}] is already exist.");
}
contextual.Add(needs, given);
}
}

/// <summary>
/// 为服务增加上下文
/// </summary>
/// <param name="needs">需求什么服务</param>
/// <param name="given">给与什么服务</param>
internal void AddContextual(string needs, Func<object> given)
{
lock (SyncRoot)
{
GuardIsDestroy();
if (contextualClosure == null)
{
contextualClosure = new Dictionary<string, Func<object>>();
}
if (contextualClosure.ContainsKey(needs)
|| (contextual != null && contextual.ContainsKey(needs)))
{
throw new LogicException($"Needs [{needs}] is already exist.");
}
contextualClosure.Add(needs, given);
}
}

/// <summary>
/// 获取上下文的需求关系
/// </summary>
Expand All @@ -105,6 +136,20 @@ internal string GetContextual(string needs)
return contextual.TryGetValue(needs, out string contextualNeeds) ? contextualNeeds : needs;
}

/// <summary>
/// 获取上下文关系闭包实现
/// </summary>
/// <param name="needs">需求的服务</param>
/// <returns>给与的闭包</returns>
internal Func<object> GetContextualClosure(string needs)
{
if (contextualClosure == null)
{
return null;
}
return contextualClosure.TryGetValue(needs, out Func<object> closure) ? closure : null;
}

/// <summary>
/// 解除绑定
/// </summary>
Expand Down
Loading