If you have been playing with Peer Channel, you probably noticed that there is a programmability element called PeerNode. In this blog post, I would like to briefly discuss one of the properties on this object called - "MessagePropagationFilter". you can use this filter to affect the message flow inside a Peer Channel mesh.

There is a single abstract method in the abstract class System.ServiceModel.PeerMessagePropagationFilter:

public abstract PeerMessagePropagation ShouldPropagateMessage(Message message, PeerMessageOrigination origination);

to participate in the message flow, you simply create a concrete derived class of PeerMessagePropagationFilter and attach it to the peernode.

Make sure you attach your propagation filter before opening the peer channel.

For evey message that passes through your peernode (basically, the transport manager created under the covers to support your peer channel instance), this filter is invoked to make propagation decisions. This is true for messages that originated elsewhere in the mesh and your node has received as well as messages created by your application. the last argument to the method call identifies the origin (PeerMessageOrigination.Local or PeerMessageOrigination.Remote). For each message, your filter can decide if the message should be delivered only locally, meaning to other endpoints in your application, onto the mesh only, both or simply drop the message. You can do this, by returning one of the intuitively named constants in the PeerMessagePropagation enum: None, Local, Remote, LocalAndRemote.

A full copy of the message is passed to this method, any changes you make to the message, do not affect the actual message.

just for fun, here is a sample implementation that only delivers remote messages to your application (filters out locally generated messages).

class  RemoteOnlyMessagePropagationFilter : PeerMessagePropagationFilter

{

public RemoteOnlyMessagePropagationFilter()

{

}

public override PeerMessagePropagation ShouldPropagateMessage(Message message, PeerMessageOrigination origination)

{

PeerMessagePropagation destination = PeerMessagePropagation.LocalAndRemote;

    if(origination == PeerMessageOrigination.Local)

       destination = PeerMessagePropagation.Remote;

    return destination;

}

}

 

here is the code snippet to attach an instance of the filter class to your peer node:

      

ChannelFactory<IDoNothing> channelFactory = new ChannelFactory<IDoNothing>(...);

IDoNothing doer = channelFactory.CreateChannel();

RemoteOnlyMessagePropagationFilter myPropagationFilter = new RemoteOnlyMessagePropagationFilter();

PeerNode myPeerNode = ((IClientChannel)doer).GetProperty<PeerNode>(); 

myPeerNode.MessagePropagationFilter = myPropagationFilter;

doer.Open();

make sure to attach the filter before you open the channel.

This technique can be useful if you do not want to receive messages that your application has generated - can happen if you have an output channel and a service endpoint both opened at the same endpoint address. Or, if you opened a duplex channel - Peer Channel's duplex channel instances reflect the message back to your instance context.

as you can see this is a very simple example. you are not gauranteed that the filter invokaction by the node is serialized. Multiple threads may call into your filter at the same time - unless you opened your peer channel instance on a UI thread.