Skip to content

Commit

Permalink
Merge pull request #99 from CatLib/feature/1.3.0-alpha.2
Browse files Browse the repository at this point in the history
Feature/1.3.0 alpha.2

resolved #95
  • Loading branch information
喵喵大人 authored Dec 5, 2018
2 parents 6c75a79 + 94ab027 commit c4e6974
Show file tree
Hide file tree
Showing 7 changed files with 337 additions and 12 deletions.
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

0 comments on commit c4e6974

Please sign in to comment.