Skip to content

Commit c4e6974

Browse files
author
喵喵大人
authored
Merge pull request #99 from CatLib/feature/1.3.0-alpha.2
Feature/1.3.0 alpha.2 resolved #95
2 parents 6c75a79 + 94ab027 commit c4e6974

File tree

7 files changed

+337
-12
lines changed

7 files changed

+337
-12
lines changed

src/CatLib.Core.Tests/CatLib/ApplicationTests.cs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,111 @@ public void TestRegisterProcessMake()
481481
app.Register(new TestRegisterProcessMakeServiceProvider());
482482
}
483483

484+
public class TestExistedBoostrap : IBootstrap
485+
{
486+
public void Bootstrap()
487+
{
488+
489+
}
490+
}
491+
492+
[TestMethod]
493+
[ExpectedException(typeof(LogicException))]
494+
public void TestExistBoostrap()
495+
{
496+
var app = new Application();
497+
var boostrap = new TestExistedBoostrap();
498+
app.Bootstrap(boostrap, boostrap);
499+
}
500+
501+
private static int assertValue = 0;
502+
503+
public class OrderAssertClass : IBootstrap, IServiceProvider
504+
{
505+
private readonly int assert;
506+
public OrderAssertClass(int assert)
507+
{
508+
this.assert = assert;
509+
}
510+
511+
public void Bootstrap()
512+
{
513+
Assert.AreEqual(assert, assertValue++);
514+
}
515+
516+
/// <summary>
517+
/// 服务提供者初始化
518+
/// </summary>
519+
public void Init()
520+
{
521+
Bootstrap();
522+
}
523+
524+
/// <summary>
525+
/// 当注册服务提供者
526+
/// </summary>
527+
public void Register()
528+
{
529+
530+
}
531+
}
532+
533+
public class OrderAssertClassSub : OrderAssertClass
534+
{
535+
public OrderAssertClassSub(int assert)
536+
:base(assert)
537+
{
538+
539+
}
540+
}
541+
542+
[Priority(0)]
543+
public class OrderFirstClass : IBootstrap, IServiceProvider
544+
{
545+
public void Bootstrap()
546+
{
547+
Assert.AreEqual(0, assertValue);
548+
}
549+
550+
/// <summary>
551+
/// 服务提供者初始化
552+
/// </summary>
553+
public void Init()
554+
{
555+
Bootstrap();
556+
}
557+
558+
/// <summary>
559+
/// 当注册服务提供者
560+
/// </summary>
561+
public void Register()
562+
{
563+
564+
}
565+
}
566+
567+
[TestMethod]
568+
public void TestBoostrapOrder()
569+
{
570+
assertValue = 0;
571+
var app = new Application();
572+
app.Bootstrap(new OrderAssertClass(0), new OrderFirstClass(), new OrderAssertClass(1));
573+
Assert.AreEqual(2, assertValue);
574+
}
575+
576+
[TestMethod]
577+
public void TestProviderOrder()
578+
{
579+
assertValue = 0;
580+
var app = new Application();
581+
app.Bootstrap();
582+
app.Register(new OrderAssertClass(0));
583+
app.Register(new OrderFirstClass());
584+
app.Register(new OrderAssertClassSub(1));
585+
app.Init();
586+
Assert.AreEqual(2, assertValue);
587+
}
588+
484589
private Application MakeApplication()
485590
{
486591
var app = new Application();

src/CatLib.Core.Tests/Support/Container/GivenDataTests.cs

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,120 @@ public void CheckGivenIllegalValue()
5252

5353
ExceptionAssert.Throws<ArgumentNullException>(() =>
5454
{
55-
givenData.Given(null);
55+
givenData.Given(string.Empty);
5656
});
57-
ExceptionAssert.Throws<ArgumentNullException>(() =>
57+
}
58+
59+
60+
private class TestGivenClosureClass
61+
{
62+
public string Name { get; set; }
63+
public int Value { get; set; }
64+
public TestGivenClosureClass(string name, int value = 0)
5865
{
59-
givenData.Given(string.Empty);
66+
Name = name;
67+
Value = value;
68+
}
69+
}
70+
71+
[TestMethod]
72+
public void TestGivenClosure()
73+
{
74+
var container = new Container();
75+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world")
76+
.Needs<int>().Given(()=> 10);
77+
78+
Assert.AreEqual("hello world", container.Make<TestGivenClosureClass>().Name);
79+
Assert.AreEqual(10, container.Make<TestGivenClosureClass>().Value);
80+
}
81+
82+
[TestMethod]
83+
[ExpectedException(typeof(LogicException))]
84+
public void TestGivenDuplicateValue()
85+
{
86+
var container = new Container();
87+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
88+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "ddd");
89+
}
90+
91+
[TestMethod]
92+
[ExpectedException(typeof(LogicException))]
93+
public void TestGivenDuplicateValue2()
94+
{
95+
var container = new Container();
96+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
97+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
98+
}
99+
100+
[TestMethod]
101+
[ExpectedException(typeof(LogicException))]
102+
public void TestGivenDuplicateValue3()
103+
{
104+
var container = new Container();
105+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
106+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
107+
}
108+
109+
[TestMethod]
110+
[ExpectedException(typeof(LogicException))]
111+
public void TestGivenDuplicateValue4()
112+
{
113+
var container = new Container();
114+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
115+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<long>();
116+
}
117+
118+
[TestMethod]
119+
[ExpectedException(typeof(LogicException))]
120+
public void TestGivenDuplicateValue5()
121+
{
122+
var container = new Container();
123+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
124+
container.Bind<TestGivenClosureClass>().Needs<long>().Given<long>();
125+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<long>();
126+
}
127+
128+
[TestMethod]
129+
[ExpectedException(typeof(LogicException))]
130+
public void TestGivenDuplicateValue6()
131+
{
132+
var container = new Container();
133+
container.Bind<TestGivenClosureClass>().Needs<string>().Given<int>();
134+
container.Bind<TestGivenClosureClass>().Needs<long>().Given(() => "hello world");
135+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() => "hello world");
136+
}
137+
138+
[TestMethod]
139+
[ExpectedException(typeof(AssertException))]
140+
public void TestGivenClosureException()
141+
{
142+
var container = new Container();
143+
container.Bind<TestGivenClosureClass>().Needs<string>().Given(() =>
144+
{
145+
throw new AssertException("hello world");
60146
});
147+
148+
container.Make<TestGivenClosureClass>();
149+
}
150+
151+
private class TestGivenClosureAttrClass
152+
{
153+
[Inject]
154+
public string Name { get; set; }
155+
156+
[Inject]
157+
public int Value { get; set; }
158+
}
159+
160+
[TestMethod]
161+
public void TestGivenAttrClosure()
162+
{
163+
var container = new Container();
164+
container.Bind<TestGivenClosureAttrClass>().Needs<string>().Given(() => "hello world")
165+
.Needs<int>().Given(() => 10);
166+
167+
Assert.AreEqual("hello world", container.Make<TestGivenClosureAttrClass>().Name);
168+
Assert.AreEqual(10, container.Make<TestGivenClosureAttrClass>().Value);
61169
}
62170
}
63171
}

src/CatLib.Core/CatLib/Application.cs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ public enum StartProcess
9090
/// <summary>
9191
/// 服务提供者
9292
/// </summary>
93-
private readonly SortSet<IServiceProvider, int> serviceProviders = new SortSet<IServiceProvider, int>();
93+
private readonly List<KeyValuePair<IServiceProvider, int>> serviceProviders =
94+
new List<KeyValuePair<IServiceProvider, int>>();
9495

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

201-
var sorting = new SortSet<IBootstrap, int>();
202+
var sorting = new List<KeyValuePair<IBootstrap, int>>();
203+
var existed = new HashSet<IBootstrap>();
202204

203205
foreach (var bootstrap in bootstraps)
204206
{
205-
if (bootstrap != null)
207+
if (bootstrap == null)
206208
{
207-
sorting.Add(bootstrap, GetPriority(bootstrap.GetType(), nameof(IBootstrap.Bootstrap)));
209+
continue;
208210
}
211+
212+
if (existed.Contains(bootstrap))
213+
{
214+
throw new LogicException($"The bootstrap already exists : {bootstrap}");
215+
}
216+
217+
existed.Add(bootstrap);
218+
sorting.Add(new KeyValuePair<IBootstrap, int>(bootstrap,
219+
GetPriority(bootstrap.GetType(), nameof(IBootstrap.Bootstrap))));
209220
}
210221

211-
foreach (var bootstrap in sorting)
222+
sorting.Sort((left, right) => left.Value.CompareTo(right.Value));
223+
224+
foreach (var kv in sorting)
212225
{
226+
var bootstrap = kv.Key;
213227
var allow = TriggerHalt(ApplicationEvents.Bootstrapping, bootstrap) == null;
214228
if (bootstrap != null && allow)
215229
{
@@ -250,9 +264,11 @@ protected IEnumerator CoroutineInit()
250264
Trigger(ApplicationEvents.OnInit, this);
251265
Process = StartProcess.Initing;
252266

267+
serviceProviders.Sort((left, right) => left.Value.CompareTo(right.Value));
268+
253269
foreach (var provider in serviceProviders)
254270
{
255-
yield return InitProvider(provider);
271+
yield return InitProvider(provider.Key);
256272
}
257273

258274
inited = true;
@@ -312,7 +328,10 @@ protected IEnumerator CoroutineRegister(IServiceProvider provider)
312328
{
313329
registering = false;
314330
}
315-
serviceProviders.Add(provider, GetPriority(provider.GetType(), nameof(IServiceProvider.Init)));
331+
332+
serviceProviders.Add(
333+
new KeyValuePair<IServiceProvider, int>(provider,
334+
GetPriority(provider.GetType(), nameof(IServiceProvider.Init))));
316335
serviceProviderTypes.Add(GetProviderBaseType(provider));
317336

318337
if (inited)

src/CatLib.Core/Support/Container/Bindable.cs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* Document: http://catlib.io/
1010
*/
1111

12+
using System;
1213
using System.Collections.Generic;
1314

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

38+
/// <summary>
39+
/// 服务上下文闭包
40+
/// 当前服务需求某个服务时给定的闭包
41+
/// </summary>
42+
private Dictionary<string, Func<object>> contextualClosure;
43+
3744
/// <summary>
3845
/// 同步锁
3946
/// </summary>
@@ -83,14 +90,38 @@ internal void AddContextual(string needs, string given)
8390
{
8491
contextual = new Dictionary<string, string>();
8592
}
86-
if (contextual.ContainsKey(needs))
93+
if (contextual.ContainsKey(needs)
94+
|| (contextualClosure != null && contextualClosure.ContainsKey(needs)))
8795
{
8896
throw new LogicException($"Needs [{needs}] is already exist.");
8997
}
9098
contextual.Add(needs, given);
9199
}
92100
}
93101

102+
/// <summary>
103+
/// 为服务增加上下文
104+
/// </summary>
105+
/// <param name="needs">需求什么服务</param>
106+
/// <param name="given">给与什么服务</param>
107+
internal void AddContextual(string needs, Func<object> given)
108+
{
109+
lock (SyncRoot)
110+
{
111+
GuardIsDestroy();
112+
if (contextualClosure == null)
113+
{
114+
contextualClosure = new Dictionary<string, Func<object>>();
115+
}
116+
if (contextualClosure.ContainsKey(needs)
117+
|| (contextual != null && contextual.ContainsKey(needs)))
118+
{
119+
throw new LogicException($"Needs [{needs}] is already exist.");
120+
}
121+
contextualClosure.Add(needs, given);
122+
}
123+
}
124+
94125
/// <summary>
95126
/// 获取上下文的需求关系
96127
/// </summary>
@@ -105,6 +136,20 @@ internal string GetContextual(string needs)
105136
return contextual.TryGetValue(needs, out string contextualNeeds) ? contextualNeeds : needs;
106137
}
107138

139+
/// <summary>
140+
/// 获取上下文关系闭包实现
141+
/// </summary>
142+
/// <param name="needs">需求的服务</param>
143+
/// <returns>给与的闭包</returns>
144+
internal Func<object> GetContextualClosure(string needs)
145+
{
146+
if (contextualClosure == null)
147+
{
148+
return null;
149+
}
150+
return contextualClosure.TryGetValue(needs, out Func<object> closure) ? closure : null;
151+
}
152+
108153
/// <summary>
109154
/// 解除绑定
110155
/// </summary>

0 commit comments

Comments
 (0)