Skip to content

Commit cbd8db9

Browse files
committed
增加LifeTimeTrackingInterceptor,从源头防止实例被释放
1 parent d65933c commit cbd8db9

File tree

7 files changed

+79
-80
lines changed

7 files changed

+79
-80
lines changed

WebApiClient/HttpApiFactory.Static.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@ public partial class HttpApiFactory
1919
/// 注册http接口到默认工厂
2020
/// </summary>
2121
/// <typeparam name="TInterface"></typeparam>
22-
/// <exception cref="InvalidOperationException"></exception>
23-
public static void Add<TInterface>() where TInterface : class, IHttpApi
22+
/// <returns></returns>
23+
public static bool Add<TInterface>() where TInterface : class, IHttpApi
2424
{
25-
Add<TInterface>(config: null);
25+
return Add<TInterface>(config: null);
2626
}
2727

2828
/// <summary>
2929
/// 注册http接口到默认工厂
3030
/// </summary>
3131
/// <typeparam name="TInterface"></typeparam>
3232
/// <param name="config">HttpApiConfig的配置</param>
33-
/// <exception cref="InvalidOperationException"></exception>
34-
public static void Add<TInterface>(Action<HttpApiConfig> config) where TInterface : class, IHttpApi
33+
/// <returns></returns>
34+
public static bool Add<TInterface>(Action<HttpApiConfig> config) where TInterface : class, IHttpApi
3535
{
36-
Add<TInterface>(config, handlerFactory: null);
36+
return Add<TInterface>(config, handlerFactory: null);
3737
}
3838

3939
/// <summary>
@@ -42,16 +42,17 @@ public static void Add<TInterface>(Action<HttpApiConfig> config) where TInterfac
4242
/// <typeparam name="TInterface"></typeparam>
4343
/// <param name="config">HttpApiConfig的配置</param>
4444
/// <param name="handlerFactory">HttpMessageHandler创建委托</param>
45-
/// <exception cref="InvalidOperationException"></exception>
46-
public static void Add<TInterface>(Action<HttpApiConfig> config, Func<HttpMessageHandler> handlerFactory) where TInterface : class, IHttpApi
45+
/// <returns></returns>
46+
public static bool Add<TInterface>(Action<HttpApiConfig> config, Func<HttpMessageHandler> handlerFactory) where TInterface : class, IHttpApi
4747
{
48-
Default.AddHttpApi<TInterface>(config, handlerFactory);
48+
return Default.AddHttpApi<TInterface>(config, handlerFactory);
4949
}
5050

5151
/// <summary>
5252
/// 使用默认工厂创建指定接口的代理实例
5353
/// </summary>
5454
/// <typeparam name="TInterface"></typeparam>
55+
/// <exception cref="ArgumentException"></exception>
5556
/// <returns></returns>
5657
public static TInterface Create<TInterface>() where TInterface : class, IHttpApi
5758
{

WebApiClient/HttpApiFactory.cs

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ public partial class HttpApiFactory : IHttpApiFactory, _IHttpApiFactory
2626
/// <summary>
2727
/// 过期的记录
2828
/// </summary>
29-
private readonly ConcurrentQueue<ExpiredHandlerEntry> expiredEntries;
29+
private readonly ConcurrentQueue<ExpiredEntry> expiredEntries;
3030

3131
/// <summary>
3232
/// 激活记录的创建工厂
3333
/// </summary>
34-
private readonly Func<Type, Lazy<ActiveHandlerEntry>> activeEntryFactory;
34+
private readonly Func<Type, Lazy<ActiveEntry>> activeEntryFactory;
3535

3636
/// <summary>
3737
/// http接口代理创建选项
@@ -41,19 +41,18 @@ public partial class HttpApiFactory : IHttpApiFactory, _IHttpApiFactory
4141
/// <summary>
4242
/// 激活的记录
4343
/// </summary>
44-
private readonly ConcurrentDictionary<Type, Lazy<ActiveHandlerEntry>> activeEntries;
45-
44+
private readonly ConcurrentDictionary<Type, Lazy<ActiveEntry>> activeEntries;
4645

4746
/// <summary>
48-
/// 获取已过期但还未释放的HttpMessageHandler数量
47+
/// 获取已过期但还未释放的HttpApi实例数量
4948
/// </summary>
50-
public int ExpiredHandlerCount
49+
public int ExpiredCount
5150
{
5251
get => this.expiredEntries.Count;
5352
}
5453

5554
/// <summary>
56-
/// 获取或设置HttpMessageHandler的生命周期
55+
/// 获取或设置HttpApi实例的生命周期
5756
/// </summary>
5857
/// <exception cref="ArgumentOutOfRangeException"></exception>
5958
public TimeSpan Lifetime
@@ -73,7 +72,7 @@ public TimeSpan Lifetime
7372
}
7473

7574
/// <summary>
76-
/// 获取或设置清理过期的HttpMessageHandler的时间间隔
75+
/// 获取或设置清理过期的HttpApi实例的时间间隔
7776
/// </summary>
7877
/// <exception cref="ArgumentOutOfRangeException"></exception>
7978
public TimeSpan CleanupInterval
@@ -97,10 +96,10 @@ public TimeSpan CleanupInterval
9796
/// </summary>
9897
public HttpApiFactory()
9998
{
100-
this.expiredEntries = new ConcurrentQueue<ExpiredHandlerEntry>();
101-
this.activeEntries = new ConcurrentDictionary<Type, Lazy<ActiveHandlerEntry>>();
99+
this.expiredEntries = new ConcurrentQueue<ExpiredEntry>();
100+
this.activeEntries = new ConcurrentDictionary<Type, Lazy<ActiveEntry>>();
102101
this.httpApiCreateOptions = new ConcurrentDictionary<Type, HttpApiCreateOption>();
103-
this.activeEntryFactory = apiType => new Lazy<ActiveHandlerEntry>(() => this.CreateActiveEntry(apiType), LazyThreadSafetyMode.ExecutionAndPublication);
102+
this.activeEntryFactory = apiType => new Lazy<ActiveEntry>(() => this.CreateActiveEntry(apiType), LazyThreadSafetyMode.ExecutionAndPublication);
104103

105104
this.RegisteCleanup();
106105
}
@@ -111,8 +110,8 @@ public HttpApiFactory()
111110
/// <typeparam name="TInterface"></typeparam>
112111
/// <param name="config">HttpApiConfig的配置</param>
113112
/// <param name="handlerFactory">HttpMessageHandler创建委托</param>
114-
/// <exception cref="InvalidOperationException"></exception>
115-
public void AddHttpApi<TInterface>(Action<HttpApiConfig> config, Func<HttpMessageHandler> handlerFactory) where TInterface : class, IHttpApi
113+
/// <returns></returns>
114+
public bool AddHttpApi<TInterface>(Action<HttpApiConfig> config, Func<HttpMessageHandler> handlerFactory) where TInterface : class, IHttpApi
116115
{
117116
if (handlerFactory == null)
118117
{
@@ -125,62 +124,60 @@ public void AddHttpApi<TInterface>(Action<HttpApiConfig> config, Func<HttpMessag
125124
HandlerFactory = handlerFactory
126125
};
127126

128-
var state = this.httpApiCreateOptions.TryAdd(typeof(TInterface), options);
129-
if (state == false)
130-
{
131-
throw new InvalidOperationException($"接口{typeof(TInterface)}不能重复注册");
132-
}
127+
return this.httpApiCreateOptions.TryAdd(typeof(TInterface), options);
133128
}
134129

135130
/// <summary>
136131
/// 创建指定接口的代理实例
137132
/// </summary>
138133
/// <typeparam name="TInterface"></typeparam>
134+
/// <exception cref="ArgumentException"></exception>
139135
/// <returns></returns>
140136
public TInterface CreateHttpApi<TInterface>() where TInterface : class, IHttpApi
141137
{
142138
var apiType = typeof(TInterface);
143139
var entry = this.activeEntries.GetOrAdd(apiType, this.activeEntryFactory).Value;
144-
return HttpApiClient.Create<TInterface>(entry.HttpApiConfig);
140+
return HttpApiClient.Create(apiType, entry.Interceptor) as TInterface;
145141
}
146142

147143
/// <summary>
148-
/// 创建激活状态的Handler记录
144+
/// 创建激活状态的记录
149145
/// </summary>
150146
/// <param name="apiType">http接口类型</param>
147+
/// <exception cref="ArgumentException"></exception>
151148
/// <returns></returns>
152-
private ActiveHandlerEntry CreateActiveEntry(Type apiType)
149+
private ActiveEntry CreateActiveEntry(Type apiType)
153150
{
154151
if (this.httpApiCreateOptions.TryGetValue(apiType, out var option) == false)
155152
{
156153
throw new ArgumentException($"未注册的接口类型{apiType}");
157154
}
158155

159-
var innder = option.HandlerFactory.Invoke();
160-
var handler = new LifeTimeTrackingHandler(innder);
156+
var handler = option.HandlerFactory.Invoke();
161157
var httpApiConfig = new HttpApiConfig(handler, false);
158+
var interceptor = new LifeTimeTrackingInterceptor(httpApiConfig);
162159

163160
if (option.ConfigAction != null)
164161
{
165162
option.ConfigAction.Invoke(httpApiConfig);
166163
}
167164

168-
return new ActiveHandlerEntry(this)
165+
return new ActiveEntry(this)
169166
{
170167
ApiType = apiType,
171-
Disposable = innder,
172-
HttpApiConfig = httpApiConfig
168+
Disposable = httpApiConfig,
169+
Interceptor = interceptor
173170
};
174171
}
175172

176173
/// <summary>
177174
/// 当有记录失效时
178175
/// </summary>
179176
/// <param name="active">激活的记录</param>
180-
void _IHttpApiFactory.OnEntryDeactivate(ActiveHandlerEntry active)
177+
void _IHttpApiFactory.OnEntryDeactivate(ActiveEntry active)
181178
{
182179
this.activeEntries.TryRemove(active.ApiType, out var _);
183-
var expired = new ExpiredHandlerEntry(active);
180+
var expired = new ExpiredEntry(active);
184181
this.expiredEntries.Enqueue(expired);
185182
}
186183

WebApiClient/Internal/HttpApiFactories/ActiveHandlerEntry.cs renamed to WebApiClient/Internal/HttpApiFactories/ActiveEntry.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,30 @@
44
namespace WebApiClient
55
{
66
/// <summary>
7-
/// 表示激活状态的Handler记录
7+
/// 表示激活状态的记录
88
/// </summary>
9-
class ActiveHandlerEntry
9+
class ActiveEntry
1010
{
1111
/// <summary>
1212
/// 获取或设置关联的http接口类型
1313
/// </summary>
1414
public Type ApiType { get; set; }
1515

1616
/// <summary>
17-
/// 获取或设置http接口配置
17+
/// 获取或设置用于释放资源的对象
1818
/// </summary>
19-
public HttpApiConfig HttpApiConfig { get; set; }
19+
public IDisposable Disposable { get; set; }
2020

2121
/// <summary>
22-
/// 获取或设置用于释放资源的对象
22+
/// 获取或设置http接口拦截器
2323
/// </summary>
24-
public IDisposable Disposable { get; set; }
24+
public LifeTimeTrackingInterceptor Interceptor { get; set; }
2525

2626
/// <summary>
27-
/// 激活状态的Handler记录
27+
/// 激活状态的记录
2828
/// </summary>
2929
/// <param name="factory">httpApiClient工厂</param>
30-
public ActiveHandlerEntry(_IHttpApiFactory factory)
30+
public ActiveEntry(_IHttpApiFactory factory)
3131
{
3232
Task.Delay(factory.Lifetime)
3333
.ConfigureAwait(false)

WebApiClient/Internal/HttpApiFactories/ExpiredHandlerEntry.cs renamed to WebApiClient/Internal/HttpApiFactories/ExpiredEntry.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
namespace WebApiClient
44
{
55
/// <summary>
6-
/// 表示过期状态的Handler记录
6+
/// 表示过期状态的记录
77
/// </summary>
8-
class ExpiredHandlerEntry : IDisposable
8+
class ExpiredEntry : IDisposable
99
{
1010
/// <summary>
1111
/// 用于释放资源的对象
1212
/// </summary>
1313
private readonly IDisposable disposable;
1414

1515
/// <summary>
16-
/// httpApiClient对象的弱引用
16+
/// 监视对象的弱引用
1717
/// </summary>
1818
private readonly WeakReference weakReference;
1919

@@ -27,13 +27,13 @@ public bool CanDispose
2727
}
2828

2929
/// <summary>
30-
/// 过期状态的Handler记录
30+
/// 过期状态的记录
3131
/// </summary>
32-
/// <param name="active">激活状态的Handler记录</param>
33-
public ExpiredHandlerEntry(ActiveHandlerEntry active)
32+
/// <param name="active">激活状态的记录</param>
33+
public ExpiredEntry(ActiveEntry active)
3434
{
3535
this.disposable = active.Disposable;
36-
this.weakReference = new WeakReference(active.HttpApiConfig);
36+
this.weakReference = new WeakReference(active.Interceptor);
3737
}
3838

3939
/// <summary>

WebApiClient/Internal/HttpApiFactories/IHttpApiFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ interface _IHttpApiFactory
1616
/// 当有记录失效时
1717
/// </summary>
1818
/// <param name="entry">激活状态的记录</param>
19-
void OnEntryDeactivate(ActiveHandlerEntry entry);
19+
void OnEntryDeactivate(ActiveEntry entry);
2020
}
2121
}

WebApiClient/Internal/HttpApiFactories/LifeTimeTrackingHandler.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using WebApiClient.Defaults;
3+
4+
namespace WebApiClient
5+
{
6+
/// <summary>
7+
/// 表示具有生命周期自动监视的http接口调用的拦截器
8+
/// </summary>
9+
class LifeTimeTrackingInterceptor : ApiInterceptor
10+
{
11+
/// <summary>
12+
/// http接口调用的拦截器
13+
/// </summary>
14+
/// <param name="httpApiConfig">httpApi配置</param>
15+
/// <exception cref="ArgumentNullException"></exception>
16+
public LifeTimeTrackingInterceptor(HttpApiConfig httpApiConfig)
17+
: base(httpApiConfig)
18+
{
19+
}
20+
21+
/// <summary>
22+
/// 这里不释放资源
23+
/// </summary>
24+
public sealed override void Dispose()
25+
{
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)