using System;
using System.Messaging;
using System.ServiceModel;
using System.ServiceModel.MsmqIntegration;
namespace BelgianAgencies.Wcf
{
public class WcfMsmqFactory<I>
{
private string _queueAddress;
private string _netmsmqAddress;
public WcfMsmqFactory(string queueName)
{
_queueAddress = String.Format(@".\private$\{0}", queueName);
_netmsmqAddress = String.Format(@"msmq.formatname:DIRECT=OS:{0}", _queueAddress);
if (!MessageQueue.Exists(_queueAddress))
MessageQueue.Create(_queueAddress, true);
}
public bool UseCustomDeadLetterQueue
{
get;
set;
}
/// <summary>
/// Is the queue on a device connected to active directory.
/// Standard = false.
/// </summary>
/// <value><c>true</c> if [in active directory]; otherwise, <c>false</c>.</value>
public bool InActiveDirectory
{
get; set;
}
public ServiceHost CreateService<T>(string namespaceName)
{
var sHost = new ServiceHost(typeof(T));
MsmqIntegrationBinding binding;
binding = InActiveDirectory ? new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.Transport) : new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None);
// Retry at most 5 times
binding.ReceiveRetryCount = 1;
// Max amount of retries before cancel message
// (1 + MaxRetryCycles) * (ReceiveRetryCount + 1) = total amount of retries
binding.MaxRetryCycles = 3;
// time before timout when unable to get message out of the queue
binding.ReceiveTimeout = new TimeSpan(0, 0, 5);
// when unable to dequeue put message on dead letter queue
//TODO: set to reject on msmq 4.0
binding.ReceiveErrorHandling = ReceiveErrorHandling.Fault;
// this message is not volatile, when hard reboot message will not get lost
binding.Durable = true;
// timout when opening connection
binding.OpenTimeout = new TimeSpan(0, 0, 5);
// timout when closing connection
binding.CloseTimeout = new TimeSpan(0, 0, 5);
binding.Namespace = namespaceName;
sHost.AddServiceEndpoint(
typeof(I),
binding,
new Uri(_netmsmqAddress)
);
return sHost;
}
public I CreateChannel()
{
var binding = new MsmqIntegrationBinding(MsmqIntegrationSecurityMode.None);
var address = new EndpointAddress(String.Format("msmq.formatname:DIRECT=OS:{0}", _queueAddress));
var channelFactory = new ChannelFactory<I>(binding, address);
return channelFactory.CreateChannel();
}
}
}