【问题标题】:rich client data handling and caching patterns富客户端数据处理和缓存模式
【发布时间】:2012-12-02 08:37:38
【问题描述】:

我正在使用 WPF-PRISM-MVVM 开发一个富客户端应用程序。
客户端与提供 CRUD 功能的存储库服务交互,并通过 WCF 通道发布域实体的任何更改。
客户端处理域实体缓存以提高性能并提供离线功能。
为此,我编写了一个存储库代理服务,它位于客户端并包装存储库服务并处理缓存和更改传播到对域实体更改感兴趣的相关客户端组件。

经过长时间的介绍,我的问题是这样做的方法吗?
是否有任何我应该注意的客户端数据处理和缓存模式?

干杯,
多伦

【问题讨论】:

    标签: design-patterns caching mvvm prism


    【解决方案1】:

    我们以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();
        }
    }
    

    【讨论】:

      【解决方案2】:

      Decorator Pattern 的一个相当经典的应用是添加缓存功能。您基本上将实际的组件实现与另一个缓存特定类型的请求的组件实现包装起来,从而提高性能。这是 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();
      

      【讨论】:

      • 谢谢!这是我目前使用的策略。我正在寻找是否有其他选择。
      猜你喜欢
      • 1970-01-01
      • 2010-10-04
      • 2013-01-04
      • 1970-01-01
      • 2023-04-09
      • 2015-09-14
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      相关资源
      最近更新 更多