Last active
December 18, 2015 20:59
-
-
Save waynebaby/5843843 to your computer and use it in GitHub Desktop.
一个类似Lazy<T>的模式 Link<TId,TTarget> 支持Async. 求Code Review
//不再使用参数Id 这样可以保证不会出现旧id 执行完毕覆盖新Id的状况
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
using AzureChat.Abstractions; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace AzureChat.Common | |
{ | |
/// <summary> | |
/// 一个根据ID取相关资源的类似LazyLoad的模式:Link | |
/// </summary> | |
/// <typeparam name="TId">Id类型</typeparam> | |
/// <typeparam name="TTarget">内容</typeparam> | |
public abstract class LinkBase<TId, TTarget> : ILink<TId, TTarget> | |
{ | |
/// <summary> | |
/// 构造函数 | |
/// </summary> | |
/// <param name="factory">传入Factory</param> | |
public LinkBase(Func<TId, Task<TTarget>> factory) | |
{ | |
_Factory = factory; | |
} | |
/// <summary> | |
/// 由于是否装载,Id与取到的值 往往是对应的,所以用一个struct进行状态维护 | |
/// </summary> | |
protected class LoadedValue | |
{ | |
/// <summary> | |
/// 是否已经Load | |
/// </summary> | |
public bool IsLoaded { get; set; } | |
/// <summary> | |
/// 值 | |
/// </summary> | |
public TTarget Value { get; set; } | |
/// <summary> | |
/// Link的Id | |
/// </summary> | |
public TId Id { get; set; } | |
public override bool Equals(object obj) | |
{ | |
return Id.Equals(((LoadedValue)obj).Id); | |
} | |
public override int GetHashCode() | |
{ | |
return Id.GetHashCode(); | |
} | |
} | |
protected LoadedValue _LoadedValue = new LoadedValue(); | |
/// <summary> | |
/// 定位资源用的工厂 | |
/// </summary> | |
protected Func<TId, Task<TTarget>> _Factory; | |
/// <summary> | |
/// 资源的Id | |
/// </summary> | |
public virtual TId LinkId | |
{ | |
get | |
{ | |
return _LoadedValue.Id; | |
} | |
set | |
{ | |
if (!_LoadedValue.Id.Equals(value)) | |
{ | |
_LoadedValue = new LoadedValue | |
{ | |
Id = value | |
}; | |
} | |
} | |
} | |
/// <summary> | |
/// 异步取得资源 | |
/// </summary> | |
/// <returns>资源内容</returns> | |
public async Task<TTarget> GetItemAsync() | |
{ | |
return (await internalGetValueAsync()).Value; | |
} | |
/// <summary> | |
/// 同步取得资源 | |
/// </summary> | |
/// <returns>资源内容</returns> | |
public TTarget GetItem() | |
{ | |
return (internalGetValue()).Value; | |
} | |
/// <summary> | |
/// 资源是否载入 | |
/// </summary> | |
public bool IsInstanceLoaded | |
{ | |
get { return _LoadedValue.IsLoaded; } | |
} | |
/// <summary> | |
/// 实际同步取得值的逻辑 | |
/// </summary> | |
/// <param name="linkid">资源Id</param> | |
/// <returns>资源值</returns> | |
protected abstract LoadedValue internalGetValue(); | |
/// <summary> | |
/// 实际异步取得值的逻辑 | |
/// </summary> | |
/// <param name="linkid">资源Id</param> | |
/// <returns>资源值</returns> | |
protected abstract Task<LoadedValue> internalGetValueAsync(); | |
/// <summary> | |
/// 清空 | |
/// </summary> | |
public virtual void ClearLoaded() | |
{ | |
_LoadedValue = new LoadedValue() { Id = _LoadedValue.Id }; | |
} | |
public virtual async Task ClearLoadedAsync() | |
{ | |
ClearLoaded(); | |
await Task.Yield(); | |
} | |
} | |
/// <summary> | |
/// 不考虑线程安全的Link | |
/// </summary> | |
/// <typeparam name="TId">资源Id类型</typeparam> | |
/// <typeparam name="TTarget">资源类型</typeparam> | |
public class SimpleLink<TId, TTarget> : LinkBase<TId, TTarget> | |
{ | |
public SimpleLink(Func<TId, Task<TTarget>> factory) | |
: base(factory) | |
{ | |
} | |
protected override LinkBase<TId, TTarget>.LoadedValue internalGetValue() | |
{ | |
return internalGetValueAsync().Result; | |
} | |
protected override async Task<LinkBase<TId, TTarget>.LoadedValue> internalGetValueAsync() | |
{ | |
var tLoaded = _LoadedValue; | |
if (!tLoaded.IsLoaded) | |
{ | |
//简单的调用factory等待值 | |
_LoadedValue = new LoadedValue | |
{ | |
Id = tLoaded.Id, | |
IsLoaded = true, | |
Value = await _Factory(tLoaded.Id).ConfigureAwait(false), | |
}; | |
return _LoadedValue; | |
} | |
else | |
{ | |
return tLoaded; | |
} | |
} | |
} | |
/// <summary> | |
/// 线程安全的Link | |
/// </summary> | |
/// <typeparam name="TId">资源Id类型</typeparam> | |
/// <typeparam name="TTarget">资源内容类型</typeparam> | |
public class SafeLink<TId, TTarget> : SimpleLink<TId, TTarget> | |
{ | |
/// <summary> | |
/// 构造函数 | |
/// </summary> | |
/// <param name="factory">传入Factory</param> | |
public SafeLink(Func<TId, Task<TTarget>> factory) | |
: base(factory) | |
{ | |
} | |
System.Threading.Tasks.ConcurrentExclusiveSchedulerPair rws = new ConcurrentExclusiveSchedulerPair(); | |
protected override LinkBase<TId, TTarget>.LoadedValue internalGetValue() | |
{ | |
return internalGetValueAsync().Result; | |
} | |
protected override async Task<LinkBase<TId, TTarget>.LoadedValue> internalGetValueAsync() | |
{ | |
var nt = Task.Factory.StartNew<Task<LoadedValue>> | |
( | |
base.internalGetValueAsync, | |
CancellationToken.None, | |
TaskCreationOptions.None, | |
rws.ExclusiveScheduler | |
);//所有的Task用互斥的编排器 | |
return await await nt; | |
} | |
public override void ClearLoaded() | |
{ | |
ClearLoadedAsync().Wait(); | |
} | |
public override async Task ClearLoadedAsync() | |
{ | |
var nt = Task.Factory.StartNew<Task> | |
( | |
base.ClearLoadedAsync, | |
CancellationToken.None, | |
TaskCreationOptions.None, | |
rws.ExclusiveScheduler | |
); | |
await await nt; | |
} | |
public override TId LinkId | |
{ | |
get | |
{ | |
return base.LinkId; | |
} | |
set | |
{ | |
var nt = Task.Factory.StartNew | |
( | |
() => base.LinkId = value, | |
CancellationToken.None, | |
TaskCreationOptions.None, | |
rws.ExclusiveScheduler | |
); | |
nt.Wait(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment