/// <summary>
        /// Receives from queue.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="targetModel">The target model.</param>
        /// <param name="handler">The handler.</param>
        /// <returns></returns>
        public bool ReceiveFromQueue <T>(T targetModel, Func <T, Task> handler)
        {
            try
            {
                ServiceBusDetails serviceBusDetails = GetServiceBusDetailsFromT(targetModel.GetType());

                if (!string.IsNullOrEmpty(serviceBusDetails.Connection))
                {
                    receiverClient = new AzureQueueReceiver(serviceBusDetails.Connection, serviceBusDetails.QueueName);
                    MessageHandlerOptions messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
                    {
                        MaxConcurrentCalls = 50,
                        AutoComplete       = true
                    };

                    //subscriptionClient.RegisterMessageHandler(handler, messageHandlerOptions);
                    receiverClient.RegisterMessageHandler(async(msg, token) =>
                    {
                        // Get message
                        string message      = Encoding.UTF8.GetString(msg.Body).ToBase64Decode();
                        dynamic obj         = JsonConvert.DeserializeObject(message);
                        dynamic retrunModel = JsonConvert.DeserializeObject <T>(JsonConvert.SerializeObject(obj.originalvalue));
                        handler(retrunModel);
                    }, messageHandlerOptions);

                    return(true);
                }

                return(false);
            }
            catch (Exception)
            {
                return(false);
            }
        }
        /// <summary>
        /// Setups the azure topic provider.
        /// </summary>
        /// <param name="domainManager">The domain manager.</param>
        static void SetupAzureTopicProvider(DomainManager domainManager)
        {
            if (domainManager != null && domainManager.DomainConfiguration != null)
            {
                foreach (Type data in domainManager.DomainConfiguration)
                {
                    ServiceBusDetails serviceBusDetails = GetServiceBusDetailsFromT(data);
                    if (!string.IsNullOrEmpty(serviceBusDetails.Connection))
                    {
                        if (!string.IsNullOrWhiteSpace(serviceBusDetails.TopicName))
                        {
                            ////Add topic client to _topicManager which will be used for publish
                            string topicKeyName = $"{serviceBusDetails.Endpoint}||{serviceBusDetails.TopicName}";
                            if (!_topicManager.ContainsKey(topicKeyName))
                            {
                                ////Check for topic and if not exists AzureTopicProvider will create it.
                                AzureTopicProvider azureTopicProvider = new AzureTopicProvider(serviceBusDetails.Connection, serviceBusDetails.TopicName, serviceBusDetails.Subscription);
                                azureTopicProvider.AddTopic();

                                AzureTopicPublisher topicClient = new AzureTopicPublisher(serviceBusDetails.Connection, serviceBusDetails.TopicName);
                                _topicManager.TryAdd(topicKeyName, topicClient);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Setups the azure queue provider.
        /// </summary>
        /// <param name="domainManager">The domain manager.</param>
        static void SetupAzureQueueProvider(DomainManager domainManager)
        {
            if (domainManager != null && domainManager.DomainConfiguration != null)
            {
                foreach (Type data in domainManager.DomainConfiguration)
                {
                    ServiceBusDetails serviceBusDetails = GetServiceBusDetailsFromT(data);
                    if (!string.IsNullOrEmpty(serviceBusDetails.Connection))
                    {
                        if (!string.IsNullOrWhiteSpace(serviceBusDetails.QueueName))
                        {
                            ////Add queue client to _queueManager which will be used for publish
                            string queueKeyName = $"{serviceBusDetails.Endpoint}||{serviceBusDetails.QueueName}";
                            if (!_queueManager.ContainsKey(queueKeyName))
                            {
                                ////Check for queue and if not exists AzureQueueProvider will create it.
                                AzureQueueProvider azureQueueProvider = new AzureQueueProvider(serviceBusDetails.Connection, serviceBusDetails.QueueName);
                                azureQueueProvider.AddQueue(serviceBusDetails.ServiceBusNamespace, serviceBusDetails.SharedAccessKeyName, serviceBusDetails.SharedAccessKey, serviceBusDetails.QueueName, string.Empty);

                                AzureQueueSender queueClient = new AzureQueueSender(serviceBusDetails.Connection, serviceBusDetails.QueueName);
                                _queueManager.TryAdd(queueKeyName, queueClient);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Publishes the specified gereric event model.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="gerericEventModel">The gereric event model.</param>
        /// <returns></returns>
        public bool Publish <T>(T gerericEventModel)
        {
            try
            {
                ServiceBusDetails serviceBusDetails = GetServiceBusDetailsFromT(gerericEventModel.GetType());

                if (!string.IsNullOrEmpty(serviceBusDetails.Connection))
                {
                    if (_topicManager.TryGetValue($"{serviceBusDetails.Endpoint}||{serviceBusDetails.TopicName}", out AzureTopicPublisher topicClient))
                    {
                        Dictionary <string, object> userPropertiesDict = new Dictionary <string, object>
                        {
                            //// version wise event bus: Consider ver = EventTypeVersion which is atleast 1 (which we have settled in GetServiceBusDetailsFromT() )
                            { "ver", serviceBusDetails.EventTypeVersion },
                            { "type", 1 },
                            { "mId", Guid.NewGuid().ToString() },
                            { "pId", serviceBusDetails.ProducerId },
                            { "eId", Convert.ToInt16(serviceBusDetails.EventId) },
                            { "tsSend", DateTime.UtcNow.Ticks },

                            //// Producer application id;
                            { "paId", serviceBusDetails.ProducerApplicationId },
                        };

                        EventModel <object> eventModel = new EventModel <object>()
                        {
                            Value = JsonConvert.SerializeObject(gerericEventModel).ToBase64Encode(),
                        };

                        Message message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(eventModel).ToBase64Encode()));

                        foreach (KeyValuePair <string, object> item in userPropertiesDict)
                        {
                            message.UserProperties.Add(new KeyValuePair <string, object>(item.Key, item.Value));
                        }

                        topicClient.SendAsync(message).Wait();
                        return(true);
                    }
                }

                return(false);
            }
            catch (Exception ex)
            {
                return(false);
            }
        }
        /// <summary>
        /// Gets the service bus details from t.
        /// </summary>
        /// <param name="domainType">Type of the domain.</param>
        /// <returns></returns>
        static ServiceBusDetails GetServiceBusDetailsFromT(Type domainType)
        {
            ServiceBusDetails serviceBusDetails = new ServiceBusDetails();

            ConfigureAttribute customAttribute = (ConfigureAttribute)Attribute.GetCustomAttribute(domainType, typeof(ConfigureAttribute));

            if (customAttribute != null && !string.IsNullOrEmpty(customAttribute.Connection))
            {
                if (_eventBusConfiguration != null)
                {
                    _eventBusConfiguration.TryGet(customAttribute.Connection, out string serviceBusConnection);
                    if (!string.IsNullOrEmpty(serviceBusConnection))
                    {
                        serviceBusDetails.Connection = serviceBusConnection;
                        serviceBusDetails.TopicName  = customAttribute.TopicName;
                        serviceBusDetails.EventId    = customAttribute.EventId;
                        //serviceBusDetails.ProducerId = (Int16)_domainManager.ServiceType;

                        //serviceBusDetails.ProducerApplicationId = (Int16)_domainManager.ApplicationType;

                        Dictionary <string, string> dict = serviceBusConnection.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                                                           .Select(part => part.Split(new[] { '=' }, 2))
                                                           .ToDictionary(split => split[0], split => split[1]);

                        serviceBusDetails.ServiceBusNamespace = dict["Endpoint"].Split("//")[1].Split('.')[0];
                        serviceBusDetails.SharedAccessKeyName = dict["SharedAccessKeyName"];
                        serviceBusDetails.SharedAccessKey     = dict["SharedAccessKey"];
                        serviceBusDetails.Endpoint            = dict["Endpoint"].Split("//")[1].Split('/')[0];

                        //// version wise event bus: if EventTypeVersion  == 0 then consider version = 1 else set subscription name based on version defined in ConfigureAttribute
                        serviceBusDetails.EventTypeVersion = customAttribute.EventTypeVersion;
                        if (serviceBusDetails.EventTypeVersion == 0)
                        {
                            serviceBusDetails.EventTypeVersion = 1;
                        }
                        //serviceBusDetails.Subscription = $"{_domainManager.ServiceType.ToString().ToLower()}_{customAttribute.EventId.ToString()}_v{customAttribute.EventTypeVersion.ToString()}";
                        serviceBusDetails.Subscription = "solution-logs-subs-qa";

                        serviceBusDetails.QueueName = customAttribute.QueueName;
                    }
                }
            }

            return(serviceBusDetails);
        }
        /// <summary>
        /// Subscribes the specified target model.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="targetModel">The target model.</param>
        /// <param name="handler">The handler.</param>
        /// <returns></returns>
        public bool Subscribe <T>(T targetModel, Func <T, Task> handler)
        {
            try
            {
                ServiceBusDetails serviceBusDetails = GetServiceBusDetailsFromT(targetModel.GetType());

                if (!string.IsNullOrEmpty(serviceBusDetails.Connection))
                {
                    //Check for Subscription and topic, if not exists AzureTopicProvider will create both them.
                    //we are considering UserProperty event id for sql filter
                    AzureTopicProvider azureTopicProvider = new AzureTopicProvider(serviceBusDetails.Connection, serviceBusDetails.TopicName, serviceBusDetails.Subscription);

                    //// version wise event bus: Each version wise subscriber get only message of that versioned model/object
                    string routingKey = $"user.eId = {serviceBusDetails.EventId}  AND user.ver = {serviceBusDetails.EventTypeVersion}";

                    azureTopicProvider.AddSubscriber(routingKey);

                    subscriptionClient = new AzureTopicSubscriber(serviceBusDetails.Connection, serviceBusDetails.TopicName, serviceBusDetails.Subscription);
                    MessageHandlerOptions messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
                    {
                        MaxConcurrentCalls = 1,
                        AutoComplete       = true
                    };

                    //subscriptionClient.RegisterMessageHandler(handler, messageHandlerOptions);
                    subscriptionClient.RegisterMessageHandler(async(msg, token) =>
                    {
                        try
                        {
                            // Get message
                            string message = Encoding.UTF8.GetString(msg.Body).ToBase64Decode();

                            EventModel <object> objEvent1 = JsonConvert.DeserializeObject <EventModel <object> >(message);
                            T retrunModel = JsonConvert.DeserializeObject <T>(JsonConvert.SerializeObject(objEvent1.OriginalValue));

                            msg.UserProperties.Add(new KeyValuePair <string, object>("tsReceive", DateTime.UtcNow.Ticks));
                            msg.UserProperties.Add(new KeyValuePair <string, object>("rId", _domainManager.ServiceType));

                            PropertyInfo prop = null;

                            //// set producer id to the message model which will be received by subscriber
                            if (msg.UserProperties.TryGetValue("pId", out object producerId))
                            {
                                prop = retrunModel.GetType().GetProperty("_ProducerId", BindingFlags.Public | BindingFlags.Instance);
                                if (null != prop && prop.CanWrite)
                                {
                                    prop.SetValue(retrunModel, producerId, null);
                                }
                            }

                            //// set original message to the message model which will be received by subscriber
                            prop = retrunModel.GetType().GetProperty("_OriginalMessage", BindingFlags.Public | BindingFlags.Instance);
                            if (null != prop && prop.CanWrite)
                            {
                                prop.SetValue(retrunModel, JsonConvert.SerializeObject(msg), null);
                            }

                            //// set producer application id to the message model which will be received by subscriber
                            if (msg.UserProperties.TryGetValue("paId", out object producerApplicationId))
                            {
                                prop = retrunModel.GetType().GetProperty("_ProducerApplicationId", BindingFlags.Public | BindingFlags.Instance);
                                if (null != prop && prop.CanWrite)
                                {
                                    prop.SetValue(retrunModel, producerApplicationId, null);
                                }
                            }

                            //// set event id to the message model which will be received by subscriber
                            if (msg.UserProperties.TryGetValue("eId", out object eventId))
                            {
                                prop = retrunModel.GetType().GetProperty("_EventId", BindingFlags.Public | BindingFlags.Instance);
                                if (null != prop && prop.CanWrite)
                                {
                                    prop.SetValue(retrunModel, eventId, null);
                                }
                            }

                            handler(retrunModel);
                        }
                        catch (Exception ex)
                        {
                        }
                    }, messageHandlerOptions);

                    return(true);
                }

                return(false);
            }
            catch (Exception)
            {
                return(false);
            }
        }