You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by aa...@apache.org on 2023/03/07 07:20:05 UTC

[rocketmq-clients] branch master updated (00492cc7 -> cd4302c5)

This is an automated email from the ASF dual-hosted git repository.

aaronai pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git


    from 00492cc7 Bugfix: wrong message type judgement
     new 912b3752 Add more tests
     new cd4302c5 Support to use DateTime.Now to send message

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 csharp/examples/ProducerDelayMessageExample.cs     |   2 +-
 .../examples/ProducerTransactionMessageExample.cs  |   2 +-
 csharp/examples/SimpleConsumerExample.cs           |   2 +-
 csharp/rocketmq-client-csharp/Broker.cs            |   2 +-
 csharp/rocketmq-client-csharp/ClientManager.cs     |   4 +-
 csharp/rocketmq-client-csharp/ClientMeter.cs       |   6 +-
 .../ConfigFileCredentialsProvider.cs               |  18 ++--
 csharp/rocketmq-client-csharp/Consumer.cs          |   2 +-
 .../ExponentialBackoffRetryPolicy.cs               |   6 +-
 csharp/rocketmq-client-csharp/IClientManager.cs    |  47 ++++++++--
 csharp/rocketmq-client-csharp/IConsumer.cs         |  27 ------
 csharp/rocketmq-client-csharp/IRetryPolicy.cs      |   7 +-
 csharp/rocketmq-client-csharp/Message.cs           |   8 +-
 csharp/rocketmq-client-csharp/MessageQueue.cs      |   2 +-
 csharp/rocketmq-client-csharp/MessageView.cs       |   5 +-
 csharp/rocketmq-client-csharp/Producer.cs          |  11 ++-
 csharp/rocketmq-client-csharp/PublishingMessage.cs |   4 +-
 .../rocketmq-client-csharp/PublishingSettings.cs   |   2 +-
 csharp/rocketmq-client-csharp/Resource.cs          |   4 +-
 csharp/rocketmq-client-csharp/Settings.cs          |   4 +-
 csharp/rocketmq-client-csharp/Topic.cs             |   4 +-
 .../rocketmq-client-csharp/TopicRouteException.cs  |  29 ------
 csharp/rocketmq-client-csharp/Transaction.cs       |   4 +-
 .../TransactionResolution.cs                       |   6 +-
 .../rocketmq-client-csharp.csproj                  |   2 +-
 csharp/tests/ConfigFileCredentialsProviderTest.cs  |  11 ++-
 csharp/tests/DateTimeTest.cs                       |  14 +--
 csharp/tests/EndpointsTest.cs                      |  17 +++-
 csharp/tests/MessageTest.cs                        |  47 +++++++++-
 csharp/tests/MqLogManagerTest.cs                   |   1 +
 csharp/tests/PublishingMessageTest.cs              | 103 +++++++++++++++++++++
 csharp/tests/SendResultTest.cs                     |  33 -------
 csharp/tests/SignatureTest.cs                      |  44 ---------
 csharp/tests/TopicTest.cs                          |  51 ----------
 csharp/tests/UnitTest1.cs                          |  82 ----------------
 csharp/tests/tests.csproj                          |   4 +-
 36 files changed, 274 insertions(+), 343 deletions(-)
 delete mode 100644 csharp/rocketmq-client-csharp/IConsumer.cs
 delete mode 100644 csharp/rocketmq-client-csharp/TopicRouteException.cs
 create mode 100644 csharp/tests/PublishingMessageTest.cs
 delete mode 100644 csharp/tests/SendResultTest.cs
 delete mode 100644 csharp/tests/SignatureTest.cs
 delete mode 100644 csharp/tests/TopicTest.cs
 delete mode 100644 csharp/tests/UnitTest1.cs


[rocketmq-clients] 02/02: Support to use DateTime.Now to send message

Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aaronai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git

commit cd4302c5f23c9602b5bc9d70587ff5c856963aee
Author: Aaron Ai <ya...@gmail.com>
AuthorDate: Tue Mar 7 14:50:53 2023 +0800

    Support to use DateTime.Now to send message
---
 csharp/examples/ProducerDelayMessageExample.cs     |  2 +-
 csharp/rocketmq-client-csharp/IClientManager.cs    |  3 +--
 csharp/rocketmq-client-csharp/Message.cs           |  4 +++-
 csharp/rocketmq-client-csharp/MessageView.cs       |  5 +++--
 csharp/rocketmq-client-csharp/Producer.cs          |  3 ++-
 csharp/rocketmq-client-csharp/PublishingMessage.cs |  2 +-
 csharp/tests/EndpointsTest.cs                      |  4 ++--
 csharp/tests/MessageTest.cs                        | 25 ++++++++++++++++++++++
 8 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/csharp/examples/ProducerDelayMessageExample.cs b/csharp/examples/ProducerDelayMessageExample.cs
index f1119245..84808872 100644
--- a/csharp/examples/ProducerDelayMessageExample.cs
+++ b/csharp/examples/ProducerDelayMessageExample.cs
@@ -59,7 +59,7 @@ namespace examples
                 .SetTag(tag)
                 // You could set multiple keys for the single message actually.
                 .SetKeys("yourMessageKey-2f00df144e48")
-                .SetDeliveryTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(30))
+                .SetDeliveryTimestamp(DateTime.Now + TimeSpan.FromSeconds(30))
                 .Build();
 
             var sendReceipt = await producer.Send(message);
diff --git a/csharp/rocketmq-client-csharp/IClientManager.cs b/csharp/rocketmq-client-csharp/IClientManager.cs
index d69b0506..19f9459f 100644
--- a/csharp/rocketmq-client-csharp/IClientManager.cs
+++ b/csharp/rocketmq-client-csharp/IClientManager.cs
@@ -90,8 +90,7 @@ namespace Org.Apache.Rocketmq
         /// <param name="timeout">Request max duration.</param>
         /// <returns></returns>
         Task<RpcInvocation<ReceiveMessageRequest, List<ReceiveMessageResponse>>> ReceiveMessage(Endpoints endpoints,
-            ReceiveMessageRequest request,
-            TimeSpan timeout);
+            ReceiveMessageRequest request, TimeSpan timeout);
 
         /// <summary>
         /// Message acknowledgement towards remote endpoints.
diff --git a/csharp/rocketmq-client-csharp/Message.cs b/csharp/rocketmq-client-csharp/Message.cs
index 42c271a5..b71a4650 100644
--- a/csharp/rocketmq-client-csharp/Message.cs
+++ b/csharp/rocketmq-client-csharp/Message.cs
@@ -131,7 +131,9 @@ namespace Org.Apache.Rocketmq
             {
                 Preconditions.CheckArgument(null == _messageGroup,
                     "deliveryTimestamp and messageGroup should not be set at same time");
-                _deliveryTimestamp = deliveryTimestamp;
+                _deliveryTimestamp = DateTimeKind.Utc == deliveryTimestamp.Kind
+                    ? TimeZoneInfo.ConvertTimeFromUtc(deliveryTimestamp, TimeZoneInfo.Local)
+                    : deliveryTimestamp;
                 return this;
             }
 
diff --git a/csharp/rocketmq-client-csharp/MessageView.cs b/csharp/rocketmq-client-csharp/MessageView.cs
index 57a10619..2581f48b 100644
--- a/csharp/rocketmq-client-csharp/MessageView.cs
+++ b/csharp/rocketmq-client-csharp/MessageView.cs
@@ -158,11 +158,12 @@ namespace Org.Apache.Rocketmq
             var messageGroup = systemProperties.HasMessageGroup ? systemProperties.MessageGroup : null;
             DateTime? deliveryTime = null == systemProperties.DeliveryTimestamp
                 ? null
-                : systemProperties.DeliveryTimestamp.ToDateTime();
+                : TimeZoneInfo.ConvertTimeFromUtc(systemProperties.DeliveryTimestamp.ToDateTime(), TimeZoneInfo.Local);
             var keys = systemProperties.Keys.ToList();
 
             var bornHost = systemProperties.BornHost;
-            var bornTime = systemProperties.BornTimestamp.ToDateTime();
+            var bornTime =
+                TimeZoneInfo.ConvertTimeFromUtc(systemProperties.BornTimestamp.ToDateTime(), TimeZoneInfo.Local);
             var deliveryAttempt = systemProperties.DeliveryAttempt;
             var queueOffset = systemProperties.QueueOffset;
             var properties = new Dictionary<string, string>();
diff --git a/csharp/rocketmq-client-csharp/Producer.cs b/csharp/rocketmq-client-csharp/Producer.cs
index 95ddf98b..eebc24a2 100644
--- a/csharp/rocketmq-client-csharp/Producer.cs
+++ b/csharp/rocketmq-client-csharp/Producer.cs
@@ -188,7 +188,8 @@ namespace Org.Apache.Rocketmq
                 }
             }
 
-            throw exception!;
+            throw new Exception($"Failed to send message finally, topic={message.Topic}, clientId={ClientId}",
+                exception);
         }
 
         public async Task<ISendReceipt> Send(Message message)
diff --git a/csharp/rocketmq-client-csharp/PublishingMessage.cs b/csharp/rocketmq-client-csharp/PublishingMessage.cs
index b65f4660..ff681fe7 100644
--- a/csharp/rocketmq-client-csharp/PublishingMessage.cs
+++ b/csharp/rocketmq-client-csharp/PublishingMessage.cs
@@ -92,7 +92,7 @@ namespace Org.Apache.Rocketmq
 
             if (DeliveryTimestamp.HasValue)
             {
-                systemProperties.DeliveryTimestamp = Timestamp.FromDateTime(DeliveryTimestamp.Value);
+                systemProperties.DeliveryTimestamp = Timestamp.FromDateTime(DeliveryTimestamp.Value.ToUniversalTime());
             }
 
             if (null != MessageGroup)
diff --git a/csharp/tests/EndpointsTest.cs b/csharp/tests/EndpointsTest.cs
index 4c85209e..8e71ae23 100644
--- a/csharp/tests/EndpointsTest.cs
+++ b/csharp/tests/EndpointsTest.cs
@@ -35,8 +35,8 @@ namespace tests
         public void TestGrpcTargetWithSsl()
         {
             var endpoints = new Endpoints("127.0.0.1");
-            var targetWithoutSsl = endpoints.GrpcTarget(true);
-            Assert.AreEqual("https://127.0.0.1:80", targetWithoutSsl);
+            var targetWithSsl = endpoints.GrpcTarget(true);
+            Assert.AreEqual("https://127.0.0.1:80", targetWithSsl);
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/tests/MessageTest.cs b/csharp/tests/MessageTest.cs
index d8191d28..56d942cf 100644
--- a/csharp/tests/MessageTest.cs
+++ b/csharp/tests/MessageTest.cs
@@ -148,6 +148,31 @@ namespace tests
             new Message.Builder().SetKeys("a", "b");
         }
 
+        [TestMethod]
+        public void TestSetDeliveryTimestampWithLocalTime()
+        {
+            var deliveryTimestamp = DateTime.Now;
+            var message = new Message.Builder().SetTopic("yourTopic").SetDeliveryTimestamp(deliveryTimestamp)
+                .SetBody(Encoding.UTF8.GetBytes("foobar"))
+                .Build();
+            Assert.IsTrue(message.DeliveryTimestamp.HasValue);
+            Assert.AreEqual(DateTimeKind.Local, message.DeliveryTimestamp.Value.Kind);
+            Assert.AreEqual(deliveryTimestamp, message.DeliveryTimestamp.Value);
+        }
+
+        [TestMethod]
+        public void TestSetDeliveryTimestampWithUtcTime()
+        {
+            var deliveryTimestamp = DateTime.UtcNow;
+            var message = new Message.Builder().SetTopic("yourTopic").SetDeliveryTimestamp(deliveryTimestamp)
+                .SetBody(Encoding.UTF8.GetBytes("foobar"))
+                .Build();
+            Assert.IsTrue(message.DeliveryTimestamp.HasValue);
+            Assert.AreEqual(DateTimeKind.Local, message.DeliveryTimestamp.Value.Kind);
+            var localTimestamp = TimeZoneInfo.ConvertTimeFromUtc(deliveryTimestamp, TimeZoneInfo.Local);
+            Assert.AreEqual(localTimestamp, message.DeliveryTimestamp.Value);
+        }
+
         [TestMethod]
         [ExpectedException(typeof(ArgumentException))]
         public void TestSetDeliveryTimestampAndMessageGroup()


[rocketmq-clients] 01/02: Add more tests

Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aaronai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/rocketmq-clients.git

commit 912b37526452a8f328a4dfc382f4073074ea53b7
Author: Aaron Ai <ya...@gmail.com>
AuthorDate: Mon Mar 6 18:30:09 2023 +0800

    Add more tests
---
 .../examples/ProducerTransactionMessageExample.cs  |   2 +-
 csharp/examples/SimpleConsumerExample.cs           |   2 +-
 csharp/rocketmq-client-csharp/Broker.cs            |   2 +-
 csharp/rocketmq-client-csharp/ClientManager.cs     |   4 +-
 csharp/rocketmq-client-csharp/ClientMeter.cs       |   6 +-
 .../ConfigFileCredentialsProvider.cs               |  18 ++--
 csharp/rocketmq-client-csharp/Consumer.cs          |   2 +-
 .../ExponentialBackoffRetryPolicy.cs               |   6 +-
 csharp/rocketmq-client-csharp/IClientManager.cs    |  44 ++++++++-
 csharp/rocketmq-client-csharp/IConsumer.cs         |  27 ------
 csharp/rocketmq-client-csharp/IRetryPolicy.cs      |   7 +-
 csharp/rocketmq-client-csharp/Message.cs           |   4 +
 csharp/rocketmq-client-csharp/MessageQueue.cs      |   2 +-
 csharp/rocketmq-client-csharp/Producer.cs          |   8 +-
 csharp/rocketmq-client-csharp/PublishingMessage.cs |   2 +-
 .../rocketmq-client-csharp/PublishingSettings.cs   |   2 +-
 csharp/rocketmq-client-csharp/Resource.cs          |   4 +-
 csharp/rocketmq-client-csharp/Settings.cs          |   4 +-
 csharp/rocketmq-client-csharp/Topic.cs             |   4 +-
 .../rocketmq-client-csharp/TopicRouteException.cs  |  29 ------
 csharp/rocketmq-client-csharp/Transaction.cs       |   4 +-
 .../TransactionResolution.cs                       |   6 +-
 .../rocketmq-client-csharp.csproj                  |   2 +-
 csharp/tests/ConfigFileCredentialsProviderTest.cs  |  11 ++-
 csharp/tests/DateTimeTest.cs                       |  14 +--
 csharp/tests/EndpointsTest.cs                      |  17 +++-
 csharp/tests/MessageTest.cs                        |  22 ++++-
 csharp/tests/MqLogManagerTest.cs                   |   1 +
 csharp/tests/PublishingMessageTest.cs              | 103 +++++++++++++++++++++
 csharp/tests/SendResultTest.cs                     |  33 -------
 csharp/tests/SignatureTest.cs                      |  44 ---------
 csharp/tests/TopicTest.cs                          |  51 ----------
 csharp/tests/UnitTest1.cs                          |  82 ----------------
 csharp/tests/tests.csproj                          |   4 +-
 34 files changed, 238 insertions(+), 335 deletions(-)

diff --git a/csharp/examples/ProducerTransactionMessageExample.cs b/csharp/examples/ProducerTransactionMessageExample.cs
index f9c34ffa..1b5b7aa4 100644
--- a/csharp/examples/ProducerTransactionMessageExample.cs
+++ b/csharp/examples/ProducerTransactionMessageExample.cs
@@ -31,7 +31,7 @@ namespace examples
             public TransactionResolution Check(MessageView messageView)
             {
                 Logger.Info("Receive transaction check, messageId={}", messageView.MessageId);
-                return TransactionResolution.COMMIT;
+                return TransactionResolution.Commit;
             }
         }
 
diff --git a/csharp/examples/SimpleConsumerExample.cs b/csharp/examples/SimpleConsumerExample.cs
index 25fba533..fd0d9d7a 100644
--- a/csharp/examples/SimpleConsumerExample.cs
+++ b/csharp/examples/SimpleConsumerExample.cs
@@ -56,7 +56,7 @@ namespace examples
             var messageViews = await simpleConsumer.Receive(16, TimeSpan.FromSeconds(15));
             foreach (var message in messageViews)
             {
-                Logger.Info($"Received a message, topic={message.Topic}, message-id={message.MessageId}");
+                Logger.Info($"Received a message, topic={message.Topic}, message-id={message.MessageId}, body-size={message.Body.Length}");
                 await simpleConsumer.Ack(message);
                 Logger.Info($"Message is acknowledged successfully, message-id={message.MessageId}");
                 // await simpleConsumer.ChangeInvisibleDuration(message, TimeSpan.FromSeconds(15));
diff --git a/csharp/rocketmq-client-csharp/Broker.cs b/csharp/rocketmq-client-csharp/Broker.cs
index 6a2f957a..d42d03b1 100644
--- a/csharp/rocketmq-client-csharp/Broker.cs
+++ b/csharp/rocketmq-client-csharp/Broker.cs
@@ -34,7 +34,7 @@ namespace Org.Apache.Rocketmq
 
         public Proto.Broker ToProtobuf()
         {
-            return new Proto.Broker()
+            return new Proto.Broker
             {
                 Name = Name,
                 Id = Id,
diff --git a/csharp/rocketmq-client-csharp/ClientManager.cs b/csharp/rocketmq-client-csharp/ClientManager.cs
index 9d0b92a5..808d73f1 100644
--- a/csharp/rocketmq-client-csharp/ClientManager.cs
+++ b/csharp/rocketmq-client-csharp/ClientManager.cs
@@ -27,13 +27,13 @@ namespace Org.Apache.Rocketmq
     public class ClientManager : IClientManager
     {
         private readonly Client _client;
-        private readonly Dictionary<Endpoints, RpcClient> _rpcClients;
+        private readonly Dictionary<Endpoints, IRpcClient> _rpcClients;
         private readonly ReaderWriterLockSlim _clientLock;
 
         public ClientManager(Client client)
         {
             _client = client;
-            _rpcClients = new Dictionary<Endpoints, RpcClient>();
+            _rpcClients = new Dictionary<Endpoints, IRpcClient>();
             _clientLock = new ReaderWriterLockSlim();
         }
 
diff --git a/csharp/rocketmq-client-csharp/ClientMeter.cs b/csharp/rocketmq-client-csharp/ClientMeter.cs
index 53fc2cdf..e4360cd1 100644
--- a/csharp/rocketmq-client-csharp/ClientMeter.cs
+++ b/csharp/rocketmq-client-csharp/ClientMeter.cs
@@ -38,11 +38,11 @@ namespace Org.Apache.Rocketmq
             ClientId = clientId;
         }
 
-        public Endpoints Endpoints { get; }
+        private Endpoints Endpoints { get; }
 
-        public MeterProvider MeterProvider { get; }
+        private MeterProvider MeterProvider { get; }
 
-        public string ClientId { get; }
+        private string ClientId { get; }
 
         public bool Enabled { get; }
 
diff --git a/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs b/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs
index b30d85d5..93b9e9ef 100644
--- a/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs
+++ b/csharp/rocketmq-client-csharp/ConfigFileCredentialsProvider.cs
@@ -23,13 +23,12 @@ using NLog;
 
 namespace Org.Apache.Rocketmq
 {
-
     /**
      * File-based credentials provider that reads JSON configurations from ${HOME}/.rocketmq/config
      * A sample config content is as follows:
      * {"AccessKey": "key", "AccessSecret": "secret"}
      */
-    public class ConfigFileCredentialsProvider 
+    public class ConfigFileCredentialsProvider
     {
         private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger();
 
@@ -53,7 +52,7 @@ namespace Org.Apache.Rocketmq
                     Logger.Error($"Failed to parse JSON configuration: {json}");
                     return;
                 }
-                
+
                 _accessKey = kv["AccessKey"];
                 _accessSecret = kv["AccessSecret"];
                 _valid = true;
@@ -66,19 +65,14 @@ namespace Org.Apache.Rocketmq
 
         public SessionCredentials GetCredentials()
         {
-            if (!_valid)
-            {
-                return null;
-            }
-
-            return new SessionCredentials(_accessKey, _accessSecret);
+            return !_valid ? null : new SessionCredentials(_accessKey, _accessSecret);
         }
 
-        public static String DefaultConfigFilePath()
+        public static string DefaultConfigFilePath()
         {
             var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
-            string[] pathSegments = {home, ".rocketmq", "config"}; 
-            return String.Join(Path.DirectorySeparatorChar, pathSegments);
+            string[] pathSegments = { home, ".rocketmq", "config" };
+            return string.Join(Path.DirectorySeparatorChar, pathSegments);
         }
 
         private readonly string _accessKey;
diff --git a/csharp/rocketmq-client-csharp/Consumer.cs b/csharp/rocketmq-client-csharp/Consumer.cs
index 3444fbc0..998a3766 100644
--- a/csharp/rocketmq-client-csharp/Consumer.cs
+++ b/csharp/rocketmq-client-csharp/Consumer.cs
@@ -42,7 +42,7 @@ namespace Org.Apache.Rocketmq
             var tolerance = ClientConfig.RequestTimeout;
             var timeout = tolerance.Add(awaitDuration);
             var invocation = await ClientManager.ReceiveMessage(mq.Broker.Endpoints, request, timeout);
-            var status = new Proto.Status()
+            var status = new Proto.Status
             {
                 Code = Proto.Code.InternalServerError,
                 Message = "Status was not set by server"
diff --git a/csharp/rocketmq-client-csharp/ExponentialBackoffRetryPolicy.cs b/csharp/rocketmq-client-csharp/ExponentialBackoffRetryPolicy.cs
index ddc4d281..d4826d85 100644
--- a/csharp/rocketmq-client-csharp/ExponentialBackoffRetryPolicy.cs
+++ b/csharp/rocketmq-client-csharp/ExponentialBackoffRetryPolicy.cs
@@ -39,11 +39,11 @@ namespace Org.Apache.Rocketmq
             return _maxAttempts;
         }
 
-        public TimeSpan InitialBackoff { get; }
+        private TimeSpan InitialBackoff { get; }
 
-        public TimeSpan MaxBackoff { get; }
+        private TimeSpan MaxBackoff { get; }
 
-        public double BackoffMultiplier { get; }
+        private double BackoffMultiplier { get; }
 
         public IRetryPolicy InheritBackoff(Proto.RetryPolicy retryPolicy)
         {
diff --git a/csharp/rocketmq-client-csharp/IClientManager.cs b/csharp/rocketmq-client-csharp/IClientManager.cs
index 47af0280..d69b0506 100644
--- a/csharp/rocketmq-client-csharp/IClientManager.cs
+++ b/csharp/rocketmq-client-csharp/IClientManager.cs
@@ -65,27 +65,61 @@ namespace Org.Apache.Rocketmq
         /// <summary>
         /// Send message to remote endpoints.
         /// </summary>
-        /// <param name="endpoints"></param>
-        /// <param name="request"></param>
-        /// <param name="timeout"></param>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request for message publishing.</param>
+        /// <param name="timeout">Request max duration.</param>
         /// <returns></returns>
         Task<RpcInvocation<SendMessageRequest, SendMessageResponse>> SendMessage(Endpoints endpoints,
             SendMessageRequest request, TimeSpan timeout);
 
+        /// <summary>
+        /// Query assignment to receive message for push consumer.
+        /// </summary>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request for querying assignment.</param>
+        /// <param name="timeout">Request max duration.</param>
+        /// <returns></returns>
         Task<RpcInvocation<QueryAssignmentRequest, QueryAssignmentResponse>> QueryAssignment(Endpoints endpoints,
             QueryAssignmentRequest request, TimeSpan timeout);
 
+        /// <summary>
+        /// Receive message from remote endpoints.
+        /// </summary>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request for message receiving.</param>
+        /// <param name="timeout">Request max duration.</param>
+        /// <returns></returns>
         Task<RpcInvocation<ReceiveMessageRequest, List<ReceiveMessageResponse>>> ReceiveMessage(Endpoints endpoints,
             ReceiveMessageRequest request,
             TimeSpan timeout);
 
+        /// <summary>
+        /// Message acknowledgement towards remote endpoints.
+        /// </summary>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request for message acknowledgement.</param>
+        /// <param name="timeout">Request max duration.</param>
+        /// <returns></returns>
         Task<RpcInvocation<AckMessageRequest, AckMessageResponse>> AckMessage(Endpoints endpoints,
             AckMessageRequest request, TimeSpan timeout);
 
+        /// <summary>
+        /// Change message invisible duration.
+        /// </summary>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request of changing message invisible duration.</param>
+        /// <param name="timeout">Request max duration.</param>
+        /// <returns></returns>
         Task<RpcInvocation<ChangeInvisibleDurationRequest, ChangeInvisibleDurationResponse>> ChangeInvisibleDuration(
-            Endpoints endpoints,
-            ChangeInvisibleDurationRequest request, TimeSpan timeout);
+            Endpoints endpoints, ChangeInvisibleDurationRequest request, TimeSpan timeout);
 
+        /// <summary>
+        /// Transaction ending request.
+        /// </summary>
+        /// <param name="endpoints">The target endpoints.</param>
+        /// <param name="request">gRPC request of ending transaction.</param>
+        /// <param name="timeout">Request max duration.</param>
+        /// <returns></returns>
         Task<RpcInvocation<EndTransactionRequest, EndTransactionResponse>> EndTransaction(Endpoints endpoints,
             EndTransactionRequest request, TimeSpan timeout);
 
diff --git a/csharp/rocketmq-client-csharp/IConsumer.cs b/csharp/rocketmq-client-csharp/IConsumer.cs
deleted file mode 100644
index 2ad0daba..00000000
--- a/csharp/rocketmq-client-csharp/IConsumer.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System.Threading.Tasks;
-namespace Org.Apache.Rocketmq
-{
-    public interface IConsumer
-    {
-        Task Start();
-
-        Task Shutdown();
-    }
-}
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/IRetryPolicy.cs b/csharp/rocketmq-client-csharp/IRetryPolicy.cs
index 86d280eb..fe7e7116 100644
--- a/csharp/rocketmq-client-csharp/IRetryPolicy.cs
+++ b/csharp/rocketmq-client-csharp/IRetryPolicy.cs
@@ -45,6 +45,11 @@ namespace Org.Apache.Rocketmq
         /// <returns></returns>
         RetryPolicy ToProtobuf();
 
-        IRetryPolicy InheritBackoff(Proto.RetryPolicy retryPolicy);
+        /// <summary>
+        /// Inherit backoff of retry policy.
+        /// </summary>
+        /// <param name="retryPolicy"></param>
+        /// <returns></returns>
+        IRetryPolicy InheritBackoff(RetryPolicy retryPolicy);
     }
 }
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/Message.cs b/csharp/rocketmq-client-csharp/Message.cs
index 32c4352c..42c271a5 100644
--- a/csharp/rocketmq-client-csharp/Message.cs
+++ b/csharp/rocketmq-client-csharp/Message.cs
@@ -129,6 +129,8 @@ namespace Org.Apache.Rocketmq
 
             public Builder SetDeliveryTimestamp(DateTime deliveryTimestamp)
             {
+                Preconditions.CheckArgument(null == _messageGroup,
+                    "deliveryTimestamp and messageGroup should not be set at same time");
                 _deliveryTimestamp = deliveryTimestamp;
                 return this;
             }
@@ -137,6 +139,8 @@ namespace Org.Apache.Rocketmq
             {
                 Preconditions.CheckArgument(!string.IsNullOrWhiteSpace(messageGroup),
                     "messageGroup should not be null or white space");
+                Preconditions.CheckArgument(null == _deliveryTimestamp,
+                    "messageGroup and deliveryTimestamp should not be set at same time");
                 _messageGroup = messageGroup;
                 return this;
             }
diff --git a/csharp/rocketmq-client-csharp/MessageQueue.cs b/csharp/rocketmq-client-csharp/MessageQueue.cs
index b4504f12..e5146d52 100644
--- a/csharp/rocketmq-client-csharp/MessageQueue.cs
+++ b/csharp/rocketmq-client-csharp/MessageQueue.cs
@@ -37,7 +37,7 @@ namespace Org.Apache.Rocketmq
 
         public Broker Broker { get; }
 
-        public Resource TopicResource { get; }
+        private Resource TopicResource { get; }
 
         public Permission Permission { get; }
 
diff --git a/csharp/rocketmq-client-csharp/Producer.cs b/csharp/rocketmq-client-csharp/Producer.cs
index 6510909b..95ddf98b 100644
--- a/csharp/rocketmq-client-csharp/Producer.cs
+++ b/csharp/rocketmq-client-csharp/Producer.cs
@@ -293,12 +293,12 @@ namespace Org.Apache.Rocketmq
             var transactionResolution = _checker.Check(message);
             switch (transactionResolution)
             {
-                case TransactionResolution.COMMIT:
-                case TransactionResolution.ROLLBACK:
+                case TransactionResolution.Commit:
+                case TransactionResolution.Rollback:
                     await EndTransaction(endpoints, message.Topic, message.MessageId, command.TransactionId,
                         transactionResolution);
                     break;
-                case TransactionResolution.UNKNOWN:
+                case TransactionResolution.Unknown:
                 default:
                     break;
             }
@@ -321,7 +321,7 @@ namespace Org.Apache.Rocketmq
                 TransactionId = transactionId,
                 MessageId = messageId,
                 Topic = topicResource,
-                Resolution = TransactionResolution.COMMIT == resolution
+                Resolution = TransactionResolution.Commit == resolution
                     ? Proto.TransactionResolution.Commit
                     : Proto.TransactionResolution.Rollback
             };
diff --git a/csharp/rocketmq-client-csharp/PublishingMessage.cs b/csharp/rocketmq-client-csharp/PublishingMessage.cs
index b5c92f51..b65f4660 100644
--- a/csharp/rocketmq-client-csharp/PublishingMessage.cs
+++ b/csharp/rocketmq-client-csharp/PublishingMessage.cs
@@ -29,7 +29,7 @@ namespace Org.Apache.Rocketmq
     /// </summary>
     public class PublishingMessage : Message
     {
-        public MessageType MessageType { set; get; }
+        public MessageType MessageType { get; }
 
         internal string MessageId { get; }
 
diff --git a/csharp/rocketmq-client-csharp/PublishingSettings.cs b/csharp/rocketmq-client-csharp/PublishingSettings.cs
index fd442bbe..22423b56 100644
--- a/csharp/rocketmq-client-csharp/PublishingSettings.cs
+++ b/csharp/rocketmq-client-csharp/PublishingSettings.cs
@@ -31,7 +31,7 @@ namespace Org.Apache.Rocketmq
         private volatile int _maxBodySizeBytes = 4 * 1024 * 1024;
         private volatile bool _validateMessageType = true;
 
-        public PublishingSettings(string clientId, Endpoints endpoints, ExponentialBackoffRetryPolicy retryPolicy,
+        public PublishingSettings(string clientId, Endpoints endpoints, IRetryPolicy retryPolicy,
             TimeSpan requestTimeout, ConcurrentDictionary<string, bool> topics) : base(clientId, ClientType.Producer,
             endpoints, retryPolicy, requestTimeout)
         {
diff --git a/csharp/rocketmq-client-csharp/Resource.cs b/csharp/rocketmq-client-csharp/Resource.cs
index 3395a16f..5d339475 100644
--- a/csharp/rocketmq-client-csharp/Resource.cs
+++ b/csharp/rocketmq-client-csharp/Resource.cs
@@ -34,7 +34,7 @@ namespace Org.Apache.Rocketmq
             Name = name;
         }
 
-        public string Namespace { get; }
+        private string Namespace { get; }
         public string Name { get; }
 
         public Proto.Resource ToProtobuf()
@@ -48,7 +48,7 @@ namespace Org.Apache.Rocketmq
 
         public override string ToString()
         {
-            return String.IsNullOrEmpty(Namespace) ? Name : $"{Namespace}.{Name}";
+            return string.IsNullOrEmpty(Namespace) ? Name : $"{Namespace}.{Name}";
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/Settings.cs b/csharp/rocketmq-client-csharp/Settings.cs
index 491aa564..0ee95fb0 100644
--- a/csharp/rocketmq-client-csharp/Settings.cs
+++ b/csharp/rocketmq-client-csharp/Settings.cs
@@ -28,7 +28,7 @@ namespace Org.Apache.Rocketmq
         protected volatile IRetryPolicy RetryPolicy;
         protected readonly TimeSpan RequestTimeout;
 
-        public Settings(string clientId, ClientType clientType, Endpoints endpoints, IRetryPolicy retryPolicy,
+        protected Settings(string clientId, ClientType clientType, Endpoints endpoints, IRetryPolicy retryPolicy,
             TimeSpan requestTimeout)
         {
             ClientId = clientId;
@@ -38,7 +38,7 @@ namespace Org.Apache.Rocketmq
             RequestTimeout = requestTimeout;
         }
 
-        public Settings(string clientId, ClientType clientType, Endpoints endpoints, TimeSpan requestTimeout)
+        protected Settings(string clientId, ClientType clientType, Endpoints endpoints, TimeSpan requestTimeout)
         {
             ClientId = clientId;
             ClientType = clientType;
diff --git a/csharp/rocketmq-client-csharp/Topic.cs b/csharp/rocketmq-client-csharp/Topic.cs
index f1ae453c..ff66b719 100644
--- a/csharp/rocketmq-client-csharp/Topic.cs
+++ b/csharp/rocketmq-client-csharp/Topic.cs
@@ -27,8 +27,8 @@ namespace Org.Apache.Rocketmq
             Name = name;
         }
 
-        public string ResourceNamespace { get; }
-        public string Name { get; }
+        private string ResourceNamespace { get; }
+        private string Name { get; }
 
         public bool Equals(Topic other)
         {
diff --git a/csharp/rocketmq-client-csharp/TopicRouteException.cs b/csharp/rocketmq-client-csharp/TopicRouteException.cs
deleted file mode 100644
index c80e8699..00000000
--- a/csharp/rocketmq-client-csharp/TopicRouteException.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using System;
-namespace Org.Apache.Rocketmq
-{
-    public class TopicRouteException : Exception
-    {
-        public TopicRouteException(string message) : base(message)
-        {
-
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/Transaction.cs b/csharp/rocketmq-client-csharp/Transaction.cs
index 5084ae4e..5a0e81a6 100644
--- a/csharp/rocketmq-client-csharp/Transaction.cs
+++ b/csharp/rocketmq-client-csharp/Transaction.cs
@@ -105,7 +105,7 @@ namespace Org.Apache.Rocketmq
             foreach (var (publishingMessage, sendReceipt) in _messageSendReceiptDict)
             {
                 await _producer.EndTransaction(sendReceipt.Endpoints, publishingMessage.Topic, sendReceipt.MessageId,
-                    sendReceipt.TransactionId, TransactionResolution.COMMIT);
+                    sendReceipt.TransactionId, TransactionResolution.Commit);
             }
         }
 
@@ -124,7 +124,7 @@ namespace Org.Apache.Rocketmq
             foreach (var (publishingMessage, sendReceipt) in _messageSendReceiptDict)
             {
                 await _producer.EndTransaction(sendReceipt.Endpoints, publishingMessage.Topic, sendReceipt.MessageId,
-                    sendReceipt.TransactionId, TransactionResolution.ROLLBACK);
+                    sendReceipt.TransactionId, TransactionResolution.Rollback);
             }
         }
     }
diff --git a/csharp/rocketmq-client-csharp/TransactionResolution.cs b/csharp/rocketmq-client-csharp/TransactionResolution.cs
index 5bb4d5e1..89595570 100644
--- a/csharp/rocketmq-client-csharp/TransactionResolution.cs
+++ b/csharp/rocketmq-client-csharp/TransactionResolution.cs
@@ -19,8 +19,8 @@ namespace Org.Apache.Rocketmq
 {
     public enum TransactionResolution
     {
-        COMMIT,
-        ROLLBACK,
-        UNKNOWN
+        Commit,
+        Rollback,
+        Unknown
     }
 }
\ No newline at end of file
diff --git a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
index 94c2d718..ebbb8487 100644
--- a/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
+++ b/csharp/rocketmq-client-csharp/rocketmq-client-csharp.csproj
@@ -14,7 +14,7 @@
     <Description>.NET Client for Apache RocketMQ</Description>
     <PackageProjectUrl>https://github.com/apache/rocketmq-clients</PackageProjectUrl>
     <RepositoryUrl>https://github.com/apache/rocketmq-clients</RepositoryUrl>
-    <PackageVersion>0.0.6-SNAPSHOT</PackageVersion>
+    <PackageVersion>0.0.8-SNAPSHOT</PackageVersion>
     <PackageIcon>logo.png</PackageIcon>
   </PropertyGroup>
 
diff --git a/csharp/tests/ConfigFileCredentialsProviderTest.cs b/csharp/tests/ConfigFileCredentialsProviderTest.cs
index 0ebea9e3..7874795e 100644
--- a/csharp/tests/ConfigFileCredentialsProviderTest.cs
+++ b/csharp/tests/ConfigFileCredentialsProviderTest.cs
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-using Microsoft.VisualStudio.TestTools.UnitTesting;
 using System.IO;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Org.Apache.Rocketmq;
 
-namespace Org.Apache.Rocketmq
+namespace tests
 {
     [TestClass]
     public class ConfigFileCredentialsProviderTest
@@ -27,14 +28,14 @@ namespace Org.Apache.Rocketmq
         public void Setup()
         {
             var configFilePath = ConfigFileCredentialsProvider.DefaultConfigFilePath();
-            FileInfo fileInfo = new FileInfo(configFilePath);
+            var fileInfo = new FileInfo(configFilePath);
             var dir = fileInfo.Directory;
-            if (!dir.Exists)
+            if (dir != null && !dir.Exists)
             {
                 dir.Create();
             }
 
-            string json = "{\"AccessKey\": \"key\", \"AccessSecret\": \"secret\"}";
+            var json = "{\"AccessKey\": \"key\", \"AccessSecret\": \"secret\"}";
             File.WriteAllText(configFilePath, json);
         }
         
diff --git a/csharp/tests/DateTimeTest.cs b/csharp/tests/DateTimeTest.cs
index 17bbd889..265e09e7 100644
--- a/csharp/tests/DateTimeTest.cs
+++ b/csharp/tests/DateTimeTest.cs
@@ -14,10 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-using Microsoft.VisualStudio.TestTools.UnitTesting;
+
 using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Org.Apache.Rocketmq;
 
-namespace Org.Apache.Rocketmq
+namespace tests
 {
 
     [TestClass]
@@ -25,11 +27,11 @@ namespace Org.Apache.Rocketmq
     {
 
         [TestMethod]
-        public void testFormat()
+        public void TestFormat()
         {
-            DateTime instant = new DateTime(2022, 02, 15, 08, 31, 56);
-            string time = instant.ToString(MetadataConstants.DateTimeFormat);
-            string expected = "20220215T083156Z";
+            var instant = new DateTime(2022, 02, 15, 08, 31, 56);
+            var time = instant.ToString(MetadataConstants.DateTimeFormat);
+            const string expected = "20220215T083156Z";
             Assert.AreEqual(time, expected);
         }
 
diff --git a/csharp/tests/EndpointsTest.cs b/csharp/tests/EndpointsTest.cs
index 6c4a6c71..4c85209e 100644
--- a/csharp/tests/EndpointsTest.cs
+++ b/csharp/tests/EndpointsTest.cs
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-using System;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Org.Apache.Rocketmq;
 
@@ -25,11 +24,19 @@ namespace tests
     public class EndpointsTest
     {
         [TestMethod]
-        public void testConstructor()
+        public void TestGrpcTargetWithoutSsl()
         {
-            Console.WriteLine(Uri.CheckHostName("127.0.0.1"));
-            Console.WriteLine(Uri.CheckHostName("1050:0000:0000:0000:0005:0600:300c:326b"));
-            Console.WriteLine(Uri.CheckHostName("baidu.com"));
+            var endpoints = new Endpoints("127.0.0.1");
+            var targetWithoutSsl = endpoints.GrpcTarget(false);
+            Assert.AreEqual("http://127.0.0.1:80", targetWithoutSsl);
+        }
+
+        [TestMethod]
+        public void TestGrpcTargetWithSsl()
+        {
+            var endpoints = new Endpoints("127.0.0.1");
+            var targetWithoutSsl = endpoints.GrpcTarget(true);
+            Assert.AreEqual("https://127.0.0.1:80", targetWithoutSsl);
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/tests/MessageTest.cs b/csharp/tests/MessageTest.cs
index 7b28a6da..d8191d28 100644
--- a/csharp/tests/MessageTest.cs
+++ b/csharp/tests/MessageTest.cs
@@ -17,10 +17,11 @@
 
 using System;
 using System.Collections.Generic;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
 using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Org.Apache.Rocketmq;
 
-namespace Org.Apache.Rocketmq
+namespace tests
 {
     [TestClass]
     public class MessageTest
@@ -146,5 +147,22 @@ namespace Org.Apache.Rocketmq
         {
             new Message.Builder().SetKeys("a", "b");
         }
+
+        [TestMethod]
+        [ExpectedException(typeof(ArgumentException))]
+        public void TestSetDeliveryTimestampAndMessageGroup()
+        {
+            new Message.Builder().SetDeliveryTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(30))
+                .SetMessageGroup("messageGroup").Build();
+        }
+
+        [TestMethod]
+        [ExpectedException(typeof(ArgumentException))]
+        public void TestSetMessageGroupAndDeliveryTimestamp()
+        {
+            new Message.Builder().SetMessageGroup("messageGroup")
+                .SetDeliveryTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(30))
+                .Build();
+        }
     }
 }
\ No newline at end of file
diff --git a/csharp/tests/MqLogManagerTest.cs b/csharp/tests/MqLogManagerTest.cs
index 8a0e2c2a..076c9331 100644
--- a/csharp/tests/MqLogManagerTest.cs
+++ b/csharp/tests/MqLogManagerTest.cs
@@ -14,6 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using NLog;
diff --git a/csharp/tests/PublishingMessageTest.cs b/csharp/tests/PublishingMessageTest.cs
new file mode 100644
index 00000000..9f4938c0
--- /dev/null
+++ b/csharp/tests/PublishingMessageTest.cs
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Concurrent;
+using System.Text;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Org.Apache.Rocketmq;
+
+namespace tests
+{
+    [TestClass]
+    public class PublishingMessageTest
+    {
+        private const string ClientId = "fakeClientId";
+        private static readonly Endpoints Endpoints = new("127.0.0.1:8081");
+
+
+        [TestMethod]
+        public void TestNormalMessage()
+        {
+            const string topic = "yourNormalTopic";
+            var message = new Message.Builder().SetTopic(topic).SetBody(Encoding.UTF8.GetBytes("foobar")).Build();
+            var topics = new ConcurrentDictionary<string, bool>
+            {
+                [topic] = true
+            };
+            var settings = new PublishingSettings(ClientId, Endpoints,
+                ExponentialBackoffRetryPolicy.ImmediatelyRetryPolicy(3), TimeSpan.FromSeconds(3), topics);
+            var publishingMessage = new PublishingMessage(message, settings, false);
+            Assert.AreEqual(publishingMessage.MessageType, MessageType.Normal);
+        }
+
+        [TestMethod]
+        public void TestFifoMessage()
+        {
+            const string topic = "yourFifoTopic";
+            const string messageGroup = "yourMessageGroup";
+            var message = new Message.Builder().SetTopic(topic)
+                .SetMessageGroup(messageGroup).SetBody(Encoding.UTF8.GetBytes("foobar"))
+                .Build();
+            var topics = new ConcurrentDictionary<string, bool>
+            {
+                [topic] = true
+            };
+            var settings = new PublishingSettings(ClientId, Endpoints,
+                ExponentialBackoffRetryPolicy.ImmediatelyRetryPolicy(3), TimeSpan.FromSeconds(3), topics);
+            var publishingMessage = new PublishingMessage(message, settings, false);
+            Assert.AreEqual(publishingMessage.MessageType, MessageType.Fifo);
+        }
+
+        [TestMethod]
+        public void TestDelayMessage()
+        {
+            const string topic = "yourDelayTopic";
+            var message = new Message.Builder()
+                .SetTopic(topic)
+                .SetDeliveryTimestamp(DateTime.UtcNow + TimeSpan.FromSeconds(30))
+                .SetBody(Encoding.UTF8.GetBytes("foobar")).Build();
+            var topics = new ConcurrentDictionary<string, bool>
+            {
+                [topic] = true
+            };
+            var settings = new PublishingSettings(ClientId, Endpoints,
+                ExponentialBackoffRetryPolicy.ImmediatelyRetryPolicy(3),
+                TimeSpan.FromSeconds(3), topics);
+            var publishingMessage = new PublishingMessage(message, settings, false);
+            Assert.AreEqual(publishingMessage.MessageType, MessageType.Delay);
+        }
+
+        [TestMethod]
+        public void TestTransactionMessage()
+        {
+            const string topic = "yourTransactionMessage";
+            var message = new Message.Builder()
+                .SetTopic(topic)
+                .SetBody(Encoding.UTF8.GetBytes("foobar")).Build();
+            var topics = new ConcurrentDictionary<string, bool>
+            {
+                [topic] = true
+            };
+            var settings = new PublishingSettings(ClientId, Endpoints,
+                ExponentialBackoffRetryPolicy.ImmediatelyRetryPolicy(3),
+                TimeSpan.FromSeconds(3), topics);
+            var publishingMessage = new PublishingMessage(message, settings, true);
+            Assert.AreEqual(publishingMessage.MessageType, MessageType.Transaction);
+        }
+    }
+}
\ No newline at end of file
diff --git a/csharp/tests/SendResultTest.cs b/csharp/tests/SendResultTest.cs
deleted file mode 100644
index 262410da..00000000
--- a/csharp/tests/SendResultTest.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace Org.Apache.Rocketmq
-{
-    [TestClass]
-    public class SendResultTest
-    {
-        [TestMethod]
-        public void testCtor()
-        {
-            // string messageId = new string("abc");
-            // var sendResult = new SendReceipt(messageId);
-            // Assert.AreEqual(messageId, sendResult.MessageId);
-        }
-    }
-}
\ No newline at end of file
diff --git a/csharp/tests/SignatureTest.cs b/csharp/tests/SignatureTest.cs
deleted file mode 100644
index 63b7cdf8..00000000
--- a/csharp/tests/SignatureTest.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using grpc = Grpc.Core;
-using Moq;
-using Org.Apache.Rocketmq;
-
-namespace tests
-{
-
-    [TestClass]
-    public class SignatureTest
-    {
-
-        [TestMethod]
-        public void TestSign()
-        {
-            // var mock = new Mock<IClientConfig>();
-            //
-            // string accessKey = "key";
-            // string accessSecret = "secret";
-            // var credentialsProvider = new StaticCredentialsProvider(accessKey, accessSecret);
-            //
-            // var metadata = new grpc::Metadata();
-            // Signature.Sign(mock.Object, metadata);
-            // Assert.IsNotNull(metadata.Get(MetadataConstants.Authorization));
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/csharp/tests/TopicTest.cs b/csharp/tests/TopicTest.cs
deleted file mode 100644
index 9f386dea..00000000
--- a/csharp/tests/TopicTest.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Collections.Generic;
-
-namespace Org.Apache.Rocketmq
-{
-
-    [TestClass]
-    public class TopicTest
-    {
-
-        [TestMethod]
-        public void testCompareTo()
-        {
-            List<Topic> topics = new List<Topic>();
-            topics.Add(new Topic("ns1", "t1"));
-            topics.Add(new Topic("ns0", "t1"));
-            topics.Add(new Topic("ns0", "t0"));
-
-            topics.Sort();
-
-            Assert.AreEqual(topics[0].ResourceNamespace, "ns0");
-            Assert.AreEqual(topics[0].Name, "t0");
-
-            Assert.AreEqual(topics[1].ResourceNamespace, "ns0");
-            Assert.AreEqual(topics[1].Name, "t1");
-
-
-            Assert.AreEqual(topics[2].ResourceNamespace, "ns1");
-            Assert.AreEqual(topics[2].Name, "t1");
-
-        }
-
-
-    }
-}
\ No newline at end of file
diff --git a/csharp/tests/UnitTest1.cs b/csharp/tests/UnitTest1.cs
deleted file mode 100644
index 2f6b468a..00000000
--- a/csharp/tests/UnitTest1.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Proto = Apache.Rocketmq.V2;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-
-namespace tests
-{
-    [TestClass]
-    public class UnitTest1
-    {
-        [TestMethod]
-        public void TestMethod1()
-        {
-            Proto::Permission perm = Proto::Permission.None;
-            switch (perm)
-            {
-                case Proto::Permission.None:
-                {
-                    Console.WriteLine("None");
-                    break;
-                }
-
-                case Proto::Permission.Read:
-                {
-                    Console.WriteLine("Read");
-                    break;
-                }
-
-                case Proto::Permission.Write:
-                {
-                    Console.WriteLine("Write");
-                    break;
-                }
-
-                case Proto::Permission.ReadWrite:
-                {
-                    Console.WriteLine("ReadWrite");
-                    break;
-                }
-            }
-        }
-
-        [TestMethod]
-        public void TestConcurrentDictionary()
-        {
-            var dict = new ConcurrentDictionary<string, List<String>>();
-            string s = "abc";
-            List<String> result;
-            var exists = dict.TryGetValue(s, out result);
-            Assert.IsFalse(exists);
-            Assert.IsNull(result);
-
-            result = new List<string>();
-            result.Add("abc");
-            Assert.IsTrue(dict.TryAdd(s, result));
-
-            List<String> list;
-            exists = dict.TryGetValue(s, out list);
-            Assert.IsTrue(exists);
-            Assert.IsNotNull(list);
-            Assert.AreEqual(1, list.Count);
-        }
-    }
-}
\ No newline at end of file
diff --git a/csharp/tests/tests.csproj b/csharp/tests/tests.csproj
index 578fe4e2..358b4a12 100644
--- a/csharp/tests/tests.csproj
+++ b/csharp/tests/tests.csproj
@@ -14,8 +14,8 @@
     <PackageReference Include="coverlet.collector" Version="3.0.2" />
   </ItemGroup>
 
-  <ItemGroup>
-    <ProjectReference Include="..\rocketmq-client-csharp\rocketmq-client-csharp.csproj" />
+  <ItemGroup>
+    <ProjectReference Include="..\rocketmq-client-csharp\rocketmq-client-csharp.csproj" />
   </ItemGroup>
 
 </Project>