我正在使用 WPF-PRISM-MVVM 开发一个富客户端应用程序。
客户端与提供 CRUD 功能的存储库服务交互,并通过 WCF 通道发布域实体的任何更改。
客户端处理域实体缓存以提高性能并提供离线功能。
为此,我编写了一个存储库代理服务,它位于客户端并包装存储库服务并处理缓存和更改传播到对域实体更改感兴趣的相关客户端组件。
经过长时间的介绍,我的问题是这样做的吗?
是否有任何我应该注意的客户端数据处理和缓存模式?
干杯,
多伦
我正在使用 WPF-PRISM-MVVM 开发一个富客户端应用程序。
客户端与提供 CRUD 功能的存储库服务交互,并通过 WCF 通道发布域实体的任何更改。
客户端处理域实体缓存以提高性能并提供离线功能。
为此,我编写了一个存储库代理服务,它位于客户端并包装存储库服务并处理缓存和更改传播到对域实体更改感兴趣的相关客户端组件。
经过长时间的介绍,我的问题是这样做的吗?
是否有任何我应该注意的客户端数据处理和缓存模式?
干杯,
多伦
我们使用PostSharp形式的AOP进行客户端缓存,我们只需向方法添加一个属性,然后中提琴它就被缓存了:
我们的方面看起来像这样——它将实际的缓存实现推迟到一个实例,ICacheService
但你明白了。
[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, PersistMetaData = true)]
public class MethodCacheAttribute : MethodInterceptionAspect
{
public const int DefaultCacheSeconds = 600;
private ICacheService CacheService { get; set; }
private string methodName;
[IntroduceMember(Visibility = PostSharp.Reflection.Visibility.Family, OverrideAction = MemberOverrideAction.Ignore, IsVirtual = true)]
public double CacheForSeconds { get; set; }
public MethodCacheAttribute() : this(DefaultCacheSeconds ) { }
public MethodCacheAttribute(int seconds)
{
this.CacheForSeconds = seconds;
}
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
this.methodName = method.Name;
}
public sealed override void OnInvoke(MethodInterceptionArgs args)
{
var key = this.BuildCacheKey(args.Arguments,args.Method);
var item = ServiceLocator.Current.GetInstance<ICacheService>().Cache<object>(key, () =>
{
return args.Invoke(args.Arguments);
},CacheForSeconds ==0 ? TimeSpan.MaxValue : TimeSpan.FromSeconds(CacheForSeconds));
args.ReturnValue = item;
}
private string BuildCacheKey(Arguments arguments, MethodBase method)
{
var sb = new StringBuilder();
sb.Append(this.methodName);
foreach (var argument in arguments.ToArray())
{
sb.Append(argument == null ? "_" : argument.GetHashCode().ToString());
}
if (method.IsGenericMethod)
{
var genericArgs = String.Join("-", method.GetGenericArguments().Select(t => t.Name));
sb.Append(genericArgs);
}
return sb.ToString();
}
}
装饰器模式的一个相当经典的应用是添加缓存功能。您基本上将实际组件实现与另一个缓存某些类型的请求的组件实现包装,从而提高性能。这是 IMO 一种简单且非常优雅的方法。
Component myComponent = new ScientificCalculator();
Component myDecorator = new ComponentDecorator(myComponent);
// expensive
double result = myComponent.doExpensiveComputation();
// use the Decorator and cache the first time
result = myDecorator.doExpensiveComputation();
// and now is cheap
result = myDecorator.doExpensiveComputation();