-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
826c012
commit 67035a1
Showing
6 changed files
with
312 additions
and
160 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
VSProj~ | ||
.github | ||
.github | ||
README.md | ||
Documentation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# 装饰器 | ||
|
||
值得一提的是,装饰器的实现有以下优势: | ||
|
||
* 调用是0GC,低开销的 | ||
* 实现只需要指定一个`DecoratorAttribute` | ||
* 支持装饰异步函数 | ||
|
||
## 例子 | ||
|
||
下面的例子实现目标方法执行前和后打印信息 | ||
|
||
定义一个装饰器,需要继承自`DecoratorAttribute`,并实现`Decorate`方法 | ||
|
||
```csharp | ||
public class DebugInvocationAttribute:DecoratorAttribute | ||
{ | ||
string info; | ||
|
||
public DebugInvocationAttribute(string _info) | ||
{ | ||
info = _info; | ||
} | ||
|
||
void OnCompleted() | ||
{ | ||
Debug.Log("end "+info); | ||
} | ||
|
||
protected override R Decorate<R>(InvocationInfo<R> invocation) | ||
{ | ||
Debug.Log("begin "+info+string.Join(",",invocation.Arguments)); | ||
// invoke original method | ||
var r = invocation.FastInvoke(); | ||
if(IsAsyncMethod) | ||
{ | ||
// delay on async method | ||
invocation.GetAwaiter(r).OnCompleted(OnCompleted); | ||
} | ||
else | ||
{ | ||
OnCompleted(); | ||
} | ||
return r; | ||
} | ||
} | ||
|
||
``` | ||
|
||
使用 | ||
|
||
```csharp | ||
|
||
public class Demo:MonoBehaviour{ | ||
|
||
void Start(){ | ||
FixHelper.InstallAll(); | ||
} | ||
|
||
async void Update(){ | ||
if(Input.GetKeyDown(KeyCode.A)){ | ||
Work(1,"foo"); | ||
} | ||
if(Input.GetKeyDown(KeyCode.S)){ | ||
await AsyncWork(2,"bar"); | ||
print("return"); | ||
} | ||
} | ||
|
||
//decorate a standard method | ||
[DebugInvocation("w1")] | ||
int Work(int i, string s){ | ||
Debug.Log("do work"); | ||
return 123+i; | ||
} | ||
|
||
//decorate an async method | ||
[DebugInvocation("aw2")] | ||
async Task<int> AsyncWork(int i, string s){ | ||
Debug.Log("do a lot work"); | ||
await Task.Delay(1000); | ||
return 123+i; | ||
} | ||
} | ||
``` | ||
|
||
## 异步方法补充说明 | ||
|
||
async方法有一个值得斟酌的问题。如果上例的Task换成UniTask。则不会打印return,这是因为Decrote方法覆盖了原本的continuationAction(这与UniTask的实现有关)。使用如下Decorate方法可以解决所有此类问题: | ||
|
||
```csharp | ||
protected override R Decorate<R>(InvocationInfo<R> invocation) | ||
{ | ||
Debug.Log("begin "+info+string.Join(",",invocation.Arguments)); | ||
var r = invocation.FastInvoke(); | ||
if(IsAsyncMethod) | ||
{ | ||
// delay when its an async method | ||
var awaiter = invocation.GetAwaiter(r); | ||
UniTask.Create(async()=> | ||
{ | ||
try | ||
{ | ||
while(!invocation.IsAwaiterCompleted(awaiter)) | ||
await UniTask.Yield(); | ||
} | ||
catch {} | ||
finally | ||
{ | ||
OnCompleted(); | ||
} | ||
}); | ||
// invocation.GetAwaiter(r).OnCompleted(OnCompleted); | ||
} | ||
else | ||
{ | ||
OnCompleted(); | ||
} | ||
return r; | ||
} | ||
``` | ||
|
||
上例使用`UniTask.Create`创建了一个Timer,可以使用其他类似的方法,如自定义MonoBehaviour等。一旦`IsAwaiterCompleted`检查结束,立即执行自定义的`OnCompleted`方法。 | ||
|
||
因为Unity没有官方支持的Timer功能,基于“此库只做自己该做的”原则,这里只是给出提示。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
# 依赖注入 | ||
|
||
依赖注入对于模块间解耦帮助很大。 | ||
|
||
## 基本用法 | ||
|
||
在类成员上使用`[SimpleDI]`标签,使其可被注入。 | ||
|
||
```csharp | ||
public interface IFoo | ||
{ | ||
|
||
} | ||
|
||
public class FooA : IFoo | ||
{ | ||
|
||
} | ||
|
||
public class FooB : IFoo | ||
{ | ||
|
||
} | ||
|
||
public class ServiceA | ||
{ | ||
[SimpleDI] public IFoo foo {get;} | ||
} | ||
|
||
``` | ||
|
||
定义规则: | ||
|
||
```csharp | ||
void Start() | ||
{ | ||
// 使用FooA实现IFoo | ||
ServiceContainer.Bind<IFoo>().AsSingle(noLazy:true).To<FooA>(); | ||
} | ||
|
||
``` | ||
|
||
## 支持注入的成员 | ||
|
||
支持以下成员: | ||
|
||
+ 字段、属性 | ||
+ 静态成员、实例成员 | ||
+ 只读成员、可读可写成员 | ||
|
||
如: | ||
|
||
```csharp | ||
class Foo | ||
{ | ||
[SimpleDI] static IFoo foo; | ||
[SimpleDI] static IFoo foo { get; } | ||
[SimpleDI] static IFoo foo { get; set; } | ||
[SimpleDI] IFoo foo; | ||
[SimpleDI] IFoo foo { get; } | ||
[SimpleDI] IFoo foo { get; set; } | ||
} | ||
|
||
``` | ||
|
||
## 更多控制 | ||
|
||
### 限定DeclaringType | ||
|
||
```csharp | ||
void Init() | ||
{ | ||
// 使用FooA实现IFoo,只对ServiceA中的成员生效 | ||
ServiceContainer.In<ServiceA>().Bind<IFoo>().AsSingle(noLazy:true).To<FooA>(); | ||
} | ||
|
||
``` | ||
|
||
### 构造函数 | ||
|
||
```csharp | ||
interface IFoo { } | ||
class Foo : IFoo | ||
{ | ||
public Foo(string name, int age) | ||
{ | ||
Console.WriteLine($"我的伙伴{name},{age}岁了"); | ||
} | ||
} | ||
|
||
void Init() | ||
{ | ||
// output: 我的伙伴小黑儿,3岁了 | ||
ServiceContainer.Bind<IFoo>().AsSingle(noLazy:true).To<Foo>("小黑儿",3); | ||
} | ||
|
||
``` | ||
|
||
### 生命模式 ScopeMode | ||
|
||
+ Single 单例(默认) | ||
+ Transient 每次获取都是新实例 | ||
|
||
```csharp | ||
// 使用FooA实现IFoo | ||
ServiceContainer.Bind<IManager>().AsSingle().To<FooManager>(); | ||
ServiceContainer.Bind<IFoo>().AsTransient().To<Foo>(); | ||
``` | ||
|
||
### 泛型递归 | ||
|
||
对于`IManager<IFoo,IBar>`会分别查找IManager,IFoo,IBar,并支持泛型约束。 | ||
|
||
```csharp | ||
interface IFoo | ||
{ | ||
|
||
} | ||
|
||
interface IManager | ||
{ | ||
|
||
} | ||
|
||
class Foo : IFoo | ||
{ | ||
|
||
} | ||
|
||
class Manager : IManager | ||
{ | ||
|
||
} | ||
|
||
``` | ||
|
||
```csharp | ||
void Init() | ||
{ | ||
ServiceContainer.Get<IManager<IFoo>>(); // returns Manager<Foo> | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# 数据代理 | ||
|
||
下面的代码演示实现一个数据代理: | ||
|
||
```csharp | ||
public class Pat : ProxyData // 需要继承ProxyData | ||
{ | ||
public string name { get; set; } | ||
public int age { get; set; } | ||
} | ||
|
||
var pet = new Pet(); | ||
pet.OnSetProperty(key=>{ | ||
print($"set {key}"); | ||
}); | ||
pet.OnGetProperty(key=>{ | ||
print($"get {key}"); | ||
}); | ||
|
||
pet.age += 1; | ||
|
||
/* | ||
output: | ||
get age | ||
set age | ||
*/ | ||
|
||
``` | ||
|
||
有时你需要判断代理类是否被正确注入: | ||
|
||
```csharp | ||
print(pet.IsFixed()); // false | ||
FixHelper.InstallAll(); | ||
print(pet.IsFixed()); // true | ||
``` |
Oops, something went wrong.