连线WCF客户端缓存? [英] Wiring up WCF client side caching?

查看:67
本文介绍了连线WCF客户端缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序使用客户端企业缓存;我想避免为每个可缓存的调用编写代码,并且想知道是否存在一种解决方案,即使对于异步调用,也可以缓存WCF客户端调用。

My application uses client side enterprise caching; I would like to avoid writing code for each and every cacheable call and wondered if there is a solution such that WCF client side calls can be cached, even for async calls.

可以使用WCF行为或其他方法来完成此操作吗?

Can this be done with WCF "behaviour" or some other means? Code examples?

推荐答案

前几天,我在WCF服务客户端(DataServiceClient)上使用通用扩展方法进行了此操作。它使用动作和功能来传递实际的ServiceClient调用。最终的客户端用法语法有点时髦(如果您不喜欢lambdas),但是此方法会执行FaultException / Abort包装和缓存:

I did this the other day with Generic Extension methods on the WCF service client (DataServiceClient). It uses Actions and Funcs to pass around the actual ServiceClient calls. The final client usage syntax is a little funky (if you don't like lambdas), but this method does FaultException/Abort wrapping AND caching:

public static class ProxyWrapper
{
    // start with a void wrapper, no parameters
    public static void Wrap(this DataServiceClient _svc, Action operation)
    {
        bool success = false;

        try
        {
            _svc.Open();
            operation.Invoke();
            _svc.Close();

            success = true;
        }
        finally
        {
            if (!success)
                _svc.Abort();
        }
    }

    // next, a void wrapper with one generic parameter
    public static void Wrap<T>(this DataServiceClient _svc, Action<T> operation, T p1)
    {
        bool success = false;

        try
        {
            _svc.Open();
            operation.Invoke(p1);
            _svc.Close();

            success = true;
        }
        finally
        {
            if (!success)
                _svc.Abort();
        }
    }

    // non-void wrappers also work, but take Func instead of Action
    public static TResult Wrap<T, TResult>(this DataServiceClient _svc, Func<T, TResult> operation, T p1)
    {
        TResult result = default(TResult);

        bool success = false;

        try
        {
            _svc.Open();
            result = operation.Invoke(p1);
            _svc.Close();

            success = true;
        }
        finally
        {
            if (!success)
                _svc.Abort();
        }

        return result;
    }
}

在客户端,我们必须像

    internal static DBUser GetUserData(User u)
    {
        DataServiceClient _svc = new DataServiceClient();

        Func<int, DBUser> fun = (x) => _svc.GetUserById(x);

        return _svc.Wrap<int, DBUser>(fun, u.UserId);
    }

在这里查看计划?现在,我们有了用于WCF调用的通用包装器集,我们可以使用相同的想法注入一些缓存。我在这里是技术含量低的,只是开始为缓存键名乱扔字符串...毫无疑问,您可以做些更优雅的反射操作。

See the plan here? Now that we have a generic set of wrappers for WCF calls, we can use the same idea to inject some cacheing. I went "low tech" here, and just started throwing around strings for the cache key name... You could do something more elegant with reflection, no doubt.

    public static TResult Cache<TResult>(this DataServiceClient _svc, string key, Func<TResult> operation)
    {
        TResult result = (TResult)HttpRuntime.Cache.Get(key);

        if (result != null)
            return result;

        bool success = false;

        try
        {
            _svc.Open();
            result = operation.Invoke();
            _svc.Close();

            success = true;
        }
        finally
        {
            if (!success)
                _svc.Abort();
        }

        HttpRuntime.Cache.Insert(key, result);

        return result;
    }

    // uncaching is just as easy
    public static void Uncache<T>(this DataServiceClient _svc, string key, Action<T> operation, T p1)
    {
        bool success = false;

        try
        {
            _svc.Open();
            operation.Invoke(p1);
            _svc.Close();

            success = true;
        }
        finally
        {
            if (!success)
                _svc.Abort();
        }

        HttpRuntime.Cache.Remove(key);
    }

现在只需在读取内容上调用Cache,在创建/更新/删除操作上取消缓存:

Now just call Cache on your Reads and Uncache on your Create/Update/Deletes:

    // note the parameterless lambda? this was the only tricky part.
    public static IEnumerable<DBUser> GetAllDBUsers()
    {
        DataServiceClient _svc = new DataServiceClient();

        Func<DBUser[]> fun = () => _svc.GetAllUsers();

        return _svc.Cache<DBUser[]>("AllUsers", fun);
    }

我喜欢这种方法,因为我不需要在服务器端重新编码,只是我的WCF代理调用(公认到处散布着一些脆性/气味)。

I like this method because I didn't have to recode anything server-side, just my WCF proxy calls (which were admittedly a little brittle / smelly to have scattered about everywhere).

用您自己的WCF代理约定和标准缓存过程代替,并且你很好。首先也要创建所有通用包装器模板,这也需要大量工作,但是我最多只能使用两个参数,这可以帮助我所有的缓存操作共享一个函数签名(目前)。让我知道这是否适合您或您是否有任何改进。

Substitute in your own WCF proxy conventions and standard caching procedures, and you're good to go. It's a lot of work to create all the generic wrapper templates at first too, but i only went up to two parameters and it helps all my caching operations share a single function signature (for now). Let me know if this works for you or if you have any improvements.

这篇关于连线WCF客户端缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆