【问题标题】:How should I synchronize lists in WCF?我应该如何在 WCF 中同步列表?
【发布时间】:2010-04-25 14:01:16
【问题描述】:

我有一个 WCF 服务,它提供了许多不同类型的项目列表。可以在服务器上更改列表。每个更改都必须发布给所有客户端,以确保每个客户端都拥有每个服务器列表的最新副本。

目前我正在使用这种策略:登录时,每个客户端都会收到每个列表的当前状态。每次更改时,添加或删除的项目都会使用相应的回调方法发送给所有客户端。

缺点是我必须为每个列表创建一个新的回调方法,因为这些项目属于不同的类型并且不能使用单个回调方法发送。有我可以应用的模式吗?还是我真的必须为每个列表复制代码?

编辑:列表可能会经常更改,因此我希望避免在每次更改时发送整个列表。相反,我只是发送更改后的项目。

(编辑 2:次要澄清)

【问题讨论】:

    标签: .net wcf


    【解决方案1】:

    根据您的回答,提供一个接受字符串的方法,该字符串指定客户想要订阅的列表的名称。使用Dictionary<string, List<IWcfCallbackContract>> 管理订阅者列表。

    ListChanged 回调方法应包含三个参数:string listNameChangeType changeType(其中ChangeType 是一个枚举,指定是否添加、删除或更新项目),最后是object changedItem。您还必须使用ServiceKnownTypeAttribute 来指定哪些类型的对象可以出现在changedItem 参数中。

    当列表中的项目发生更改时,从Dictionary<> 对象获取该列表的所有订阅者,并使用 ListChanged 方法通知每个订阅者。客户端应将 changedItemSystem.Object 转换为它期望的任何类型(根据 listName 参数中指定的列表)。

    【讨论】:

    • 我不确定这是否有效,您没有解决实际问题的 WCF 接口。我相信你不能只传输任何对象。
    • 是的,你可以。这就是我提到ServiceKnownTypeAttribute 的原因——它必须知道可以在object 类型中序列化的可能类型是什么,然后才能工作。否则会抛出运行时异常。
    • 确实如此。我认为这个属性是个好主意,实际上为每个列表添加它并不太麻烦。
    • 您甚至可以使用它的ServiceKnownTypeAttribute(String, Type) 重载,它采用返回类型列表的方法名称。我使用该重载,并在该方法中使用反射来查找所有用我自己的自定义属性装饰的类。例如,创建一个SyncedListAttribute 并让您传递给ServiceKnownTypeAttribute 的方法返回程序集中具有您的属性的所有类。这样,当您添加一个新列表时,您所要做的就是使用该属性来装饰它,而不必添加另一个 ServiceKnownTypeAttribute
    【解决方案2】:

    我能想到一个解决方案,但感觉有点奇怪,我也不是很自信。

    服务器为每个列表提供通用订阅方法。列表的名称作为参数传递。在任何列表发生更改时,服务器将更改的列表的名称与更改的项目一起发送。问题是,该项目通常无法传递,因为回调合约只有一个“ListWasChanged”方法(我绝对希望避免为每个列表都有一个新的回调方法,请参阅问题)。

    但是,这可以通过将更改的项目序列化为字符串来解决。通过使用 NetDataContractSerializer,客户端可以轻松地重构序列化项并将其传递给每个列表的正确处理程序。

    你怎么看这个?这可行吗?起初我认为这对性能的影响太大了,但转念一想,无论如何我们都必须对每个项目进行序列化。唯一增加的性能损失是字符串的序列化,它不应该太多。

    由于这可能听起来有点混乱,这里有一个伪代码实现:

    服务器:

    // let's call it SyncList - a list that sends updates on changes
    class SyncList<T> : List<T>
    {
        // this is called on every change of the list
        void OnListChanged<T (string name, T item)
        {
            // serialize the item
            string ser = NetDataContractSerializer.Serialize(item);
            // send the item together with the name of the list
            WcfCallbackChannel.ListChanged (name, ser);
        }
    }
    

    客户:

    // this stores each of the lists
    Dictionary<string, List<T>> _Lists;
    
    // the list callback implementation
    class WcfCallbackImplementation : IWcfCallbackContract
    {
        // called on every change of ANY list
        void ListChanged (string name, string item)
        {
            // get the item back
            var item = NetDataContractSerializer.Deserialize (item);
            // add/remove/update item
            _Lists[name].Add (item);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-15
      • 2013-08-17
      • 1970-01-01
      • 2020-10-04
      • 2022-08-19
      • 1970-01-01
      • 2016-01-21
      • 2016-06-21
      相关资源
      最近更新 更多