diff --git a/CAP.sln b/CAP.sln
index a1de23c..8f4620b 100644
--- a/CAP.sln
+++ b/CAP.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.29025.244
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31919.166
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9B2AE124-6636-4DE9-83A3-70360DABD0C4}"
EndProject
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 44c3dd8..3efd601 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -26,7 +26,6 @@
-
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.AmazonSQS/AmazonPolicyExtensions.cs b/src/DotNetCore.CAP.AmazonSQS/AmazonPolicyExtensions.cs
index d3af025..1f9c652 100644
--- a/src/DotNetCore.CAP.AmazonSQS/AmazonPolicyExtensions.cs
+++ b/src/DotNetCore.CAP.AmazonSQS/AmazonPolicyExtensions.cs
@@ -209,7 +209,7 @@ namespace DotNetCore.CAP.AmazonSQS
///
/// Source ARN
/// Group prefix or null if group not present
- private static string GetArnGroupPrefix(string arn)
+ private static string? GetArnGroupPrefix(string arn)
{
const char separator = '-';
if (string.IsNullOrEmpty(arn) || !arn.Contains(separator))
@@ -235,7 +235,7 @@ namespace DotNetCore.CAP.AmazonSQS
///
/// Source ARN
/// Group name or null if group not present
- private static string GetGroupName(string arn)
+ private static string? GetGroupName(string arn)
{
const char separator = ':';
if (string.IsNullOrEmpty(arn) || !arn.Contains(separator))
diff --git a/src/DotNetCore.CAP.AmazonSQS/AmazonSQSConsumerClient.cs b/src/DotNetCore.CAP.AmazonSQS/AmazonSQSConsumerClient.cs
index 9c1a463..01dca36 100644
--- a/src/DotNetCore.CAP.AmazonSQS/AmazonSQSConsumerClient.cs
+++ b/src/DotNetCore.CAP.AmazonSQS/AmazonSQSConsumerClient.cs
@@ -27,8 +27,8 @@ namespace DotNetCore.CAP.AmazonSQS
private readonly string _groupId;
private readonly AmazonSQSOptions _amazonSQSOptions;
- private IAmazonSimpleNotificationService _snsClient;
- private IAmazonSQS _sqsClient;
+ private IAmazonSimpleNotificationService? _snsClient;
+ private IAmazonSQS? _sqsClient;
private string _queueUrl = string.Empty;
public AmazonSQSConsumerClient(string groupId, IOptions options)
@@ -37,9 +37,9 @@ namespace DotNetCore.CAP.AmazonSQS
_amazonSQSOptions = options.Value;
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
public BrokerAddress BrokerAddress => new BrokerAddress("AmazonSQS", _queueUrl);
@@ -57,7 +57,7 @@ namespace DotNetCore.CAP.AmazonSQS
{
var createTopicRequest = new CreateTopicRequest(topic.NormalizeForAws());
- var createTopicResponse = _snsClient.CreateTopicAsync(createTopicRequest).GetAwaiter().GetResult();
+ var createTopicResponse = _snsClient!.CreateTopicAsync(createTopicRequest).GetAwaiter().GetResult();
topicArns.Add(createTopicResponse.TopicArn);
}
@@ -92,13 +92,13 @@ namespace DotNetCore.CAP.AmazonSQS
while (true)
{
- var response = _sqsClient.ReceiveMessageAsync(request, cancellationToken).GetAwaiter().GetResult();
+ var response = _sqsClient!.ReceiveMessageAsync(request, cancellationToken).GetAwaiter().GetResult();
if (response.Messages.Count == 1)
{
var messageObj = JsonSerializer.Deserialize(response.Messages[0].Body);
- var header = messageObj.MessageAttributes.ToDictionary(x => x.Key, x => x.Value.Value);
+ var header = messageObj!.MessageAttributes.ToDictionary(x => x.Key, x => x.Value.Value);
var body = messageObj.Message;
var message = new TransportMessage(header, body != null ? Encoding.UTF8.GetBytes(body) : null);
@@ -119,7 +119,7 @@ namespace DotNetCore.CAP.AmazonSQS
{
try
{
- _ = _sqsClient.DeleteMessageAsync(_queueUrl, (string)sender).GetAwaiter().GetResult();
+ _ = _sqsClient!.DeleteMessageAsync(_queueUrl, (string)sender).GetAwaiter().GetResult();
}
catch (InvalidIdFormatException ex)
{
@@ -127,12 +127,12 @@ namespace DotNetCore.CAP.AmazonSQS
}
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
try
{
// Visible again in 3 seconds
- _ = _sqsClient.ChangeMessageVisibilityAsync(_queueUrl, (string)sender, 3).GetAwaiter().GetResult();
+ _ = _sqsClient!.ChangeMessageVisibilityAsync(_queueUrl, (string)sender!, 3).GetAwaiter().GetResult();
}
catch (MessageNotInflightException ex)
{
@@ -237,7 +237,7 @@ namespace DotNetCore.CAP.AmazonSQS
{
Connect(initSNS: false, initSQS: true);
- var queueAttributes = await _sqsClient.GetAttributesAsync(_queueUrl).ConfigureAwait(false);
+ var queueAttributes = await _sqsClient!.GetAttributesAsync(_queueUrl).ConfigureAwait(false);
var sqsQueueArn = queueAttributes["QueueArn"];
@@ -263,12 +263,12 @@ namespace DotNetCore.CAP.AmazonSQS
private async Task SubscribeToTopics(IEnumerable topics)
{
- var queueAttributes = await _sqsClient.GetAttributesAsync(_queueUrl).ConfigureAwait(false);
+ var queueAttributes = await _sqsClient!.GetAttributesAsync(_queueUrl).ConfigureAwait(false);
var sqsQueueArn = queueAttributes["QueueArn"];
foreach (var topicArn in topics)
{
- await _snsClient.SubscribeAsync(new SubscribeRequest
+ await _snsClient!.SubscribeAsync(new SubscribeRequest
{
TopicArn = topicArn,
Protocol = "sqs",
diff --git a/src/DotNetCore.CAP.AmazonSQS/CAP.AmazonSQSOptions.cs b/src/DotNetCore.CAP.AmazonSQS/CAP.AmazonSQSOptions.cs
index f8dcfd5..4fdf3f2 100644
--- a/src/DotNetCore.CAP.AmazonSQS/CAP.AmazonSQSOptions.cs
+++ b/src/DotNetCore.CAP.AmazonSQS/CAP.AmazonSQSOptions.cs
@@ -10,19 +10,19 @@ namespace DotNetCore.CAP
// ReSharper disable once InconsistentNaming
public class AmazonSQSOptions
{
- public RegionEndpoint Region { get; set; }
+ public RegionEndpoint Region { get; set; } = default!;
- public AWSCredentials Credentials { get; set; }
+ public AWSCredentials? Credentials { get; set; }
///
/// Overrides Service Url deduced from AWS Region. To use in local development environments like localstack.
///
- public string SNSServiceUrl { get; set; }
+ public string? SNSServiceUrl { get; set; }
///
/// Overrides Service Url deduced from AWS Region. To use in local development environments like localstack.
///
- public string SQSServiceUrl { get; set; }
+ public string? SQSServiceUrl { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.AmazonSQS/DotNetCore.CAP.AmazonSQS.csproj b/src/DotNetCore.CAP.AmazonSQS/DotNetCore.CAP.AmazonSQS.csproj
index 6518763..9cd09e5 100644
--- a/src/DotNetCore.CAP.AmazonSQS/DotNetCore.CAP.AmazonSQS.csproj
+++ b/src/DotNetCore.CAP.AmazonSQS/DotNetCore.CAP.AmazonSQS.csproj
@@ -2,12 +2,12 @@
netstandard2.1
- DotNetCore.CAP.AmazonSQS
+ enable
$(PackageTags);AmazonSQS;SQS
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.AmazonSQS.xml
+ true
1701;1702;1705;CS1591
diff --git a/src/DotNetCore.CAP.AmazonSQS/ITransport.AmazonSQS.cs b/src/DotNetCore.CAP.AmazonSQS/ITransport.AmazonSQS.cs
index 44c8583..0bbb8b9 100644
--- a/src/DotNetCore.CAP.AmazonSQS/ITransport.AmazonSQS.cs
+++ b/src/DotNetCore.CAP.AmazonSQS/ITransport.AmazonSQS.cs
@@ -22,8 +22,8 @@ namespace DotNetCore.CAP.AmazonSQS
private readonly ILogger _logger;
private readonly IOptions _sqsOptions;
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
- private IAmazonSimpleNotificationService _snsClient;
- private IDictionary _topicArnMaps;
+ private IAmazonSimpleNotificationService? _snsClient;
+ private IDictionary? _topicArnMaps;
public AmazonSQSTransport(ILogger logger, IOptions sqsOptions)
{
@@ -41,7 +41,7 @@ namespace DotNetCore.CAP.AmazonSQS
if (TryGetOrCreateTopicArn(message.GetName().NormalizeForAws(), out var arn))
{
- string bodyJson = null;
+ string? bodyJson = null;
if (message.Body != null)
{
bodyJson = Encoding.UTF8.GetString(message.Body);
@@ -59,7 +59,7 @@ namespace DotNetCore.CAP.AmazonSQS
MessageAttributes = attributes
};
- await _snsClient.PublishAsync(request);
+ await _snsClient!.PublishAsync(request);
_logger.LogDebug($"SNS topic message [{message.GetName().NormalizeForAws()}] has been published.");
return OperateResult.Success;
@@ -117,7 +117,7 @@ namespace DotNetCore.CAP.AmazonSQS
{
_topicArnMaps = new Dictionary();
- string nextToken = null;
+ string? nextToken = null;
do
{
var topics = nextToken == null
@@ -143,15 +143,15 @@ namespace DotNetCore.CAP.AmazonSQS
}
}
- private bool TryGetOrCreateTopicArn(string topicName, out string topicArn)
+ private bool TryGetOrCreateTopicArn(string topicName,[System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out string? topicArn)
{
topicArn = null;
- if (_topicArnMaps.TryGetValue(topicName, out topicArn))
+ if (_topicArnMaps!.TryGetValue(topicName, out topicArn))
{
return true;
}
- var response = _snsClient.CreateTopicAsync(topicName).GetAwaiter().GetResult();
+ var response = _snsClient!.CreateTopicAsync(topicName).GetAwaiter().GetResult();
if (string.IsNullOrEmpty(response.TopicArn))
{
diff --git a/src/DotNetCore.CAP.AmazonSQS/SQSReceivedMessage.cs b/src/DotNetCore.CAP.AmazonSQS/SQSReceivedMessage.cs
index 893b418..53fcd64 100644
--- a/src/DotNetCore.CAP.AmazonSQS/SQSReceivedMessage.cs
+++ b/src/DotNetCore.CAP.AmazonSQS/SQSReceivedMessage.cs
@@ -4,15 +4,15 @@ namespace DotNetCore.CAP.AmazonSQS
{
class SQSReceivedMessage
{
- public string Message { get; set; }
+ public string? Message { get; set; }
- public Dictionary MessageAttributes { get; set; }
+ public Dictionary MessageAttributes { get; set; } = default!;
}
class SQSReceivedMessageAttributes
{
- public string Type { get; set; }
+ public string? Type { get; set; }
- public string Value { get; set; }
+ public string? Value { get; set; }
}
}
diff --git a/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerClient.cs b/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerClient.cs
index ee5d84b..cfd1c3d 100644
--- a/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerClient.cs
+++ b/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerClient.cs
@@ -24,7 +24,7 @@ namespace DotNetCore.CAP.AzureServiceBus
private readonly string _subscriptionName;
private readonly AzureServiceBusOptions _asbOptions;
- private SubscriptionClient _consumerClient;
+ private SubscriptionClient? _consumerClient;
public AzureServiceBusConsumerClient(
ILogger logger,
@@ -36,11 +36,11 @@ namespace DotNetCore.CAP.AzureServiceBus
_asbOptions = options.Value ?? throw new ArgumentNullException(nameof(options));
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("AzureServiceBus", _asbOptions.ConnectionString);
+ public BrokerAddress BrokerAddress => new ("AzureServiceBus", _asbOptions.ConnectionString);
public void Subscribe(IEnumerable topics)
{
@@ -51,7 +51,7 @@ namespace DotNetCore.CAP.AzureServiceBus
ConnectAsync().GetAwaiter().GetResult();
- var allRuleNames = _consumerClient.GetRulesAsync().GetAwaiter().GetResult().Select(x => x.Name);
+ var allRuleNames = _consumerClient!.GetRulesAsync().GetAwaiter().GetResult().Select(x => x.Name);
foreach (var newRule in topics.Except(allRuleNames))
{
@@ -80,7 +80,7 @@ namespace DotNetCore.CAP.AzureServiceBus
if (_asbOptions.EnableSessions)
{
- _consumerClient.RegisterSessionHandler(OnConsumerReceivedWithSession,
+ _consumerClient!.RegisterSessionHandler(OnConsumerReceivedWithSession,
new SessionHandlerOptions(OnExceptionReceived)
{
AutoComplete = false,
@@ -89,7 +89,7 @@ namespace DotNetCore.CAP.AzureServiceBus
}
else
{
- _consumerClient.RegisterMessageHandler(OnConsumerReceived,
+ _consumerClient!.RegisterMessageHandler(OnConsumerReceived,
new MessageHandlerOptions(OnExceptionReceived)
{
AutoComplete = false,
@@ -111,15 +111,15 @@ namespace DotNetCore.CAP.AzureServiceBus
var commitInput = (AzureServiceBusConsumerCommitInput) sender;
if (_asbOptions.EnableSessions)
{
- commitInput.Session.CompleteAsync(commitInput.LockToken);
+ commitInput.Session?.CompleteAsync(commitInput.LockToken);
}
else
{
- _consumerClient.CompleteAsync(commitInput.LockToken);
+ _consumerClient!.CompleteAsync(commitInput.LockToken);
}
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
// ignore
}
diff --git a/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerCommitInput.cs b/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerCommitInput.cs
index c76a360..290eda1 100644
--- a/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerCommitInput.cs
+++ b/src/DotNetCore.CAP.AzureServiceBus/AzureServiceBusConsumerCommitInput.cs
@@ -4,13 +4,13 @@ namespace DotNetCore.CAP.AzureServiceBus
{
public class AzureServiceBusConsumerCommitInput
{
- public AzureServiceBusConsumerCommitInput(string lockToken, IMessageSession session = null)
+ public AzureServiceBusConsumerCommitInput(string lockToken, IMessageSession? session = null)
{
LockToken = lockToken;
Session = session;
}
- public IMessageSession Session { get; set; }
+ public IMessageSession? Session { get; set; }
public string LockToken { get; set; }
}
}
diff --git a/src/DotNetCore.CAP.AzureServiceBus/CAP.AzureServiceBusOptions.cs b/src/DotNetCore.CAP.AzureServiceBus/CAP.AzureServiceBusOptions.cs
index 61c6d63..050bb99 100644
--- a/src/DotNetCore.CAP.AzureServiceBus/CAP.AzureServiceBusOptions.cs
+++ b/src/DotNetCore.CAP.AzureServiceBus/CAP.AzureServiceBusOptions.cs
@@ -20,7 +20,7 @@ namespace DotNetCore.CAP
///
/// Azure Service Bus Namespace connection string. Must not contain topic information.
///
- public string ConnectionString { get; set; }
+ public string ConnectionString { get; set; } = default!;
///
/// Whether Service Bus sessions are enabled. If enabled, all messages must contain a
@@ -36,6 +36,6 @@ namespace DotNetCore.CAP
///
/// Represents the Azure Active Directory token provider for Azure Managed Service Identity integration.
///
- public ITokenProvider ManagementTokenProvider { get; set; }
+ public ITokenProvider? ManagementTokenProvider { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.AzureServiceBus/DotNetCore.CAP.AzureServiceBus.csproj b/src/DotNetCore.CAP.AzureServiceBus/DotNetCore.CAP.AzureServiceBus.csproj
index 31abcb6..04bbecd 100644
--- a/src/DotNetCore.CAP.AzureServiceBus/DotNetCore.CAP.AzureServiceBus.csproj
+++ b/src/DotNetCore.CAP.AzureServiceBus/DotNetCore.CAP.AzureServiceBus.csproj
@@ -2,7 +2,7 @@
netstandard2.1
- DotNetCore.CAP.AzureServiceBus
+ enable
$(PackageTags);AzureServiceBus
diff --git a/src/DotNetCore.CAP.AzureServiceBus/ITransport.AzureServiceBus.cs b/src/DotNetCore.CAP.AzureServiceBus/ITransport.AzureServiceBus.cs
index 3038c5d..a32d019 100644
--- a/src/DotNetCore.CAP.AzureServiceBus/ITransport.AzureServiceBus.cs
+++ b/src/DotNetCore.CAP.AzureServiceBus/ITransport.AzureServiceBus.cs
@@ -20,7 +20,7 @@ namespace DotNetCore.CAP.AzureServiceBus
private readonly ILogger _logger;
private readonly IOptions _asbOptions;
- private ITopicClient _topicClient;
+ private ITopicClient? _topicClient;
public AzureServiceBusTransport(
ILogger logger,
@@ -57,7 +57,7 @@ namespace DotNetCore.CAP.AzureServiceBus
message.UserProperties.Add(header.Key, header.Value);
}
- await _topicClient.SendAsync(message);
+ await _topicClient!.SendAsync(message);
_logger.LogDebug($"Azure Service Bus message [{transportMessage.GetName()}] has been published.");
diff --git a/src/DotNetCore.CAP.InMemoryStorage/DotNetCore.CAP.InMemoryStorage.csproj b/src/DotNetCore.CAP.InMemoryStorage/DotNetCore.CAP.InMemoryStorage.csproj
index 45b69b8..b404dad 100644
--- a/src/DotNetCore.CAP.InMemoryStorage/DotNetCore.CAP.InMemoryStorage.csproj
+++ b/src/DotNetCore.CAP.InMemoryStorage/DotNetCore.CAP.InMemoryStorage.csproj
@@ -2,7 +2,7 @@
netstandard2.1
- DotNetCore.CAP.InMemoryStorage
+ enable
$(PackageTags);InMemory
diff --git a/src/DotNetCore.CAP.InMemoryStorage/IDataStorage.InMemory.cs b/src/DotNetCore.CAP.InMemoryStorage/IDataStorage.InMemory.cs
index a27821c..975bc38 100644
--- a/src/DotNetCore.CAP.InMemoryStorage/IDataStorage.InMemory.cs
+++ b/src/DotNetCore.CAP.InMemoryStorage/IDataStorage.InMemory.cs
@@ -26,9 +26,9 @@ namespace DotNetCore.CAP.InMemoryStorage
_serializer = serializer;
}
- public static Dictionary PublishedMessages { get; } = new Dictionary();
+ public static Dictionary PublishedMessages { get; } = new();
- public static Dictionary ReceivedMessages { get; } = new Dictionary();
+ public static Dictionary ReceivedMessages { get; } = new();
public Task ChangePublishStateAsync(MediumMessage message, StatusName state)
{
@@ -46,7 +46,7 @@ namespace DotNetCore.CAP.InMemoryStorage
return Task.CompletedTask;
}
- public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
+ public MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null)
{
var message = new MediumMessage
{
@@ -85,7 +85,7 @@ namespace DotNetCore.CAP.InMemoryStorage
{
DbId = id,
Group = group,
- Origin = null,
+ Origin = null!,
Name = name,
Content = content,
Retries = _capOptions.Value.FailedRetryCount,
@@ -186,7 +186,7 @@ namespace DotNetCore.CAP.InMemoryStorage
foreach (var message in result)
{
- message.Origin = _serializer.Deserialize(message.Content);
+ message.Origin = _serializer.Deserialize(message.Content)!;
}
return Task.FromResult(result);
@@ -208,7 +208,7 @@ namespace DotNetCore.CAP.InMemoryStorage
foreach (var message in result)
{
- message.Origin = _serializer.Deserialize(message.Content);
+ message.Origin = _serializer.Deserialize(message.Content)!;
}
return Task.FromResult(result);
diff --git a/src/DotNetCore.CAP.InMemoryStorage/IMonitoringApi.InMemory.cs b/src/DotNetCore.CAP.InMemoryStorage/IMonitoringApi.InMemory.cs
index eae2cbd..2dcb4cb 100644
--- a/src/DotNetCore.CAP.InMemoryStorage/IMonitoringApi.InMemory.cs
+++ b/src/DotNetCore.CAP.InMemoryStorage/IMonitoringApi.InMemory.cs
@@ -15,14 +15,14 @@ namespace DotNetCore.CAP.InMemoryStorage
{
internal class InMemoryMonitoringApi : IMonitoringApi
{
- public Task GetPublishedMessageAsync(long id)
+ public Task GetPublishedMessageAsync(long id)
{
- return Task.FromResult((MediumMessage)InMemoryStorage.PublishedMessages.Values.FirstOrDefault(x => x.DbId == id.ToString(CultureInfo.InvariantCulture)));
+ return Task.FromResult(InMemoryStorage.PublishedMessages.Values.FirstOrDefault(x => x.DbId == id.ToString(CultureInfo.InvariantCulture)));
}
- public Task GetReceivedMessageAsync(long id)
+ public Task GetReceivedMessageAsync(long id)
{
- return Task.FromResult((MediumMessage)InMemoryStorage.ReceivedMessages.Values.FirstOrDefault(x => x.DbId == id.ToString(CultureInfo.InvariantCulture)));
+ return Task.FromResult(InMemoryStorage.ReceivedMessages.Values.FirstOrDefault(x => x.DbId == id.ToString(CultureInfo.InvariantCulture)));
}
public StatisticsDto GetStatistics()
diff --git a/src/DotNetCore.CAP.InMemoryStorage/MemoryMessage.cs b/src/DotNetCore.CAP.InMemoryStorage/MemoryMessage.cs
index 53bb070..2b53c91 100644
--- a/src/DotNetCore.CAP.InMemoryStorage/MemoryMessage.cs
+++ b/src/DotNetCore.CAP.InMemoryStorage/MemoryMessage.cs
@@ -8,10 +8,10 @@ namespace DotNetCore.CAP.InMemoryStorage
{
internal class MemoryMessage : MediumMessage
{
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
public StatusName StatusName { get; set; }
- public string Group { get; set; }
+ public string Group { get; set; } = default!;
}
}
diff --git a/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs b/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs
index 0faa14f..5ef9c30 100644
--- a/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs
+++ b/src/DotNetCore.CAP.Kafka/CAP.KafkaOptions.cs
@@ -37,11 +37,11 @@ namespace DotNetCore.CAP
/// Initial list of brokers as a CSV list of broker host or host:port.
///
///
- public string Servers { get; set; }
+ public string Servers { get; set; } = default!;
///
/// If you need to get offset and partition and so on.., you can use this function to write additional header into
///
- public Func, List>> CustomHeaders { get; set; }
+ public Func, List>>? CustomHeaders { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.Kafka/DotNetCore.CAP.Kafka.csproj b/src/DotNetCore.CAP.Kafka/DotNetCore.CAP.Kafka.csproj
index ad5c623..5564064 100644
--- a/src/DotNetCore.CAP.Kafka/DotNetCore.CAP.Kafka.csproj
+++ b/src/DotNetCore.CAP.Kafka/DotNetCore.CAP.Kafka.csproj
@@ -2,14 +2,13 @@
netstandard2.1
- DotNetCore.CAP.Kafka
+ enable
$(PackageTags);Kafka
NU1605;NU1701
NU1701;CS1591
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.Kafka.xml
diff --git a/src/DotNetCore.CAP.Kafka/ITransport.Kafka.cs b/src/DotNetCore.CAP.Kafka/ITransport.Kafka.cs
index 5484193..c4af49a 100644
--- a/src/DotNetCore.CAP.Kafka/ITransport.Kafka.cs
+++ b/src/DotNetCore.CAP.Kafka/ITransport.Kafka.cs
@@ -43,8 +43,8 @@ namespace DotNetCore.CAP.Kafka
var result = await producer.ProduceAsync(message.GetName(), new Message
{
Headers = headers,
- Key = message.Headers.TryGetValue(KafkaHeaders.KafkaKey, out string kafkaMessageKey) && !string.IsNullOrEmpty(kafkaMessageKey) ? kafkaMessageKey : message.GetId(),
- Value = message.Body
+ Key = message.Headers.TryGetValue(KafkaHeaders.KafkaKey, out string? kafkaMessageKey) && !string.IsNullOrEmpty(kafkaMessageKey) ? kafkaMessageKey : message.GetId(),
+ Value = message.Body!
});
if (result.Status == PersistenceStatus.Persisted || result.Status == PersistenceStatus.PossiblyPersisted)
diff --git a/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs b/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs
index ed235c8..98901bd 100644
--- a/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs
+++ b/src/DotNetCore.CAP.Kafka/KafkaConsumerClient.cs
@@ -21,7 +21,7 @@ namespace DotNetCore.CAP.Kafka
private readonly string _groupId;
private readonly KafkaOptions _kafkaOptions;
- private IConsumer _consumerClient;
+ private IConsumer? _consumerClient;
public KafkaConsumerClient(string groupId, IOptions options)
{
@@ -29,11 +29,11 @@ namespace DotNetCore.CAP.Kafka
_kafkaOptions = options.Value ?? throw new ArgumentNullException(nameof(options));
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("Kafka", _kafkaOptions.Servers);
+ public BrokerAddress BrokerAddress => new ("Kafka", _kafkaOptions.Servers);
public ICollection FetchTopics(IEnumerable topicNames)
{
@@ -80,7 +80,7 @@ namespace DotNetCore.CAP.Kafka
Connect();
- _consumerClient.Subscribe(topics);
+ _consumerClient!.Subscribe(topics);
}
public void Listening(TimeSpan timeout, CancellationToken cancellationToken)
@@ -89,11 +89,11 @@ namespace DotNetCore.CAP.Kafka
while (true)
{
- var consumerResult = _consumerClient.Consume(cancellationToken);
+ var consumerResult = _consumerClient!.Consume(cancellationToken);
if (consumerResult.IsPartitionEOF || consumerResult.Message.Value == null) continue;
- var headers = new Dictionary(consumerResult.Message.Headers.Count);
+ var headers = new Dictionary(consumerResult.Message.Headers.Count);
foreach (var header in consumerResult.Message.Headers)
{
var val = header.GetValueBytes();
@@ -106,7 +106,7 @@ namespace DotNetCore.CAP.Kafka
var customHeaders = _kafkaOptions.CustomHeaders(consumerResult);
foreach (var customHeader in customHeaders)
{
- headers.Add(customHeader.Key, customHeader.Value);
+ headers[customHeader.Key] = customHeader.Value;
}
}
@@ -119,12 +119,12 @@ namespace DotNetCore.CAP.Kafka
public void Commit(object sender)
{
- _consumerClient.Commit((ConsumeResult)sender);
+ _consumerClient!.Commit((ConsumeResult)sender);
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
- _consumerClient.Assign(_consumerClient.Assignment);
+ _consumerClient!.Assign(_consumerClient.Assignment);
}
public void Dispose()
@@ -177,6 +177,6 @@ namespace DotNetCore.CAP.Kafka
Reason = $"An error occurred during connect kafka --> {e.Reason}"
};
OnLog?.Invoke(null, logArgs);
- }
+ }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.MongoDB/CAP.MongoDBCapOptionsExtension.cs b/src/DotNetCore.CAP.MongoDB/CAP.MongoDBCapOptionsExtension.cs
index ff9d24b..e6578b1 100644
--- a/src/DotNetCore.CAP.MongoDB/CAP.MongoDBCapOptionsExtension.cs
+++ b/src/DotNetCore.CAP.MongoDB/CAP.MongoDBCapOptionsExtension.cs
@@ -32,7 +32,7 @@ namespace DotNetCore.CAP.MongoDB
//Try to add IMongoClient if does not exists
services.TryAddSingleton(x =>
{
- var options = x.GetService>().Value;
+ var options = x.GetRequiredService>().Value;
return new MongoClient(options.DatabaseConnection);
});
}
diff --git a/src/DotNetCore.CAP.MongoDB/CAP.MongoDBOptions.cs b/src/DotNetCore.CAP.MongoDB/CAP.MongoDBOptions.cs
index f753cb7..616fdfc 100644
--- a/src/DotNetCore.CAP.MongoDB/CAP.MongoDBOptions.cs
+++ b/src/DotNetCore.CAP.MongoDB/CAP.MongoDBOptions.cs
@@ -30,6 +30,6 @@ namespace DotNetCore.CAP.MongoDB
///
public string PublishedCollection { get; set; } = "cap.published";
- internal string Version { get; set; }
+ internal string Version { get; set; } = default!;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.MongoDB/DotNetCore.CAP.MongoDB.csproj b/src/DotNetCore.CAP.MongoDB/DotNetCore.CAP.MongoDB.csproj
index 8f975e5..0f36213 100644
--- a/src/DotNetCore.CAP.MongoDB/DotNetCore.CAP.MongoDB.csproj
+++ b/src/DotNetCore.CAP.MongoDB/DotNetCore.CAP.MongoDB.csproj
@@ -2,15 +2,10 @@
netstandard2.1
- DotNetCore.CAP.MongoDB
+ enable
$(PackageTags);MongoDB
-
-
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.MongoDB.xml
- 1701;1702;1705;CS1591
-
-
+
diff --git a/src/DotNetCore.CAP.MongoDB/IClientSessionHandle.CAP.cs b/src/DotNetCore.CAP.MongoDB/IClientSessionHandle.CAP.cs
index 177fb00..746008d 100644
--- a/src/DotNetCore.CAP.MongoDB/IClientSessionHandle.CAP.cs
+++ b/src/DotNetCore.CAP.MongoDB/IClientSessionHandle.CAP.cs
@@ -19,7 +19,7 @@ namespace MongoDB.Driver
public CapMongoDbClientSessionHandle(ICapTransaction transaction)
{
_transaction = transaction;
- _sessionHandle = (IClientSessionHandle)_transaction.DbTransaction;
+ _sessionHandle = (IClientSessionHandle)_transaction.DbTransaction!;
}
public void Dispose()
@@ -59,7 +59,7 @@ namespace MongoDB.Driver
return Task.CompletedTask;
}
- public void StartTransaction(TransactionOptions transactionOptions = null)
+ public void StartTransaction(TransactionOptions? transactionOptions = null)
{
_sessionHandle.StartTransaction(transactionOptions);
}
@@ -78,12 +78,12 @@ namespace MongoDB.Driver
return _sessionHandle.Fork();
}
- public TResult WithTransaction(Func callback, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default)
+ public TResult WithTransaction(Func callback, TransactionOptions? transactionOptions = null, CancellationToken cancellationToken = default)
{
return _sessionHandle.WithTransaction(callback, transactionOptions, cancellationToken);
}
- public Task WithTransactionAsync(Func> callbackAsync, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default)
+ public Task WithTransactionAsync(Func> callbackAsync, TransactionOptions? transactionOptions = null, CancellationToken cancellationToken = default)
{
return _sessionHandle.WithTransactionAsync(callbackAsync, transactionOptions, cancellationToken);
}
diff --git a/src/DotNetCore.CAP.MongoDB/IDataStorage.MongoDB.cs b/src/DotNetCore.CAP.MongoDB/IDataStorage.MongoDB.cs
index f6132ed..2875293 100644
--- a/src/DotNetCore.CAP.MongoDB/IDataStorage.MongoDB.cs
+++ b/src/DotNetCore.CAP.MongoDB/IDataStorage.MongoDB.cs
@@ -63,7 +63,7 @@ namespace DotNetCore.CAP.MongoDB
await collection.UpdateOneAsync(x => x.Id == long.Parse(message.DbId), updateDef);
}
- public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
+ public MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null)
{
var insertOptions = new InsertOneOptions { BypassDocumentValidation = false };
@@ -188,7 +188,7 @@ namespace DotNetCore.CAP.MongoDB
return queryResult.Select(x => new MediumMessage
{
DbId = x.Id.ToString(),
- Origin = _serializer.Deserialize(x.Content),
+ Origin = _serializer.Deserialize(x.Content)!,
Retries = x.Retries,
Added = x.Added
}).ToList();
@@ -209,7 +209,7 @@ namespace DotNetCore.CAP.MongoDB
return queryResult.Select(x => new MediumMessage
{
DbId = x.Id.ToString(),
- Origin = _serializer.Deserialize(x.Content),
+ Origin = _serializer.Deserialize(x.Content)!,
Retries = x.Retries,
Added = x.Added
}).ToList();
diff --git a/src/DotNetCore.CAP.MongoDB/IMonitoringApi.MongoDB.cs b/src/DotNetCore.CAP.MongoDB/IMonitoringApi.MongoDB.cs
index 321322e..e935145 100644
--- a/src/DotNetCore.CAP.MongoDB/IMonitoringApi.MongoDB.cs
+++ b/src/DotNetCore.CAP.MongoDB/IMonitoringApi.MongoDB.cs
@@ -27,7 +27,7 @@ namespace DotNetCore.CAP.MongoDB
_database = mongoClient.GetDatabase(_options.DatabaseName);
}
- public async Task GetPublishedMessageAsync(long id)
+ public async Task GetPublishedMessageAsync(long id)
{
var collection = _database.GetCollection(_options.PublishedCollection);
var message = await collection.Find(x => x.Id == id).FirstOrDefaultAsync();
@@ -41,7 +41,7 @@ namespace DotNetCore.CAP.MongoDB
};
}
- public async Task GetReceivedMessageAsync(long id)
+ public async Task GetReceivedMessageAsync(long id)
{
var collection = _database.GetCollection(_options.ReceivedCollection);
var message = await collection.Find(x => x.Id == id).FirstOrDefaultAsync();
diff --git a/src/DotNetCore.CAP.MongoDB/StorageMessage.cs b/src/DotNetCore.CAP.MongoDB/StorageMessage.cs
index 02cf6b8..cf3b8a4 100644
--- a/src/DotNetCore.CAP.MongoDB/StorageMessage.cs
+++ b/src/DotNetCore.CAP.MongoDB/StorageMessage.cs
@@ -9,13 +9,13 @@ namespace DotNetCore.CAP.MongoDB
{
public long Id { get; set; }
- public string Version { get; set; }
+ public string Version { get; set; } = default!;
- public string Group { get; set; }
+ public string Group { get; set; } = default!;
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
- public string Content { get; set; }
+ public string Content { get; set; } = default!;
public DateTime Added { get; set; }
@@ -23,18 +23,18 @@ namespace DotNetCore.CAP.MongoDB
public int Retries { get; set; }
- public string StatusName { get; set; }
+ public string StatusName { get; set; } = default!;
}
internal class PublishedMessage
{
public long Id { get; set; }
- public string Version { get; set; }
+ public string Version { get; set; } = default!;
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
- public string Content { get; set; }
+ public string Content { get; set; } = default!;
public DateTime Added { get; set; }
@@ -42,6 +42,6 @@ namespace DotNetCore.CAP.MongoDB
public int Retries { get; set; }
- public string StatusName { get; set; }
+ public string StatusName { get; set; } = default!;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs b/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs
index e770eb1..636dea7 100644
--- a/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs
+++ b/src/DotNetCore.CAP.MySql/CAP.EFOptions.cs
@@ -18,7 +18,7 @@ namespace DotNetCore.CAP
///
/// EF db context type.
///
- internal Type DbContextType { get; set; }
+ internal Type? DbContextType { get; set; }
///
/// Data version
diff --git a/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs b/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs
index ea1f503..a6f78f9 100644
--- a/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs
+++ b/src/DotNetCore.CAP.MySql/CAP.MySqlOptions.cs
@@ -13,7 +13,7 @@ namespace DotNetCore.CAP
///
/// Gets or sets the database's connection string that will be used to store database entities.
///
- public string ConnectionString { get; set; }
+ public string ConnectionString { get; set; } = default!;
}
internal class ConfigureMySqlOptions : IConfigureOptions
diff --git a/src/DotNetCore.CAP.MySql/DotNetCore.CAP.MySql.csproj b/src/DotNetCore.CAP.MySql/DotNetCore.CAP.MySql.csproj
index 59d3685..7d0e8bf 100644
--- a/src/DotNetCore.CAP.MySql/DotNetCore.CAP.MySql.csproj
+++ b/src/DotNetCore.CAP.MySql/DotNetCore.CAP.MySql.csproj
@@ -2,15 +2,9 @@
net6.0;netstandard2.1
- DotNetCore.CAP.MySql
+ enable
$(PackageTags);MySQL
-
-
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.MySql.xml
- 1701;1702;1705;CS1591
-
-
diff --git a/src/DotNetCore.CAP.MySql/IDataStorage.MySql.cs b/src/DotNetCore.CAP.MySql/IDataStorage.MySql.cs
index 72a0074..b2866f9 100644
--- a/src/DotNetCore.CAP.MySql/IDataStorage.MySql.cs
+++ b/src/DotNetCore.CAP.MySql/IDataStorage.MySql.cs
@@ -46,7 +46,7 @@ namespace DotNetCore.CAP.MySql
public async Task ChangeReceiveStateAsync(MediumMessage message, StatusName state) =>
await ChangeMessageStateAsync(_recName, message, state);
- public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
+ public MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null)
{
var sql = $"INSERT INTO `{_pubName}`(`Id`,`Version`,`Name`,`Content`,`Retries`,`Added`,`ExpiresAt`,`StatusName`)" +
$" VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";
@@ -68,7 +68,7 @@ namespace DotNetCore.CAP.MySql
new MySqlParameter("@Content", message.Content),
new MySqlParameter("@Retries", message.Retries),
new MySqlParameter("@Added", message.Added),
- new MySqlParameter("@ExpiresAt", message.ExpiresAt.HasValue ? (object)message.ExpiresAt.Value : DBNull.Value),
+ new MySqlParameter("@ExpiresAt", message.ExpiresAt.HasValue ? message.ExpiresAt.Value : DBNull.Value),
new MySqlParameter("@StatusName", nameof(StatusName.Scheduled)),
};
@@ -85,7 +85,7 @@ namespace DotNetCore.CAP.MySql
dbTrans = dbContextTrans.GetDbTransaction();
}
- var conn = dbTrans?.Connection;
+ var conn = dbTrans!.Connection!;
conn.ExecuteNonQuery(sql, dbTrans, sqlParams);
}
@@ -128,7 +128,7 @@ namespace DotNetCore.CAP.MySql
new MySqlParameter("@Content", _serializer.Serialize(mdMessage.Origin)),
new MySqlParameter("@Retries", mdMessage.Retries),
new MySqlParameter("@Added", mdMessage.Added),
- new MySqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? (object) mdMessage.ExpiresAt.Value : DBNull.Value),
+ new MySqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? mdMessage.ExpiresAt.Value : DBNull.Value),
new MySqlParameter("@StatusName", nameof(StatusName.Scheduled))
};
@@ -198,7 +198,7 @@ namespace DotNetCore.CAP.MySql
messages.Add(new MediumMessage
{
DbId = reader.GetInt64(0).ToString(),
- Origin = _serializer.Deserialize(reader.GetString(1)),
+ Origin = _serializer.Deserialize(reader.GetString(1))!,
Retries = reader.GetInt32(2),
Added = reader.GetDateTime(3)
});
diff --git a/src/DotNetCore.CAP.MySql/IDbConnection.Extensions.cs b/src/DotNetCore.CAP.MySql/IDbConnection.Extensions.cs
index f203025..3dcb0bf 100644
--- a/src/DotNetCore.CAP.MySql/IDbConnection.Extensions.cs
+++ b/src/DotNetCore.CAP.MySql/IDbConnection.Extensions.cs
@@ -9,7 +9,7 @@ namespace DotNetCore.CAP.MySql
{
internal static class DbConnectionExtensions
{
- public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction transaction = null,
+ public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction? transaction = null,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -33,7 +33,7 @@ namespace DotNetCore.CAP.MySql
return command.ExecuteNonQuery();
}
- public static T ExecuteReader(this IDbConnection connection, string sql, Func readerFunc,
+ public static T ExecuteReader(this IDbConnection connection, string sql, Func? readerFunc,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -51,7 +51,7 @@ namespace DotNetCore.CAP.MySql
var reader = command.ExecuteReader();
- T result = default;
+ T result = default!;
if (readerFunc != null)
{
result = readerFunc(reader);
@@ -77,14 +77,14 @@ namespace DotNetCore.CAP.MySql
var objValue = command.ExecuteScalar();
- T result = default;
+ T result = default!;
if (objValue != null)
{
var returnType = typeof(T);
var converter = TypeDescriptor.GetConverter(returnType);
if (converter.CanConvertFrom(objValue.GetType()))
{
- result = (T)converter.ConvertFrom(objValue);
+ result = (T)converter.ConvertFrom(objValue)!;
}
else
{
diff --git a/src/DotNetCore.CAP.MySql/IDbContextTransaction.CAP.cs b/src/DotNetCore.CAP.MySql/IDbContextTransaction.CAP.cs
index 2f89d47..015edf1 100644
--- a/src/DotNetCore.CAP.MySql/IDbContextTransaction.CAP.cs
+++ b/src/DotNetCore.CAP.MySql/IDbContextTransaction.CAP.cs
@@ -19,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
public CapEFDbTransaction(ICapTransaction transaction)
{
_transaction = transaction;
- var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction!;
TransactionId = dbContextTransaction.TransactionId;
}
@@ -60,7 +60,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
{
get
{
- var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction!;
return dbContextTransaction.GetDbTransaction();
}
}
diff --git a/src/DotNetCore.CAP.MySql/IMonitoringApi.MySql.cs b/src/DotNetCore.CAP.MySql/IMonitoringApi.MySql.cs
index 5864bdb..aaea317 100644
--- a/src/DotNetCore.CAP.MySql/IMonitoringApi.MySql.cs
+++ b/src/DotNetCore.CAP.MySql/IMonitoringApi.MySql.cs
@@ -247,18 +247,18 @@ WHERE `Key` >= @minKey
return result;
}
- public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
+ public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
- public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
+ public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
- private async Task GetMessageAsync(string tableName, long id)
+ private async Task GetMessageAsync(string tableName, long id)
{
var sql = $@"SELECT `Id` as DbId, `Content`,`Added`,`ExpiresAt`,`Retries` FROM `{tableName}` WHERE Id={id};";
await using var connection = new MySqlConnection(_options.ConnectionString);
var mediumMessage = connection.ExecuteReader(sql, reader =>
{
- MediumMessage message = null;
+ MediumMessage? message = null;
while (reader.Read())
{
diff --git a/src/DotNetCore.CAP.NATS/CAP.NATSOptions.cs b/src/DotNetCore.CAP.NATS/CAP.NATSOptions.cs
index 8ba4f0a..4761244 100644
--- a/src/DotNetCore.CAP.NATS/CAP.NATSOptions.cs
+++ b/src/DotNetCore.CAP.NATS/CAP.NATSOptions.cs
@@ -27,9 +27,9 @@ namespace DotNetCore.CAP
///
/// Used to setup all NATs client options
///
- public Options Options { get; set; }
+ public Options? Options { get; set; }
- public Action StreamOptions { get; set; }
+ public Action? StreamOptions { get; set; }
public Func NormalizeStreamName { get; set; } = origin => origin.Split('.')[0];
}
diff --git a/src/DotNetCore.CAP.NATS/CAP.Options.Extensions.cs b/src/DotNetCore.CAP.NATS/CAP.Options.Extensions.cs
index 743aafd..c6be74b 100644
--- a/src/DotNetCore.CAP.NATS/CAP.Options.Extensions.cs
+++ b/src/DotNetCore.CAP.NATS/CAP.Options.Extensions.cs
@@ -3,7 +3,6 @@
using System;
using DotNetCore.CAP;
-using JetBrains.Annotations;
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
@@ -15,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
///
/// CAP configuration options
/// NATS bootstrap server urls.
- public static CapOptions UseNATS(this CapOptions options, [CanBeNull] string bootstrapServers = null)
+ public static CapOptions UseNATS(this CapOptions options, string? bootstrapServers = null)
{
return options.UseNATS(opt =>
{
diff --git a/src/DotNetCore.CAP.NATS/DotNetCore.CAP.NATS.csproj b/src/DotNetCore.CAP.NATS/DotNetCore.CAP.NATS.csproj
index 2557ace..72b7718 100644
--- a/src/DotNetCore.CAP.NATS/DotNetCore.CAP.NATS.csproj
+++ b/src/DotNetCore.CAP.NATS/DotNetCore.CAP.NATS.csproj
@@ -2,16 +2,10 @@
netstandard2.1
- DotNetCore.CAP.NATS
+ enable
$(PackageTags);NATS
-
- NU1605;NU1701
- NU1701;CS1591
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.NATS.xml
-
-
diff --git a/src/DotNetCore.CAP.NATS/NATSConsumerClient.cs b/src/DotNetCore.CAP.NATS/NATSConsumerClient.cs
index f67d67a..a7ef802 100644
--- a/src/DotNetCore.CAP.NATS/NATSConsumerClient.cs
+++ b/src/DotNetCore.CAP.NATS/NATSConsumerClient.cs
@@ -21,7 +21,7 @@ namespace DotNetCore.CAP.NATS
private readonly string _groupId;
private readonly NATSOptions _natsOptions;
- private IConnection _consumerClient;
+ private IConnection? _consumerClient;
public NATSConsumerClient(string groupId, IOptions options)
{
@@ -29,15 +29,17 @@ namespace DotNetCore.CAP.NATS
_natsOptions = options.Value ?? throw new ArgumentNullException(nameof(options));
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("NATS", _natsOptions.Servers);
+ public BrokerAddress BrokerAddress => new ("NATS", _natsOptions.Servers);
public ICollection FetchTopics(IEnumerable topicNames)
{
- var jsm = _consumerClient.CreateJetStreamManagementContext();
+ Connect();
+
+ var jsm = _consumerClient!.CreateJetStreamManagementContext();
var streamGroup = topicNames.GroupBy(x => _natsOptions.NormalizeStreamName(x));
@@ -80,7 +82,7 @@ namespace DotNetCore.CAP.NATS
Connect();
- var js = _consumerClient.CreateJetStreamContext();
+ var js = _consumerClient!.CreateJetStreamContext();
foreach (var subject in topics)
{
@@ -106,7 +108,7 @@ namespace DotNetCore.CAP.NATS
private void Subscription_MessageHandler(object sender, MsgHandlerEventArgs e)
{
- var headers = new Dictionary();
+ var headers = new Dictionary();
foreach (string h in e.Message.Header.Keys)
{
@@ -126,7 +128,7 @@ namespace DotNetCore.CAP.NATS
}
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
if (sender is Msg msg)
{
@@ -153,7 +155,7 @@ namespace DotNetCore.CAP.NATS
if (_consumerClient == null)
{
var opts = _natsOptions.Options ?? ConnectionFactory.GetDefaultOptions();
- opts.Url = _natsOptions.Servers ?? opts.Url;
+ opts.Url ??= _natsOptions.Servers;
opts.ClosedEventHandler = ConnectedEventHandler;
opts.DisconnectedEventHandler = ConnectedEventHandler;
opts.AsyncErrorEventHandler = AsyncErrorEventHandler;
diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs
index 5fa9d8b..4108988 100644
--- a/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs
+++ b/src/DotNetCore.CAP.PostgreSql/CAP.EFOptions.cs
@@ -16,11 +16,11 @@ namespace DotNetCore.CAP
///
public string Schema { get; set; } = DefaultSchema;
- internal Type DbContextType { get; set; }
+ internal Type? DbContextType { get; set; }
///
/// Data version
///
- internal string Version { get; set; }
+ internal string Version { get; set; } = default!;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
index d881b2d..bcaf405 100644
--- a/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
+++ b/src/DotNetCore.CAP.PostgreSql/CAP.PostgreSqlOptions.cs
@@ -13,7 +13,7 @@ namespace DotNetCore.CAP
///
/// Gets or sets the database's connection string that will be used to store database entities.
///
- public string ConnectionString { get; set; }
+ public string ConnectionString { get; set; } = default!;
}
internal class ConfigurePostgreSqlOptions : IConfigureOptions
diff --git a/src/DotNetCore.CAP.PostgreSql/DotNetCore.CAP.PostgreSql.csproj b/src/DotNetCore.CAP.PostgreSql/DotNetCore.CAP.PostgreSql.csproj
index e5fe752..6dfb06c 100644
--- a/src/DotNetCore.CAP.PostgreSql/DotNetCore.CAP.PostgreSql.csproj
+++ b/src/DotNetCore.CAP.PostgreSql/DotNetCore.CAP.PostgreSql.csproj
@@ -2,15 +2,10 @@
net6.0;netstandard2.1
- DotNetCore.CAP.PostgreSql
+ enable
$(PackageTags);PostgreSQL
-
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.PostgreSql.xml
- 1701;1702;1705;CS1591
-
-
diff --git a/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs b/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
index 6b60b6f..73a8610 100644
--- a/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
+++ b/src/DotNetCore.CAP.PostgreSql/IDataStorage.PostgreSql.cs
@@ -46,7 +46,7 @@ namespace DotNetCore.CAP.PostgreSql
public async Task ChangeReceiveStateAsync(MediumMessage message, StatusName state) =>
await ChangeMessageStateAsync(_recName, message, state);
- public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
+ public MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null)
{
var sql =
$"INSERT INTO {_pubName} (\"Id\",\"Version\",\"Name\",\"Content\",\"Retries\",\"Added\",\"ExpiresAt\",\"StatusName\")" +
@@ -69,7 +69,7 @@ namespace DotNetCore.CAP.PostgreSql
new NpgsqlParameter("@Content", message.Content),
new NpgsqlParameter("@Retries", message.Retries),
new NpgsqlParameter("@Added", message.Added),
- new NpgsqlParameter("@ExpiresAt", message.ExpiresAt.HasValue ? (object)message.ExpiresAt.Value : DBNull.Value),
+ new NpgsqlParameter("@ExpiresAt", message.ExpiresAt.HasValue ? message.ExpiresAt.Value : DBNull.Value),
new NpgsqlParameter("@StatusName", nameof(StatusName.Scheduled))
};
@@ -84,7 +84,7 @@ namespace DotNetCore.CAP.PostgreSql
if (dbTrans == null && dbTransaction is IDbContextTransaction dbContextTrans)
dbTrans = dbContextTrans.GetDbTransaction();
- var conn = dbTrans?.Connection;
+ var conn = dbTrans?.Connection!;
conn.ExecuteNonQuery(sql, dbTrans, sqlParams);
}
@@ -127,7 +127,7 @@ namespace DotNetCore.CAP.PostgreSql
new NpgsqlParameter("@Content", _serializer.Serialize(mdMessage.Origin)),
new NpgsqlParameter("@Retries", mdMessage.Retries),
new NpgsqlParameter("@Added", mdMessage.Added),
- new NpgsqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? (object) mdMessage.ExpiresAt.Value : DBNull.Value),
+ new NpgsqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? mdMessage.ExpiresAt.Value : DBNull.Value),
new NpgsqlParameter("@StatusName", nameof(StatusName.Scheduled))
};
@@ -199,7 +199,7 @@ namespace DotNetCore.CAP.PostgreSql
messages.Add(new MediumMessage
{
DbId = reader.GetInt64(0).ToString(),
- Origin = _serializer.Deserialize(reader.GetString(1)),
+ Origin = _serializer.Deserialize(reader.GetString(1))!,
Retries = reader.GetInt32(2),
Added = reader.GetDateTime(3)
});
diff --git a/src/DotNetCore.CAP.PostgreSql/IDbConnection.Extensions.cs b/src/DotNetCore.CAP.PostgreSql/IDbConnection.Extensions.cs
index 0a5ac1f..52f35b3 100644
--- a/src/DotNetCore.CAP.PostgreSql/IDbConnection.Extensions.cs
+++ b/src/DotNetCore.CAP.PostgreSql/IDbConnection.Extensions.cs
@@ -9,7 +9,7 @@ namespace DotNetCore.CAP.PostgreSql
{
internal static class DbConnectionExtensions
{
- public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction transaction = null,
+ public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction? transaction = null,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -33,7 +33,7 @@ namespace DotNetCore.CAP.PostgreSql
return command.ExecuteNonQuery();
}
- public static T ExecuteReader(this IDbConnection connection, string sql, Func readerFunc,
+ public static T ExecuteReader(this IDbConnection connection, string sql, Func? readerFunc,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -51,7 +51,7 @@ namespace DotNetCore.CAP.PostgreSql
var reader = command.ExecuteReader();
- T result = default;
+ T result = default!;
if (readerFunc != null)
{
result = readerFunc(reader);
@@ -77,14 +77,14 @@ namespace DotNetCore.CAP.PostgreSql
var objValue = command.ExecuteScalar();
- T result = default;
+ T result = default!;
if (objValue != null)
{
var returnType = typeof(T);
var converter = TypeDescriptor.GetConverter(returnType);
if (converter.CanConvertFrom(objValue.GetType()))
{
- result = (T)converter.ConvertFrom(objValue);
+ result = (T)converter.ConvertFrom(objValue)!;
}
else
{
diff --git a/src/DotNetCore.CAP.PostgreSql/IDbContextTransaction.CAP.cs b/src/DotNetCore.CAP.PostgreSql/IDbContextTransaction.CAP.cs
index 794ea2e..1354274 100644
--- a/src/DotNetCore.CAP.PostgreSql/IDbContextTransaction.CAP.cs
+++ b/src/DotNetCore.CAP.PostgreSql/IDbContextTransaction.CAP.cs
@@ -18,7 +18,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
public CapEFDbTransaction(ICapTransaction transaction)
{
_transaction = transaction;
- var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction!;
TransactionId = dbContextTransaction.TransactionId;
}
@@ -58,7 +58,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
{
get
{
- var dbContextTransaction = (IDbContextTransaction) _transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction) _transaction.DbTransaction!;
return dbContextTransaction.GetDbTransaction();
}
}
diff --git a/src/DotNetCore.CAP.PostgreSql/IMonitoringApi.PostgreSql.cs b/src/DotNetCore.CAP.PostgreSql/IMonitoringApi.PostgreSql.cs
index 39d55db..ec98a80 100644
--- a/src/DotNetCore.CAP.PostgreSql/IMonitoringApi.PostgreSql.cs
+++ b/src/DotNetCore.CAP.PostgreSql/IMonitoringApi.PostgreSql.cs
@@ -27,9 +27,9 @@ namespace DotNetCore.CAP.PostgreSql
_recName = initializer.GetReceivedTableName();
}
- public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
+ public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
- public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
+ public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
public StatisticsDto GetStatistics()
{
@@ -120,7 +120,7 @@ namespace DotNetCore.CAP.PostgreSql
Content = reader.GetString(index++),
Retries = reader.GetInt32(index++),
Added = reader.GetDateTime(index++),
- ExpiresAt = reader.IsDBNull(index++) ? (DateTime?)null : reader.GetDateTime(index - 1),
+ ExpiresAt = reader.IsDBNull(index++) ? null : reader.GetDateTime(index - 1),
StatusName = reader.GetString(index)
});
}
@@ -242,14 +242,14 @@ select ""Key"",""Count"" from aggr where ""Key"" >= @minKey and ""Key"" <= @maxK
return result;
}
- private async Task GetMessageAsync(string tableName, long id)
+ private async Task GetMessageAsync(string tableName, long id)
{
var sql = $@"SELECT ""Id"" AS ""DbId"", ""Content"", ""Added"", ""ExpiresAt"", ""Retries"" FROM {tableName} WHERE ""Id""={id} FOR UPDATE SKIP LOCKED";
await using var connection = new NpgsqlConnection(_options.ConnectionString);
var mediumMessage = connection.ExecuteReader(sql, reader =>
{
- MediumMessage message = null;
+ MediumMessage? message = null;
while (reader.Read())
{
diff --git a/src/DotNetCore.CAP.Pulsar/CAP.PulsarOptions.cs b/src/DotNetCore.CAP.Pulsar/CAP.PulsarOptions.cs
index 61428c9..2384439 100644
--- a/src/DotNetCore.CAP.Pulsar/CAP.PulsarOptions.cs
+++ b/src/DotNetCore.CAP.Pulsar/CAP.PulsarOptions.cs
@@ -11,9 +11,11 @@ namespace DotNetCore.CAP
///
public class PulsarOptions
{
- public string ServiceUrl { get; set; }
+ public string ServiceUrl { get; set; } = default!;
- public TlsOptions TlsOptions { get; set; }
+ public bool EnableClientLog { get; set; } = false;
+
+ public TlsOptions? TlsOptions { get; set; }
}
}
diff --git a/src/DotNetCore.CAP.Pulsar/DotNetCore.CAP.Pulsar.csproj b/src/DotNetCore.CAP.Pulsar/DotNetCore.CAP.Pulsar.csproj
index ecc1af2..6df7111 100644
--- a/src/DotNetCore.CAP.Pulsar/DotNetCore.CAP.Pulsar.csproj
+++ b/src/DotNetCore.CAP.Pulsar/DotNetCore.CAP.Pulsar.csproj
@@ -2,14 +2,9 @@
netstandard2.1
- DotNetCore.CAP.Pulsar
+ enable
$(PackageTags);Pulsar
-
-
-
- NU1605;NU1701
- NU1701;CS1591
- bin\$(Configuration)\netstandard2.0\DotNetCore.CAP.Pulsar.xml
+ CS0067
diff --git a/src/DotNetCore.CAP.Pulsar/IConnectionFactory.Default.cs b/src/DotNetCore.CAP.Pulsar/IConnectionFactory.Default.cs
index e0c55f1..822b737 100644
--- a/src/DotNetCore.CAP.Pulsar/IConnectionFactory.Default.cs
+++ b/src/DotNetCore.CAP.Pulsar/IConnectionFactory.Default.cs
@@ -13,12 +13,14 @@ namespace DotNetCore.CAP.Pulsar
{
public class ConnectionFactory : IConnectionFactory, IAsyncDisposable
{
- private PulsarClient _client;
+ private readonly ILogger _logger;
+ private PulsarClient? _client;
private readonly PulsarOptions _options;
private readonly ConcurrentDictionary>> _topicProducers;
public ConnectionFactory(ILogger logger, IOptions options)
{
+ _logger = logger;
_options = options.Value;
_topicProducers = new ConcurrentDictionary>>();
diff --git a/src/DotNetCore.CAP.Pulsar/ITransport.Pulsar.cs b/src/DotNetCore.CAP.Pulsar/ITransport.Pulsar.cs
index 55c9bb0..5594a3b 100644
--- a/src/DotNetCore.CAP.Pulsar/ITransport.Pulsar.cs
+++ b/src/DotNetCore.CAP.Pulsar/ITransport.Pulsar.cs
@@ -22,7 +22,7 @@ namespace DotNetCore.CAP.Pulsar
_connectionFactory = connectionFactory;
}
- public BrokerAddress BrokerAddress => new BrokerAddress("Pulsar", _connectionFactory.ServersAddress);
+ public BrokerAddress BrokerAddress => new ("Pulsar", _connectionFactory.ServersAddress);
public async Task SendAsync(TransportMessage message)
{
@@ -30,9 +30,9 @@ namespace DotNetCore.CAP.Pulsar
try
{
- var headerDic = new Dictionary(message.Headers);
+ var headerDic = new Dictionary(message.Headers);
headerDic.TryGetValue(PulsarHeaders.PulsarKey, out var key);
- var pulsarMessage = producer.NewMessage(message.Body, key, headerDic);
+ var pulsarMessage = producer.NewMessage(message.Body!, key, headerDic);
var result = await producer.SendAsync(pulsarMessage);
if (result.Type != null)
diff --git a/src/DotNetCore.CAP.Pulsar/PulsarConsumerClient.cs b/src/DotNetCore.CAP.Pulsar/PulsarConsumerClient.cs
index e81b953..236204b 100644
--- a/src/DotNetCore.CAP.Pulsar/PulsarConsumerClient.cs
+++ b/src/DotNetCore.CAP.Pulsar/PulsarConsumerClient.cs
@@ -7,6 +7,8 @@ using System.Reflection;
using System.Threading;
using DotNetCore.CAP.Messages;
using DotNetCore.CAP.Transport;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Pulsar.Client.Api;
using Pulsar.Client.Common;
@@ -15,23 +17,23 @@ namespace DotNetCore.CAP.Pulsar
{
internal sealed class PulsarConsumerClient : IConsumerClient
{
- private static PulsarClient _client;
+ private readonly PulsarClient _client;
private readonly string _groupId;
private readonly PulsarOptions _pulsarOptions;
- private IConsumer _consumerClient;
+ private IConsumer? _consumerClient;
- public PulsarConsumerClient(PulsarClient client,string groupId, IOptions options)
+ public PulsarConsumerClient(PulsarClient client, string groupId, IOptions options)
{
- _client = client;
+ _client = client;
_groupId = groupId;
_pulsarOptions = options.Value;
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("Pulsar", _pulsarOptions.ServiceUrl);
+ public BrokerAddress BrokerAddress => new ("Pulsar", _pulsarOptions.ServiceUrl);
public void Subscribe(IEnumerable topics)
{
@@ -41,22 +43,22 @@ namespace DotNetCore.CAP.Pulsar
}
var serviceName = Assembly.GetEntryAssembly()?.GetName().Name.ToLower();
-
+
_consumerClient = _client.NewConsumer()
.Topics(topics)
.SubscriptionName(_groupId)
.ConsumerName(serviceName)
.SubscriptionType(SubscriptionType.Shared)
- .SubscribeAsync().Result;
+ .SubscribeAsync().GetAwaiter().GetResult();
}
public void Listening(TimeSpan timeout, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
- var consumerResult = _consumerClient.ReceiveAsync().Result;
+ var consumerResult = _consumerClient!.ReceiveAsync(cancellationToken).Result;
- var headers = new Dictionary(consumerResult.Properties.Count);
+ var headers = new Dictionary(consumerResult.Properties.Count);
foreach (var header in consumerResult.Properties)
{
headers.Add(header.Key, header.Value);
@@ -72,12 +74,15 @@ namespace DotNetCore.CAP.Pulsar
public void Commit(object sender)
{
- _consumerClient.AcknowledgeAsync((MessageId)sender);
+ _consumerClient!.AcknowledgeAsync((MessageId)sender);
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
- _consumerClient.NegativeAcknowledge((MessageId)sender);
+ if(sender is MessageId id)
+ {
+ _consumerClient!.NegativeAcknowledge(id);
+ }
}
public void Dispose()
@@ -85,14 +90,6 @@ namespace DotNetCore.CAP.Pulsar
_consumerClient?.DisposeAsync();
}
- private void ConsumerClient_OnConsumeError(IConsumer consumer, Exception e)
- {
- var logArgs = new LogMessageEventArgs
- {
- LogType = MqLogType.ServerConnError,
- Reason = $"An error occurred during connect pulsar --> {e.Message}"
- };
- OnLog?.Invoke(null, logArgs);
- }
- }
+
+ }
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.Pulsar/PulsarConsumerClientFactory.cs b/src/DotNetCore.CAP.Pulsar/PulsarConsumerClientFactory.cs
index 5771a4d..22d4fa1 100644
--- a/src/DotNetCore.CAP.Pulsar/PulsarConsumerClientFactory.cs
+++ b/src/DotNetCore.CAP.Pulsar/PulsarConsumerClientFactory.cs
@@ -2,7 +2,9 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using DotNetCore.CAP.Transport;
+using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using Pulsar.Client.Api;
namespace DotNetCore.CAP.Pulsar
{
@@ -11,10 +13,15 @@ namespace DotNetCore.CAP.Pulsar
private readonly IConnectionFactory _connection;
private readonly IOptions _pulsarOptions;
- public PulsarConsumerClientFactory(IConnectionFactory connection, IOptions pulsarOptions)
+ public PulsarConsumerClientFactory(IConnectionFactory connection, ILoggerFactory loggerFactory, IOptions pulsarOptions)
{
_connection = connection;
_pulsarOptions = pulsarOptions;
+
+ if (_pulsarOptions.Value.EnableClientLog)
+ {
+ PulsarClient.Logger = loggerFactory.CreateLogger();
+ }
}
public IConsumerClient Create(string groupId)
@@ -22,7 +29,7 @@ namespace DotNetCore.CAP.Pulsar
try
{
var client = _connection.RentClient();
- var consumerClient = new PulsarConsumerClient(client,groupId, _pulsarOptions);
+ var consumerClient = new PulsarConsumerClient(client, groupId, _pulsarOptions);
return consumerClient;
}
catch (System.Exception e)
diff --git a/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs b/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs
index d642222..ebe68e5 100644
--- a/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs
+++ b/src/DotNetCore.CAP.RabbitMQ/CAP.RabbiMQOptions.cs
@@ -74,28 +74,29 @@ namespace DotNetCore.CAP
/// Optional queue arguments, also known as "x-arguments" because of their field name in the AMQP 0-9-1 protocol,
/// is a map (dictionary) of arbitrary key/value pairs that can be provided by clients when a queue is declared.
///
- public QueueArgumentsOptions QueueArguments { get; set; } = new QueueArgumentsOptions();
+ public QueueArgumentsOptions QueueArguments { get; set; } = new ();
///
/// If you need to get additional native delivery args, you can use this function to write into .
///
- public Func>> CustomHeaders { get; set; }
+ public Func>>? CustomHeaders { get; set; }
///
/// RabbitMQ native connection factory options
///
- public Action ConnectionFactoryOptions { get; set; }
+ public Action? ConnectionFactoryOptions { get; set; }
public class QueueArgumentsOptions
{
///
/// Gets or sets queue mode by supplying the 'x-queue-mode' declaration argument with a string specifying the desired mode.
///
- public string QueueMode { get; set; }
+ public string QueueMode { get; set; } = default!;
///
/// Gets or sets queue message automatic deletion time (in milliseconds) "x-message-ttl", Default 864000000 ms (10 days).
///
+ // ReSharper disable once InconsistentNaming
public int MessageTTL { get; set; } = 864000000;
}
}
diff --git a/src/DotNetCore.CAP.RabbitMQ/DotNetCore.CAP.RabbitMQ.csproj b/src/DotNetCore.CAP.RabbitMQ/DotNetCore.CAP.RabbitMQ.csproj
index eb88d96..d91e004 100644
--- a/src/DotNetCore.CAP.RabbitMQ/DotNetCore.CAP.RabbitMQ.csproj
+++ b/src/DotNetCore.CAP.RabbitMQ/DotNetCore.CAP.RabbitMQ.csproj
@@ -2,14 +2,9 @@
netstandard2.1
- DotNetCore.CAP.RabbitMQ
+ enable
$(PackageTags);RabbitMQ
-
-
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.RabbitMQ.xml
- 1701;1702;1705;CS1591
-
diff --git a/src/DotNetCore.CAP.RabbitMQ/IConnectionChannelPool.Default.cs b/src/DotNetCore.CAP.RabbitMQ/IConnectionChannelPool.Default.cs
index 1889553..370df8e 100644
--- a/src/DotNetCore.CAP.RabbitMQ/IConnectionChannelPool.Default.cs
+++ b/src/DotNetCore.CAP.RabbitMQ/IConnectionChannelPool.Default.cs
@@ -18,7 +18,7 @@ namespace DotNetCore.CAP.RabbitMQ
private readonly Func _connectionActivator;
private readonly ILogger _logger;
private readonly ConcurrentQueue _pool;
- private IConnection _connection;
+ private IConnection? _connection;
private static readonly object SLock = new object();
private int _count;
diff --git a/src/DotNetCore.CAP.RabbitMQ/ITransport.RabbitMQ.cs b/src/DotNetCore.CAP.RabbitMQ/ITransport.RabbitMQ.cs
index 0a19789..499b7c4 100644
--- a/src/DotNetCore.CAP.RabbitMQ/ITransport.RabbitMQ.cs
+++ b/src/DotNetCore.CAP.RabbitMQ/ITransport.RabbitMQ.cs
@@ -27,11 +27,11 @@ namespace DotNetCore.CAP.RabbitMQ
_exchange = _connectionChannelPool.Exchange;
}
- public BrokerAddress BrokerAddress => new BrokerAddress("RabbitMQ", _connectionChannelPool.HostAddress);
+ public BrokerAddress BrokerAddress => new ("RabbitMQ", _connectionChannelPool.HostAddress);
public Task SendAsync(TransportMessage message)
{
- IModel channel = null;
+ IModel? channel = null;
try
{
channel = _connectionChannelPool.Rent();
@@ -40,7 +40,7 @@ namespace DotNetCore.CAP.RabbitMQ
var props = channel.CreateBasicProperties();
props.DeliveryMode = 2;
- props.Headers = message.Headers.ToDictionary(x => x.Key, x => (object)x.Value);
+ props.Headers = message.Headers.ToDictionary(x => x.Key, x => (object?)x.Value);
channel.ExchangeDeclare(_exchange, RabbitMQOptions.ExchangeType, true);
diff --git a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs
index 9624841..548001b 100644
--- a/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs
+++ b/src/DotNetCore.CAP.RabbitMQ/RabbitMQConsumerClient.cs
@@ -22,9 +22,8 @@ namespace DotNetCore.CAP.RabbitMQ
private readonly string _exchangeName;
private readonly string _queueName;
private readonly RabbitMQOptions _rabbitMQOptions;
- private IModel _channel;
-
- private IConnection _connection;
+ private IModel? _channel;
+ private IConnection? _connection;
public RabbitMQConsumerClient(string queueName,
IConnectionChannelPool connectionChannelPool,
@@ -36,11 +35,11 @@ namespace DotNetCore.CAP.RabbitMQ
_exchangeName = connectionChannelPool.Exchange;
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("RabbitMQ", _rabbitMQOptions.HostName);
+ public BrokerAddress BrokerAddress => new("RabbitMQ", _rabbitMQOptions.HostName);
public void Subscribe(IEnumerable topics)
{
@@ -81,17 +80,17 @@ namespace DotNetCore.CAP.RabbitMQ
public void Commit(object sender)
{
- if (_channel.IsOpen)
+ if (_channel!.IsOpen)
{
_channel.BasicAck((ulong)sender, false);
}
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
- if (_channel.IsOpen)
+ if (_channel!.IsOpen && sender is ulong val)
{
- _channel.BasicReject((ulong)sender, true);
+ _channel.BasicReject(val, true);
}
}
@@ -175,7 +174,7 @@ namespace DotNetCore.CAP.RabbitMQ
private void OnConsumerReceived(object sender, BasicDeliverEventArgs e)
{
- var headers = new Dictionary();
+ var headers = new Dictionary();
if (e.BasicProperties.Headers != null)
{
diff --git a/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.Extensions.cs b/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.Extensions.cs
index d892867..52a26dd 100644
--- a/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.Extensions.cs
+++ b/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.Extensions.cs
@@ -15,12 +15,22 @@ namespace Microsoft.Extensions.DependencyInjection
return options.UseRedis(_ => { });
}
+ ///
+ /// Use redis streams as the message transport.
+ ///
+ /// The .
+ /// The StackExchange.Redis comma-delimited configuration string.
public static CapOptions UseRedis(this CapOptions options, string connection)
{
return options.UseRedis(opt => opt.Configuration = ConfigurationOptions.Parse(connection));
}
-
+ ///
+ /// Use redis streams as the message transport.
+ ///
+ /// The .
+ /// The CAP redis client options.
+ /// is null.
public static CapOptions UseRedis(this CapOptions options, Action configure)
{
if (configure is null) throw new ArgumentNullException(nameof(configure));
diff --git a/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.cs b/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.cs
index 1b5d56a..90f0c54 100644
--- a/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.cs
+++ b/src/DotNetCore.CAP.RedisStreams/CapOptions.Redis.cs
@@ -9,11 +9,11 @@ namespace DotNetCore.CAP
public class CapRedisOptions
{
///
- /// Gets or sets the options of redis connections
+ /// Gets or sets the native options of StackExchange.Redis
///
- public ConfigurationOptions Configuration { get; set; }
+ public ConfigurationOptions? Configuration { get; set; }
- internal string Endpoint { get; set; }
+ internal string Endpoint { get; set; } = default!;
///
/// Gets or sets the count of entries consumed from stream
diff --git a/src/DotNetCore.CAP.RedisStreams/DotNetCore.CAP.RedisStreams.csproj b/src/DotNetCore.CAP.RedisStreams/DotNetCore.CAP.RedisStreams.csproj
index 168b972..37ba7e1 100644
--- a/src/DotNetCore.CAP.RedisStreams/DotNetCore.CAP.RedisStreams.csproj
+++ b/src/DotNetCore.CAP.RedisStreams/DotNetCore.CAP.RedisStreams.csproj
@@ -2,7 +2,7 @@
netstandard2.1
- DotNetCore.CAP.RedisStreams
+ enable
$(PackageTags);RedisStreams
@@ -16,7 +16,7 @@
-
+
diff --git a/src/DotNetCore.CAP.RedisStreams/IConnectionPool.Default.cs b/src/DotNetCore.CAP.RedisStreams/IConnectionPool.Default.cs
index af08696..998e183 100644
--- a/src/DotNetCore.CAP.RedisStreams/IConnectionPool.Default.cs
+++ b/src/DotNetCore.CAP.RedisStreams/IConnectionPool.Default.cs
@@ -14,11 +14,10 @@ namespace DotNetCore.CAP.RedisStreams
{
internal class RedisConnectionPool : IRedisConnectionPool, IDisposable
{
- private readonly ConcurrentBag _connections =
- new ConcurrentBag();
+ private readonly ConcurrentBag _connections = new();
private readonly ILoggerFactory _loggerFactory;
- private readonly SemaphoreSlim _poolLock = new SemaphoreSlim(1);
+ private readonly SemaphoreSlim _poolLock = new(1);
private readonly CapRedisOptions _redisOptions;
private bool _isDisposed;
private bool _poolAlreadyConfigured;
@@ -30,13 +29,11 @@ namespace DotNetCore.CAP.RedisStreams
Init().GetAwaiter().GetResult();
}
- private AsyncLazyRedisConnection QuietConnection
+ private AsyncLazyRedisConnection? QuietConnection
{
get
{
- if (_poolAlreadyConfigured)
- return _connections.OrderBy(async c => (await c).ConnectionCapacity).First();
- return null;
+ return _poolAlreadyConfigured ? _connections.OrderBy(async c => (await c).ConnectionCapacity).First() : null;
}
}
diff --git a/src/DotNetCore.CAP.RedisStreams/IConnectionPool.LazyConnection.cs b/src/DotNetCore.CAP.RedisStreams/IConnectionPool.LazyConnection.cs
index 808bdf7..862364f 100644
--- a/src/DotNetCore.CAP.RedisStreams/IConnectionPool.LazyConnection.cs
+++ b/src/DotNetCore.CAP.RedisStreams/IConnectionPool.LazyConnection.cs
@@ -28,7 +28,7 @@ namespace DotNetCore.CAP.RedisStreams
var redisLogger = new RedisLogger(logger);
- ConnectionMultiplexer connection = null;
+ ConnectionMultiplexer? connection = null;
while (attemp <= 5)
{
diff --git a/src/DotNetCore.CAP.RedisStreams/IConsumerClient.Redis.cs b/src/DotNetCore.CAP.RedisStreams/IConsumerClient.Redis.cs
index 598b35c..4d2a862 100644
--- a/src/DotNetCore.CAP.RedisStreams/IConsumerClient.Redis.cs
+++ b/src/DotNetCore.CAP.RedisStreams/IConsumerClient.Redis.cs
@@ -18,9 +18,9 @@ namespace DotNetCore.CAP.RedisStreams
{
private readonly string _groupId;
private readonly ILogger _logger;
- private readonly IOptions _options;
+ private readonly IOptions _options;
private readonly IRedisStreamManager _redis;
- private string[] _topics;
+ private string[] _topics = default!;
public RedisConsumerClient(string groupId,
IRedisStreamManager redis,
@@ -34,11 +34,11 @@ namespace DotNetCore.CAP.RedisStreams
_logger = logger;
}
- public event EventHandler OnMessageReceived;
+ public event EventHandler? OnMessageReceived;
- public event EventHandler OnLog;
+ public event EventHandler? OnLog;
- public BrokerAddress BrokerAddress => new BrokerAddress("redis", _options.Value.Endpoint);
+ public BrokerAddress BrokerAddress => new("redis", _options.Value.Endpoint);
public void Subscribe(IEnumerable topics)
{
@@ -59,16 +59,17 @@ namespace DotNetCore.CAP.RedisStreams
cancellationToken.ThrowIfCancellationRequested();
cancellationToken.WaitHandle.WaitOne(timeout);
}
+ // ReSharper disable once FunctionNeverReturns
}
public void Commit(object sender)
{
- var (stream, group, id) = ((string stream, string group, string id)) sender;
+ var (stream, group, id) = ((string stream, string group, string id))sender;
_redis.Ack(stream, group, id).GetAwaiter().GetResult();
}
- public void Reject(object sender)
+ public void Reject(object? sender)
{
// ignore
}
@@ -94,32 +95,39 @@ namespace DotNetCore.CAP.RedisStreams
private async Task ConsumeMessages(IAsyncEnumerable> streamsSet, RedisValue position)
{
await foreach (var set in streamsSet)
- foreach (var stream in set)
- foreach (var entry in stream.Entries)
{
- if (entry.IsNull)
- return;
- try
+ foreach (var stream in set)
{
- var message = RedisMessage.Create(entry, _groupId);
- OnMessageReceived?.Invoke((stream.Key.ToString(), _groupId, entry.Id.ToString()), message);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex.Message, ex);
- var logArgs = new LogMessageEventArgs
+ foreach (var entry in stream.Entries)
{
- LogType = MqLogType.ConsumeError,
- Reason = ex.ToString()
- };
- OnLog?.Invoke(entry, logArgs);
- }
- finally
- {
- var positionName = position == StreamPosition.Beginning
- ? nameof(StreamPosition.Beginning)
- : nameof(StreamPosition.NewMessages);
- _logger.LogDebug($"Redis stream entry [{entry.Id}] [position : {positionName}] was delivered.");
+ if (entry.IsNull)
+ {
+ return;
+ }
+
+ try
+ {
+ var message = RedisMessage.Create(entry, _groupId);
+ OnMessageReceived?.Invoke((stream.Key.ToString(), _groupId, entry.Id.ToString()), message);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex.Message, ex);
+ var logArgs = new LogMessageEventArgs
+ {
+ LogType = MqLogType.ConsumeError,
+ Reason = ex.ToString()
+ };
+ OnLog?.Invoke(entry, logArgs);
+ }
+ finally
+ {
+ var positionName = position == StreamPosition.Beginning
+ ? nameof(StreamPosition.Beginning)
+ : nameof(StreamPosition.NewMessages);
+ _logger.LogDebug($"Redis stream entry [{entry.Id}] [position : {positionName}] was delivered.");
+ }
+ }
}
}
}
diff --git a/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Default.cs b/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Default.cs
index ba446a8..b9b16e7 100644
--- a/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Default.cs
+++ b/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Default.cs
@@ -18,7 +18,7 @@ namespace DotNetCore.CAP.RedisStreams
private readonly IRedisConnectionPool _connectionsPool;
private readonly ILogger _logger;
private readonly CapRedisOptions _options;
- private IConnectionMultiplexer _redis;
+ private IConnectionMultiplexer? _redis;
public RedisStreamManager(IRedisConnectionPool connectionsPool, IOptions options,
ILogger logger)
@@ -33,7 +33,7 @@ namespace DotNetCore.CAP.RedisStreams
await ConnectAsync();
//The object returned from GetDatabase is a cheap pass - thru object, and does not need to be stored
- var database = _redis.GetDatabase();
+ var database = _redis!.GetDatabase();
var streamExist = await database.KeyExistsAsync(stream);
if (!streamExist)
{
@@ -53,7 +53,7 @@ namespace DotNetCore.CAP.RedisStreams
await ConnectAsync();
//The object returned from GetDatabase is a cheap pass - thru object, and does not need to be stored
- await _redis.GetDatabase().StreamAddAsync(stream, message);
+ await _redis!.GetDatabase().StreamAddAsync(stream, message);
}
public async IAsyncEnumerable> PollStreamsLatestMessagesAsync(string[] streams,
@@ -98,7 +98,7 @@ namespace DotNetCore.CAP.RedisStreams
{
await ConnectAsync();
- await _redis.GetDatabase().StreamAcknowledgeAsync(stream, consumerGroup, messageId).ConfigureAwait(false);
+ await _redis!.GetDatabase().StreamAcknowledgeAsync(stream, consumerGroup, messageId).ConfigureAwait(false);
}
private async Task> TryReadConsumerGroup(string consumerGroup,
@@ -112,7 +112,7 @@ namespace DotNetCore.CAP.RedisStreams
await ConnectAsync();
- var database = _redis.GetDatabase();
+ var database = _redis!.GetDatabase();
await foreach (var position in database.TryCreateConsumerGroup(positions, consumerGroup, _logger)
.WithCancellation(token))
diff --git a/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Extensions.cs b/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Extensions.cs
index 5250264..868ab88 100644
--- a/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Extensions.cs
+++ b/src/DotNetCore.CAP.RedisStreams/IRedisStream.Manager.Extensions.cs
@@ -11,7 +11,7 @@ namespace DotNetCore.CAP.RedisStreams
{
internal static class RedisStreamManagerExtensions
{
- public static async IAsyncEnumerable TryCreateConsumerGroup(this IDatabase database, StreamPosition[] positions, string consumerGroup, ILogger logger = null)
+ public static async IAsyncEnumerable TryCreateConsumerGroup(this IDatabase database, StreamPosition[] positions, string consumerGroup, ILogger logger)
{
foreach (var position in positions)
{
@@ -25,7 +25,7 @@ namespace DotNetCore.CAP.RedisStreams
if (await database.StreamCreateConsumerGroupAsync(stream, consumerGroup,
StreamPosition.NewMessages))
{
- logger.LogInformation(
+ logger!.LogInformation(
$"Redis stream [{position.Key}] created with consumer group [{consumerGroup}]");
created = true;
}
@@ -39,7 +39,7 @@ namespace DotNetCore.CAP.RedisStreams
if (await database.StreamCreateConsumerGroupAsync(stream, consumerGroup,
StreamPosition.NewMessages))
{
- logger.LogInformation(
+ logger!.LogInformation(
$"Redis stream [{position.Key}] created with consumer group [{consumerGroup}]");
created = true;
}
diff --git a/src/DotNetCore.CAP.RedisStreams/ITransport.Redis.cs b/src/DotNetCore.CAP.RedisStreams/ITransport.Redis.cs
index 66c46bd..9880696 100644
--- a/src/DotNetCore.CAP.RedisStreams/ITransport.Redis.cs
+++ b/src/DotNetCore.CAP.RedisStreams/ITransport.Redis.cs
@@ -25,7 +25,7 @@ namespace DotNetCore.CAP.RedisStreams
_logger = logger;
}
- public BrokerAddress BrokerAddress => new BrokerAddress("redis", _options.Endpoint);
+ public BrokerAddress BrokerAddress => new ("redis", _options.Endpoint);
public async Task SendAsync(TransportMessage message)
{
diff --git a/src/DotNetCore.CAP.RedisStreams/TransportMessage.Redis.cs b/src/DotNetCore.CAP.RedisStreams/TransportMessage.Redis.cs
index 243a688..ac055ad 100644
--- a/src/DotNetCore.CAP.RedisStreams/TransportMessage.Redis.cs
+++ b/src/DotNetCore.CAP.RedisStreams/TransportMessage.Redis.cs
@@ -23,16 +23,15 @@ namespace DotNetCore.CAP.RedisStreams
};
}
- public static TransportMessage Create(StreamEntry streamEntry, string groupId = null)
+ public static TransportMessage Create(StreamEntry streamEntry, string? groupId = null)
{
- if (streamEntry.IsNull)
- return null;
-
var headersRaw = streamEntry[Headers];
if (headersRaw.IsNullOrEmpty)
+ {
throw new ArgumentException($"Redis stream entry with id {streamEntry.Id} missing cap headers");
-
- var headers = JsonSerializer.Deserialize>(headersRaw);
+ }
+
+ var headers = JsonSerializer.Deserialize>(headersRaw)!;
var bodyRaw = streamEntry[Body];
@@ -43,8 +42,12 @@ namespace DotNetCore.CAP.RedisStreams
return new TransportMessage(headers, body);
}
- private static string ToJson(object obj)
+ private static RedisValue ToJson(object? obj)
{
+ if (obj == null)
+ {
+ return RedisValue.Null;
+ }
return JsonSerializer.Serialize(obj, new JsonSerializerOptions(JsonSerializerDefaults.Web));
}
}
diff --git a/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs b/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs
index e3d1cd2..52d1569 100644
--- a/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs
+++ b/src/DotNetCore.CAP.SqlServer/CAP.EFOptions.cs
@@ -19,14 +19,14 @@ namespace DotNetCore.CAP
///
/// EF DbContext
///
- internal Type DbContextType { get; set; }
+ internal Type? DbContextType { get; set; }
internal bool IsSqlServer2008 { get; set; }
///
/// Data version
///
- internal string Version { get; set; }
+ internal string Version { get; set; } = default!;
public EFOptions UseSqlServer2008()
{
diff --git a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs
index 513e82e..d92cb42 100644
--- a/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs
+++ b/src/DotNetCore.CAP.SqlServer/CAP.SqlServerOptions.cs
@@ -13,7 +13,7 @@ namespace DotNetCore.CAP
///
/// Gets or sets the database's connection string that will be used to store database entities.
///
- public string ConnectionString { get; set; }
+ public string ConnectionString { get; set; } = default!;
}
diff --git a/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs b/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs
index e74e3b0..59b4260 100644
--- a/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs
+++ b/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using DotNetCore.CAP.Persistence;
using DotNetCore.CAP.Transport;
@@ -11,7 +12,7 @@ using Microsoft.Data.SqlClient;
namespace DotNetCore.CAP.SqlServer.Diagnostics
{
- internal class DiagnosticObserver : IObserver>
+ internal class DiagnosticObserver : IObserver>
{
public const string SqlAfterCommitTransactionMicrosoft = "Microsoft.Data.SqlClient.WriteTransactionCommitAfter";
public const string SqlErrorCommitTransactionMicrosoft = "Microsoft.Data.SqlClient.WriteTransactionCommitError";
@@ -36,41 +37,48 @@ namespace DotNetCore.CAP.SqlServer.Diagnostics
{
}
- public void OnNext(KeyValuePair evt)
+ public void OnNext(KeyValuePair evt)
{
- if (evt.Key == SqlAfterCommitTransactionMicrosoft)
+ switch (evt.Key)
{
- if (!TryGetSqlConnection(evt, out SqlConnection sqlConnection)) return;
- var transactionKey = sqlConnection.ClientConnectionId;
- if (_bufferList.TryRemove(transactionKey, out var msgList))
+ case SqlAfterCommitTransactionMicrosoft:
{
- foreach (var message in msgList)
+ if (!TryGetSqlConnection(evt, out SqlConnection? sqlConnection)) return;
+ var transactionKey = sqlConnection.ClientConnectionId;
+ if (_bufferList.TryRemove(transactionKey, out var msgList))
{
- _dispatcher.EnqueueToPublish(message);
+ foreach (var message in msgList)
+ {
+ _dispatcher.EnqueueToPublish(message);
+ }
}
+
+ break;
}
- }
- else if (evt.Key == SqlErrorCommitTransactionMicrosoft || evt.Key == SqlAfterRollbackTransactionMicrosoft || evt.Key == SqlBeforeCloseConnectionMicrosoft)
- {
- if (!_bufferList.IsEmpty)
+ case SqlErrorCommitTransactionMicrosoft or SqlAfterRollbackTransactionMicrosoft or SqlBeforeCloseConnectionMicrosoft:
{
- if (!TryGetSqlConnection(evt, out SqlConnection sqlConnection)) return;
- var transactionKey = sqlConnection.ClientConnectionId;
+ if (!_bufferList.IsEmpty)
+ {
+ if (!TryGetSqlConnection(evt, out SqlConnection? sqlConnection)) return;
+ var transactionKey = sqlConnection.ClientConnectionId;
+
+ _bufferList.TryRemove(transactionKey, out _);
+ }
- _bufferList.TryRemove(transactionKey, out _);
+ break;
}
}
}
- private static bool TryGetSqlConnection(KeyValuePair evt, out SqlConnection sqlConnection)
+ private static bool TryGetSqlConnection(KeyValuePair evt, [NotNullWhen(true)] out SqlConnection? sqlConnection)
{
sqlConnection = GetProperty(evt.Value, "Connection") as SqlConnection;
return sqlConnection != null;
}
- private static object GetProperty(object _this, string propertyName)
+ private static object? GetProperty(object? @this, string propertyName)
{
- return _this.GetType().GetTypeInfo().GetDeclaredProperty(propertyName)?.GetValue(_this);
+ return @this?.GetType().GetTypeInfo().GetDeclaredProperty(propertyName)?.GetValue(@this);
}
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs b/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs
index ea14ca2..8027497 100644
--- a/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs
+++ b/src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs
@@ -34,7 +34,9 @@ namespace DotNetCore.CAP.SqlServer.Diagnostics
public void OnNext(DiagnosticListener listener)
{
if (listener.Name == DiagnosticListenerName)
+ {
listener.Subscribe(new DiagnosticObserver(_dispatcher, BufferList));
+ }
}
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP.SqlServer/DotNetCore.CAP.SqlServer.csproj b/src/DotNetCore.CAP.SqlServer/DotNetCore.CAP.SqlServer.csproj
index 4be0173..768097e 100644
--- a/src/DotNetCore.CAP.SqlServer/DotNetCore.CAP.SqlServer.csproj
+++ b/src/DotNetCore.CAP.SqlServer/DotNetCore.CAP.SqlServer.csproj
@@ -2,14 +2,8 @@
net6.0;netstandard2.1
- DotNetCore.CAP.SqlServer
+ enable
$(PackageTags);SQL Server
-
-
-
-
- bin\$(Configuration)\netstandard2.1\DotNetCore.CAP.SqlServer.xml
- 1701;1702;1705;CS1591
diff --git a/src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs b/src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs
index eba585f..f89270c 100644
--- a/src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs
+++ b/src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs
@@ -46,7 +46,7 @@ namespace DotNetCore.CAP
if (dbTransaction == null) throw new ArgumentNullException(nameof(DbTransaction));
}
- var transactionKey = ((SqlConnection)dbTransaction.Connection).ClientConnectionId;
+ var transactionKey = ((SqlConnection)dbTransaction.Connection!).ClientConnectionId;
if (_diagnosticProcessor.BufferList.TryGetValue(transactionKey, out var list))
{
list.Add(msg);
@@ -166,7 +166,7 @@ namespace DotNetCore.CAP
var dbTransaction = dbConnection.BeginTransaction();
publisher.Transaction.Value = ActivatorUtilities.CreateInstance(publisher.ServiceProvider);
var capTransaction = publisher.Transaction.Value.Begin(dbTransaction, autoCommit);
- return (IDbTransaction)capTransaction.DbTransaction;
+ return (IDbTransaction)capTransaction.DbTransaction!;
}
///
diff --git a/src/DotNetCore.CAP.SqlServer/IDataStorage.SqlServer.cs b/src/DotNetCore.CAP.SqlServer/IDataStorage.SqlServer.cs
index e2fd969..b5432cc 100644
--- a/src/DotNetCore.CAP.SqlServer/IDataStorage.SqlServer.cs
+++ b/src/DotNetCore.CAP.SqlServer/IDataStorage.SqlServer.cs
@@ -46,7 +46,7 @@ namespace DotNetCore.CAP.SqlServer
public async Task ChangeReceiveStateAsync(MediumMessage message, StatusName state) =>
await ChangeMessageStateAsync(_recName, message, state);
- public MediumMessage StoreMessage(string name, Message content, object dbTransaction = null)
+ public MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null)
{
var sql = $"INSERT INTO {_pubName} ([Id],[Version],[Name],[Content],[Retries],[Added],[ExpiresAt],[StatusName])" +
$"VALUES(@Id,'{_options.Value.Version}',@Name,@Content,@Retries,@Added,@ExpiresAt,@StatusName);";
@@ -84,7 +84,7 @@ namespace DotNetCore.CAP.SqlServer
dbTrans = dbContextTrans.GetDbTransaction();
var conn = dbTrans?.Connection;
- conn.ExecuteNonQuery(sql, dbTrans, sqlParams);
+ conn!.ExecuteNonQuery(sql, dbTrans, sqlParams);
}
return message;
@@ -126,7 +126,7 @@ namespace DotNetCore.CAP.SqlServer
new SqlParameter("@Content", _serializer.Serialize(mdMessage.Origin)),
new SqlParameter("@Retries", mdMessage.Retries),
new SqlParameter("@Added", mdMessage.Added),
- new SqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? (object) mdMessage.ExpiresAt.Value : DBNull.Value),
+ new SqlParameter("@ExpiresAt", mdMessage.ExpiresAt.HasValue ? mdMessage.ExpiresAt.Value : DBNull.Value),
new SqlParameter("@StatusName", nameof(StatusName.Scheduled))
};
@@ -200,7 +200,7 @@ namespace DotNetCore.CAP.SqlServer
messages.Add(new MediumMessage
{
DbId = reader.GetInt64(0).ToString(),
- Origin = _serializer.Deserialize(reader.GetString(1)),
+ Origin = _serializer.Deserialize(reader.GetString(1))!,
Retries = reader.GetInt32(2),
Added = reader.GetDateTime(3)
});
diff --git a/src/DotNetCore.CAP.SqlServer/IDbConnection.Extensions.cs b/src/DotNetCore.CAP.SqlServer/IDbConnection.Extensions.cs
index ba7dbce..b2a905e 100644
--- a/src/DotNetCore.CAP.SqlServer/IDbConnection.Extensions.cs
+++ b/src/DotNetCore.CAP.SqlServer/IDbConnection.Extensions.cs
@@ -9,7 +9,7 @@ namespace DotNetCore.CAP.SqlServer
{
internal static class DbConnectionExtensions
{
- public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction transaction = null,
+ public static int ExecuteNonQuery(this IDbConnection connection, string sql, IDbTransaction? transaction = null,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -33,7 +33,7 @@ namespace DotNetCore.CAP.SqlServer
return command.ExecuteNonQuery();
}
- public static T ExecuteReader(this IDbConnection connection, string sql, Func readerFunc,
+ public static T ExecuteReader(this IDbConnection connection, string sql, Func? readerFunc,
params object[] sqlParams)
{
if (connection.State == ConnectionState.Closed)
@@ -51,7 +51,7 @@ namespace DotNetCore.CAP.SqlServer
var reader = command.ExecuteReader();
- T result = default;
+ T result = default!;
if (readerFunc != null)
{
result = readerFunc(reader);
@@ -77,14 +77,14 @@ namespace DotNetCore.CAP.SqlServer
var objValue = command.ExecuteScalar();
- T result = default;
+ T result = default!;
if (objValue != null)
{
var returnType = typeof(T);
var converter = TypeDescriptor.GetConverter(returnType);
if (converter.CanConvertFrom(objValue.GetType()))
{
- result = (T)converter.ConvertFrom(objValue);
+ result = (T)converter.ConvertFrom(objValue)!;
}
else
{
diff --git a/src/DotNetCore.CAP.SqlServer/IDbContextTransaction.CAP.cs b/src/DotNetCore.CAP.SqlServer/IDbContextTransaction.CAP.cs
index cbeb745..7739159 100644
--- a/src/DotNetCore.CAP.SqlServer/IDbContextTransaction.CAP.cs
+++ b/src/DotNetCore.CAP.SqlServer/IDbContextTransaction.CAP.cs
@@ -18,7 +18,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
public CapEFDbTransaction(ICapTransaction transaction)
{
_transaction = transaction;
- var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction!;
TransactionId = dbContextTransaction.TransactionId;
}
@@ -58,7 +58,7 @@ namespace Microsoft.EntityFrameworkCore.Storage
{
get
{
- var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction;
+ var dbContextTransaction = (IDbContextTransaction)_transaction.DbTransaction!;
return dbContextTransaction.GetDbTransaction();
}
}
diff --git a/src/DotNetCore.CAP.SqlServer/IMonitoringApi.SqlServer.cs b/src/DotNetCore.CAP.SqlServer/IMonitoringApi.SqlServer.cs
index 5ae9333..925b16e 100644
--- a/src/DotNetCore.CAP.SqlServer/IMonitoringApi.SqlServer.cs
+++ b/src/DotNetCore.CAP.SqlServer/IMonitoringApi.SqlServer.cs
@@ -131,7 +131,7 @@ SELECT
Content = reader.GetString(index++),
Retries = reader.GetInt32(index++),
Added = reader.GetDateTime(index++),
- ExpiresAt = reader.IsDBNull(index++) ? (DateTime?)null : reader.GetDateTime(index - 1),
+ ExpiresAt = reader.IsDBNull(index++) ? null : reader.GetDateTime(index - 1),
StatusName = reader.GetString(index)
});
}
@@ -162,9 +162,9 @@ SELECT
return GetNumberOfMessage(_recName, nameof(StatusName.Succeeded));
}
- public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
+ public async Task GetPublishedMessageAsync(long id) => await GetMessageAsync(_pubName, id);
- public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
+ public async Task GetReceivedMessageAsync(long id) => await GetMessageAsync(_recName, id);
private int GetNumberOfMessage(string tableName, string statusName)
{
@@ -254,14 +254,14 @@ select [Key], [Count] from aggr with (nolock) where [Key] >= @minKey and [Key] <
return result;
}
- private async Task GetMessageAsync(string tableName, long id)
+ private async Task GetMessageAsync(string tableName, long id)
{
var sql = $@"SELECT TOP 1 Id AS DbId, Content, Added, ExpiresAt, Retries FROM {tableName} WITH (readpast) WHERE Id={id}";
await using var connection = new SqlConnection(_options.ConnectionString);
var mediumMessage = connection.ExecuteReader(sql, reader =>
{
- MediumMessage message = null;
+ MediumMessage? message = null;
while (reader.Read())
{
diff --git a/src/DotNetCore.CAP/CAP.Attribute.cs b/src/DotNetCore.CAP/CAP.Attribute.cs
index d2c886d..63eef9e 100644
--- a/src/DotNetCore.CAP/CAP.Attribute.cs
+++ b/src/DotNetCore.CAP/CAP.Attribute.cs
@@ -29,9 +29,9 @@ namespace DotNetCore.CAP
}
- public class CapHeader : ReadOnlyDictionary
+ public class CapHeader : ReadOnlyDictionary
{
- public CapHeader(IDictionary dictionary) : base(dictionary)
+ public CapHeader(IDictionary dictionary) : base(dictionary)
{
}
diff --git a/src/DotNetCore.CAP/CAP.Builder.cs b/src/DotNetCore.CAP/CAP.Builder.cs
index 8cbf830..99c3eba 100644
--- a/src/DotNetCore.CAP/CAP.Builder.cs
+++ b/src/DotNetCore.CAP/CAP.Builder.cs
@@ -6,7 +6,6 @@ using System.Linq;
using System.Reflection;
using DotNetCore.CAP.Filter;
using DotNetCore.CAP.Internal;
-using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
// ReSharper disable UnusedMember.Global
@@ -78,7 +77,7 @@ namespace DotNetCore.CAP
/// Registers subscribers from the specified types.
///
///
- public CapBuilder AddSubscriberAssembly([NotNull] params Type[] handlerAssemblyMarkerTypes)
+ public CapBuilder AddSubscriberAssembly(params Type[] handlerAssemblyMarkerTypes)
{
if (handlerAssemblyMarkerTypes == null) throw new ArgumentNullException(nameof(handlerAssemblyMarkerTypes));
diff --git a/src/DotNetCore.CAP/CAP.Options.cs b/src/DotNetCore.CAP/CAP.Options.cs
index 3a2c8ce..735b986 100644
--- a/src/DotNetCore.CAP/CAP.Options.cs
+++ b/src/DotNetCore.CAP/CAP.Options.cs
@@ -40,12 +40,12 @@ namespace DotNetCore.CAP
///
/// Subscriber group prefix.
///
- public string GroupNamePrefix { get; set; }
+ public string? GroupNamePrefix { get; set; }
///
/// Topic prefix.
///
- public string TopicNamePrefix { get; set; }
+ public string? TopicNamePrefix { get; set; }
///
/// The default version of the message, configured to isolate data in the same instance. The length must not exceed 20
@@ -67,7 +67,7 @@ namespace DotNetCore.CAP
///
/// We’ll invoke this call-back with message type,name,content when retry failed (send or executed) messages equals times.
///
- public Action FailedThresholdCallback { get; set; }
+ public Action? FailedThresholdCallback { get; set; }
///
/// The number of message retries, the retry will stop when the threshold is reached.
@@ -116,6 +116,6 @@ namespace DotNetCore.CAP
///
/// Configure JSON serialization settings
///
- public JsonSerializerOptions JsonSerializerOptions { get; } = new JsonSerializerOptions();
+ public JsonSerializerOptions JsonSerializerOptions { get; } = new ();
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Cap.P.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Cap.P.cs
index 2154c4c..fcd3bcd 100644
--- a/src/DotNetCore.CAP/Diagnostics/EventData.Cap.P.cs
+++ b/src/DotNetCore.CAP/Diagnostics/EventData.Cap.P.cs
@@ -8,27 +8,27 @@ namespace DotNetCore.CAP.Diagnostics
{
public long? OperationTimestamp { get; set; }
- public string Operation { get; set; }
+ public string Operation { get; set; } = default!;
- public Message Message { get; set; }
+ public Message Message { get; set; } = default!;
public long? ElapsedTimeMs { get; set; }
- public Exception Exception { get; set; }
+ public Exception? Exception { get; set; }
}
public class CapEventDataPubSend
{
public long? OperationTimestamp { get; set; }
- public string Operation { get; set; }
+ public string Operation { get; set; } = default!;
- public TransportMessage TransportMessage { get; set; }
+ public TransportMessage TransportMessage { get; set; } = default!;
public BrokerAddress BrokerAddress { get; set; }
public long? ElapsedTimeMs { get; set; }
- public Exception Exception { get; set; }
+ public Exception? Exception { get; set; }
}
}
diff --git a/src/DotNetCore.CAP/Diagnostics/EventData.Cap.S.cs b/src/DotNetCore.CAP/Diagnostics/EventData.Cap.S.cs
index c8fbd58..c1ff18e 100644
--- a/src/DotNetCore.CAP/Diagnostics/EventData.Cap.S.cs
+++ b/src/DotNetCore.CAP/Diagnostics/EventData.Cap.S.cs
@@ -5,7 +5,6 @@ using System;
using System.Reflection;
using DotNetCore.CAP.Messages;
using DotNetCore.CAP.Transport;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Diagnostics
{
@@ -13,30 +12,29 @@ namespace DotNetCore.CAP.Diagnostics
{
public long? OperationTimestamp { get; set; }
- public string Operation { get; set; }
+ public string Operation { get; set; } = default!;
- public TransportMessage TransportMessage { get; set; }
+ public TransportMessage TransportMessage { get; set; } = default!;
public BrokerAddress BrokerAddress { get; set; }
public long? ElapsedTimeMs { get; set; }
- public Exception Exception { get; set; }
+ public Exception? Exception { get; set; }
}
public class CapEventDataSubExecute
{
public long? OperationTimestamp { get; set; }
- public string Operation { get; set; }
+ public string Operation { get; set; } = default!;
- public Message Message { get; set; }
+ public Message Message { get; set; } = default!;
- [CanBeNull]
- public MethodInfo MethodInfo { get; set; }
+ public MethodInfo? MethodInfo { get; set; }
public long? ElapsedTimeMs { get; set; }
- public Exception Exception { get; set; }
+ public Exception? Exception { get; set; }
}
}
diff --git a/src/DotNetCore.CAP/DotNetCore.CAP.csproj b/src/DotNetCore.CAP/DotNetCore.CAP.csproj
index 914d50d..828296d 100644
--- a/src/DotNetCore.CAP/DotNetCore.CAP.csproj
+++ b/src/DotNetCore.CAP/DotNetCore.CAP.csproj
@@ -2,6 +2,7 @@
netstandard2.1
+ enable
diff --git a/src/DotNetCore.CAP/ICapPublisher.cs b/src/DotNetCore.CAP/ICapPublisher.cs
index 158417d..1cc46b5 100644
--- a/src/DotNetCore.CAP/ICapPublisher.cs
+++ b/src/DotNetCore.CAP/ICapPublisher.cs
@@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using JetBrains.Annotations;
namespace DotNetCore.CAP
{
@@ -28,7 +27,7 @@ namespace DotNetCore.CAP
/// message body content, that will be serialized. (can be null)
/// callback subscriber name
///
- Task PublishAsync(string name, [CanBeNull] T contentObj, string callbackName = null, CancellationToken cancellationToken = default);
+ Task PublishAsync(string name, T? contentObj, string? callbackName = null, CancellationToken cancellationToken = default);
///
/// Asynchronous publish an object message with custom headers
@@ -38,7 +37,7 @@ namespace DotNetCore.CAP
/// message body content, that will be serialized. (can be null)
/// message additional headers.
///
- Task PublishAsync(string name, [CanBeNull] T contentObj, IDictionary headers, CancellationToken cancellationToken = default);
+ Task PublishAsync(string name, T? contentObj, IDictionary headers, CancellationToken cancellationToken = default);
///
/// Publish an object message.
@@ -46,7 +45,7 @@ namespace DotNetCore.CAP
/// the topic name or exchange router key.
/// message body content, that will be serialized. (can be null)
/// callback subscriber name
- void Publish(string name, [CanBeNull] T contentObj, string callbackName = null);
+ void Publish(string name, T? contentObj, string? callbackName = null);
///
/// Publish an object message.
@@ -54,6 +53,6 @@ namespace DotNetCore.CAP
/// the topic name or exchange router key.
/// message body content, that will be serialized. (can be null)
/// message additional headers.
- void Publish(string name, [CanBeNull] T contentObj, IDictionary headers);
+ void Publish(string name, T? contentObj, IDictionary headers);
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/ICapTransaction.Base.cs b/src/DotNetCore.CAP/ICapTransaction.Base.cs
index 5a35fca..dc774df 100644
--- a/src/DotNetCore.CAP/ICapTransaction.Base.cs
+++ b/src/DotNetCore.CAP/ICapTransaction.Base.cs
@@ -23,7 +23,7 @@ namespace DotNetCore.CAP
public bool AutoCommit { get; set; }
- public object DbTransaction { get; set; }
+ public object? DbTransaction { get; set; }
protected internal virtual void AddToSent(MediumMessage msg)
{
diff --git a/src/DotNetCore.CAP/ICapTransaction.cs b/src/DotNetCore.CAP/ICapTransaction.cs
index 3892ed1..304626b 100644
--- a/src/DotNetCore.CAP/ICapTransaction.cs
+++ b/src/DotNetCore.CAP/ICapTransaction.cs
@@ -20,7 +20,7 @@ namespace DotNetCore.CAP
///
/// Database transaction object, can be converted to a specific database transaction object or IDBTransaction when used
///
- object DbTransaction { get; set; }
+ object? DbTransaction { get; set; }
///
/// Submit the transaction context of the CAP, we will send the message to the message queue at the time of submission
diff --git a/src/DotNetCore.CAP/Internal/ConsumerExecutedResult.cs b/src/DotNetCore.CAP/Internal/ConsumerExecutedResult.cs
index 22f6a60..8eec874 100644
--- a/src/DotNetCore.CAP/Internal/ConsumerExecutedResult.cs
+++ b/src/DotNetCore.CAP/Internal/ConsumerExecutedResult.cs
@@ -5,17 +5,17 @@ namespace DotNetCore.CAP.Internal
{
public class ConsumerExecutedResult
{
- public ConsumerExecutedResult(object result, string msgId, string callbackName)
+ public ConsumerExecutedResult(object? result, string msgId, string? callbackName)
{
Result = result;
MessageId = msgId;
CallbackName = callbackName;
}
- public object Result { get; set; }
+ public object? Result { get; set; }
public string MessageId { get; set; }
- public string CallbackName { get; set; }
+ public string? CallbackName { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ConsumerExecutorDescriptor.cs b/src/DotNetCore.CAP/Internal/ConsumerExecutorDescriptor.cs
index 0e61ba3..c4e57cc 100644
--- a/src/DotNetCore.CAP/Internal/ConsumerExecutorDescriptor.cs
+++ b/src/DotNetCore.CAP/Internal/ConsumerExecutorDescriptor.cs
@@ -12,21 +12,21 @@ namespace DotNetCore.CAP.Internal
///
public class ConsumerExecutorDescriptor
{
- public TypeInfo ServiceTypeInfo { get; set; }
+ public TypeInfo? ServiceTypeInfo { get; set; }
- public MethodInfo MethodInfo { get; set; }
+ public MethodInfo MethodInfo { get; set; } = default!;
- public TypeInfo ImplTypeInfo { get; set; }
+ public TypeInfo ImplTypeInfo { get; set; } = default!;
- public TopicAttribute Attribute { get; set; }
+ public TopicAttribute Attribute { get; set; } = default!;
- public TopicAttribute ClassAttribute { get; set; }
+ public TopicAttribute? ClassAttribute { get; set; }
- public IList Parameters { get; set; }
+ public IList Parameters { get; set; } = new List();
- public string TopicNamePrefix { get; set; }
+ public string? TopicNamePrefix { get; set; }
- private string _topicName;
+ private string? _topicName;
///
/// Topic name based on both and .
///
@@ -58,7 +58,7 @@ namespace DotNetCore.CAP.Internal
public class ConsumerExecutorDescriptorComparer : IEqualityComparer
{
- public bool Equals(ConsumerExecutorDescriptor x, ConsumerExecutorDescriptor y)
+ public bool Equals(ConsumerExecutorDescriptor? x, ConsumerExecutorDescriptor? y)
{
//Check whether the compared objects reference the same data.
if (ReferenceEquals(x, y))
@@ -77,7 +77,7 @@ namespace DotNetCore.CAP.Internal
x.Attribute.Group.Equals(y.Attribute.Group, StringComparison.OrdinalIgnoreCase);
}
- public int GetHashCode(ConsumerExecutorDescriptor obj)
+ public int GetHashCode(ConsumerExecutorDescriptor? obj)
{
//Check whether the object is null
if (obj is null) return 0;
@@ -95,9 +95,9 @@ namespace DotNetCore.CAP.Internal
public class ParameterDescriptor
{
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
- public Type ParameterType { get; set; }
+ public Type ParameterType { get; set; } = default!;
public bool IsFromCap { get; set; }
}
diff --git a/src/DotNetCore.CAP/Internal/Filter/ExceptionContext.cs b/src/DotNetCore.CAP/Internal/Filter/ExceptionContext.cs
index 576ca08..fa3086c 100644
--- a/src/DotNetCore.CAP/Internal/Filter/ExceptionContext.cs
+++ b/src/DotNetCore.CAP/Internal/Filter/ExceptionContext.cs
@@ -19,6 +19,6 @@ namespace DotNetCore.CAP.Filter
public bool ExceptionHandled { get; set; }
- public object Result { get; set; }
+ public object? Result { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/Filter/ExecutedContext.cs b/src/DotNetCore.CAP/Internal/Filter/ExecutedContext.cs
index ede0ce2..b4e771f 100644
--- a/src/DotNetCore.CAP/Internal/Filter/ExecutedContext.cs
+++ b/src/DotNetCore.CAP/Internal/Filter/ExecutedContext.cs
@@ -8,11 +8,11 @@ namespace DotNetCore.CAP.Filter
{
public class ExecutedContext : FilterContext
{
- public ExecutedContext(ConsumerContext context, object result) : base(context)
+ public ExecutedContext(ConsumerContext context, object? result) : base(context)
{
Result = result;
}
- public object Result { get; set; }
+ public object? Result { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/Filter/ExecutingContext.cs b/src/DotNetCore.CAP/Internal/Filter/ExecutingContext.cs
index 1eed760..a393eee 100644
--- a/src/DotNetCore.CAP/Internal/Filter/ExecutingContext.cs
+++ b/src/DotNetCore.CAP/Internal/Filter/ExecutingContext.cs
@@ -8,11 +8,11 @@ namespace DotNetCore.CAP.Filter
{
public class ExecutingContext : FilterContext
{
- public ExecutingContext(ConsumerContext context, object[] arguments) : base(context)
+ public ExecutingContext(ConsumerContext context, object?[] arguments) : base(context)
{
Arguments = arguments;
}
- public object[] Arguments { get; set; }
+ public object?[] Arguments { get; set; }
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/Helper.cs b/src/DotNetCore.CAP/Internal/Helper.cs
index 2f0a3ed..402a007 100644
--- a/src/DotNetCore.CAP/Internal/Helper.cs
+++ b/src/DotNetCore.CAP/Internal/Helper.cs
@@ -10,15 +10,6 @@ namespace DotNetCore.CAP.Internal
{
public static class Helper
{
- private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local)
- .AddHours(TimeZoneInfo.Local.BaseUtcOffset.Hours);
-
- public static long ToTimestamp(DateTime value)
- {
- var elapsedTime = value - Epoch;
- return (long)elapsedTime.TotalSeconds;
- }
-
public static bool IsController(TypeInfo typeInfo)
{
if (!typeInfo.IsClass)
diff --git a/src/DotNetCore.CAP/Internal/IBootstrapper.Default.cs b/src/DotNetCore.CAP/Internal/IBootstrapper.Default.cs
index 3b21f38..9ed2cf0 100644
--- a/src/DotNetCore.CAP/Internal/IBootstrapper.Default.cs
+++ b/src/DotNetCore.CAP/Internal/IBootstrapper.Default.cs
@@ -19,8 +19,9 @@ namespace DotNetCore.CAP.Internal
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger _logger;
- private IEnumerable _processors;
- private CancellationTokenSource _cts = new CancellationTokenSource();
+ private readonly CancellationTokenSource _cts = new ();
+ private bool _disposed;
+ private IEnumerable _processors = default!;
public Bootstrapper(IServiceProvider serviceProvider, ILogger logger)
{
@@ -93,9 +94,13 @@ namespace DotNetCore.CAP.Internal
public override void Dispose()
{
- _cts?.Cancel();
- _cts?.Dispose();
- _cts = null;
+ if (_disposed)
+ {
+ return;
+ }
+ _cts.Cancel();
+ _cts.Dispose();
+ _disposed = true;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
@@ -105,7 +110,7 @@ namespace DotNetCore.CAP.Internal
public override async Task StopAsync(CancellationToken cancellationToken)
{
- _cts?.Cancel();
+ _cts.Cancel();
await base.StopAsync(cancellationToken);
}
diff --git a/src/DotNetCore.CAP/Internal/ICapPublisher.Default.cs b/src/DotNetCore.CAP/Internal/ICapPublisher.Default.cs
index 1b9c7b4..62ffa5e 100644
--- a/src/DotNetCore.CAP/Internal/ICapPublisher.Default.cs
+++ b/src/DotNetCore.CAP/Internal/ICapPublisher.Default.cs
@@ -22,8 +22,7 @@ namespace DotNetCore.CAP.Internal
private readonly CapOptions _capOptions;
// ReSharper disable once InconsistentNaming
- protected static readonly DiagnosticListener s_diagnosticListener =
- new DiagnosticListener(CapDiagnosticListenerNames.DiagnosticListenerName);
+ protected static readonly DiagnosticListener s_diagnosticListener = new(CapDiagnosticListenerNames.DiagnosticListenerName);
public CapPublisher(IServiceProvider service)
{
@@ -38,20 +37,20 @@ namespace DotNetCore.CAP.Internal
public AsyncLocal Transaction { get; }
- public Task PublishAsync(string name, T value, IDictionary headers, CancellationToken cancellationToken = default)
+ public Task PublishAsync(string name, T? value, IDictionary headers, CancellationToken cancellationToken = default)
{
return Task.Run(() => Publish(name, value, headers), cancellationToken);
}
- public Task PublishAsync(string name, T value, string callbackName = null,
+ public Task PublishAsync(string name, T? value, string? callbackName = null,
CancellationToken cancellationToken = default)
{
return Task.Run(() => Publish(name, value, callbackName), cancellationToken);
}
- public void Publish(string name, T value, string callbackName = null)
+ public void Publish(string name, T? value, string? callbackName = null)
{
- var header = new Dictionary
+ var header = new Dictionary
{
{Headers.CallbackName, callbackName}
};
@@ -59,7 +58,7 @@ namespace DotNetCore.CAP.Internal
Publish(name, value, header);
}
- public void Publish(string name, T value, IDictionary headers)
+ public void Publish(string name, T? value, IDictionary headers)
{
if (string.IsNullOrEmpty(name))
{
@@ -71,14 +70,12 @@ namespace DotNetCore.CAP.Internal
name = $"{_capOptions.TopicNamePrefix}.{name}";
}
- headers ??= new Dictionary();
-
if (!headers.ContainsKey(Headers.MessageId))
{
var messageId = SnowflakeId.Default().NextId().ToString();
headers.Add(Headers.MessageId, messageId);
}
-
+
if (!headers.ContainsKey(Headers.CorrelationId))
{
headers.Add(Headers.CorrelationId, headers[Headers.MessageId]);
diff --git a/src/DotNetCore.CAP/Internal/IConsumerRegister.Default.cs b/src/DotNetCore.CAP/Internal/IConsumerRegister.Default.cs
index ebd7265..b78e264 100644
--- a/src/DotNetCore.CAP/Internal/IConsumerRegister.Default.cs
+++ b/src/DotNetCore.CAP/Internal/IConsumerRegister.Default.cs
@@ -25,15 +25,15 @@ namespace DotNetCore.CAP.Internal
private readonly TimeSpan _pollingDelay = TimeSpan.FromSeconds(1);
private readonly CapOptions _options;
- private IConsumerClientFactory _consumerClientFactory;
- private IDispatcher _dispatcher;
- private ISerializer _serializer;
- private IDataStorage _storage;
+ private IConsumerClientFactory _consumerClientFactory = default!;
+ private IDispatcher _dispatcher = default!;
+ private ISerializer _serializer = default!;
+ private IDataStorage _storage = default!;
- private MethodMatcherCache _selector;
- private CancellationTokenSource _cts;
+ private MethodMatcherCache _selector = default!;
+ private CancellationTokenSource _cts = new();
private BrokerAddress _serverAddress;
- private Task _compositeTask;
+ private Task? _compositeTask;
private bool _disposed;
private bool _isHealthy = true;
@@ -47,7 +47,6 @@ namespace DotNetCore.CAP.Internal
_logger = logger;
_serviceProvider = serviceProvider;
_options = serviceProvider.GetRequiredService>().Value;
- _cts = new CancellationTokenSource();
}
public bool IsHealthy()
@@ -57,13 +56,13 @@ namespace DotNetCore.CAP.Internal
public void Start(CancellationToken stoppingToken)
{
- _selector = _serviceProvider.GetService();
- _dispatcher = _serviceProvider.GetService();
- _serializer = _serviceProvider.GetService();
- _storage = _serviceProvider.GetService();
- _consumerClientFactory = _serviceProvider.GetService();
+ _selector = _serviceProvider.GetRequiredService();
+ _dispatcher = _serviceProvider.GetRequiredService();
+ _serializer = _serviceProvider.GetRequiredService();
+ _storage = _serviceProvider.GetRequiredService();
+ _consumerClientFactory = _serviceProvider.GetRequiredService();
- stoppingToken.Register(() => _cts?.Cancel());
+ stoppingToken.Register(Dispose);
Execute();
}
@@ -131,7 +130,7 @@ namespace DotNetCore.CAP.Internal
if (!IsHealthy() || force)
{
Pulse();
-
+
_cts = new CancellationTokenSource();
_isHealthy = true;
@@ -166,9 +165,8 @@ namespace DotNetCore.CAP.Internal
public void Pulse()
{
- _cts?.Cancel();
- _cts?.Dispose();
- _cts = null;
+ _cts.Cancel();
+ _cts.Dispose();
}
private void RegisterMessageProcessor(IConsumerClient client)
@@ -184,7 +182,7 @@ namespace DotNetCore.CAP.Internal
tracingTimestamp = TracingBefore(transportMessage, _serverAddress);
var name = transportMessage.GetName();
- var group = transportMessage.GetGroup();
+ var group = transportMessage.GetGroup()!;
Message message;
@@ -201,21 +199,36 @@ namespace DotNetCore.CAP.Internal
throw ex;
}
- var type = executor.Parameters.FirstOrDefault(x => x.IsFromCap == false)?.ParameterType;
+ var type = executor!.Parameters.FirstOrDefault(x => x.IsFromCap == false)?.ParameterType;
message = _serializer.DeserializeAsync(transportMessage, type).GetAwaiter().GetResult();
message.RemoveException();
}
catch (Exception e)
{
transportMessage.Headers[Headers.Exception] = e.GetType().Name + "-->" + e.Message;
+ string? dataUri;
if (transportMessage.Headers.TryGetValue(Headers.Type, out var val))
{
- var dataUri = $"data:{val};base64," + Convert.ToBase64String(transportMessage.Body);
+ if (transportMessage.Body != null)
+ {
+ dataUri = $"data:{val};base64," + Convert.ToBase64String(transportMessage.Body);
+ }
+ else
+ {
+ dataUri = null;
+ }
message = new Message(transportMessage.Headers, dataUri);
}
else
{
- var dataUri = "data:UnknownType;base64," + Convert.ToBase64String(transportMessage.Body);
+ if (transportMessage.Body != null)
+ {
+ dataUri = "data:UnknownType;base64," + Convert.ToBase64String(transportMessage.Body);
+ }
+ else
+ {
+ dataUri = null;
+ }
message = new Message(transportMessage.Headers, dataUri);
}
}
@@ -255,7 +268,7 @@ namespace DotNetCore.CAP.Internal
TracingAfter(tracingTimestamp, transportMessage, _serverAddress);
- _dispatcher.EnqueueToExecute(mediumMessage, executor);
+ _dispatcher.EnqueueToExecute(mediumMessage, executor!);
}
}
catch (Exception e)
diff --git a/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.Default.cs b/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.Default.cs
index 8939e0a..f0a7a0d 100644
--- a/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.Default.cs
+++ b/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.Default.cs
@@ -33,7 +33,7 @@ namespace DotNetCore.CAP.Internal
public ConsumerServiceSelector(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
- _capOptions = serviceProvider.GetService>().Value;
+ _capOptions = serviceProvider.GetRequiredService>().Value;
_cacheList = new ConcurrentDictionary>>();
}
@@ -51,7 +51,7 @@ namespace DotNetCore.CAP.Internal
return executorDescriptorList;
}
- public ConsumerExecutorDescriptor SelectBestCandidate(string key, IReadOnlyList executeDescriptor)
+ public ConsumerExecutorDescriptor? SelectBestCandidate(string key, IReadOnlyList executeDescriptor)
{
if (executeDescriptor.Count == 0)
{
@@ -107,7 +107,7 @@ namespace DotNetCore.CAP.Internal
{
var executorDescriptorList = new List();
- var types = Assembly.GetEntryAssembly().ExportedTypes;
+ var types = Assembly.GetEntryAssembly()!.ExportedTypes;
foreach (var type in types)
{
var typeInfo = type.GetTypeInfo();
@@ -120,7 +120,7 @@ namespace DotNetCore.CAP.Internal
return executorDescriptorList;
}
- protected IEnumerable GetTopicAttributesDescription(TypeInfo typeInfo, TypeInfo serviceTypeInfo = null)
+ protected IEnumerable GetTopicAttributesDescription(TypeInfo typeInfo, TypeInfo? serviceTypeInfo = null)
{
var topicClassAttribute = typeInfo.GetCustomAttribute(true);
@@ -169,9 +169,9 @@ namespace DotNetCore.CAP.Internal
TopicAttribute attr,
MethodInfo methodInfo,
TypeInfo implType,
- TypeInfo serviceTypeInfo,
+ TypeInfo? serviceTypeInfo,
IList parameters,
- TopicAttribute classAttr = null)
+ TopicAttribute? classAttr = null)
{
var descriptor = new ConsumerExecutorDescriptor
{
@@ -187,7 +187,7 @@ namespace DotNetCore.CAP.Internal
return descriptor;
}
- private ConsumerExecutorDescriptor MatchUsingName(string key, IReadOnlyList executeDescriptor)
+ private ConsumerExecutorDescriptor? MatchUsingName(string key, IReadOnlyList executeDescriptor)
{
if (key == null)
{
@@ -197,7 +197,7 @@ namespace DotNetCore.CAP.Internal
return executeDescriptor.FirstOrDefault(x => x.TopicName.Equals(key, StringComparison.InvariantCultureIgnoreCase));
}
- private ConsumerExecutorDescriptor MatchWildcardUsingRegex(string key, IReadOnlyList executeDescriptor)
+ private ConsumerExecutorDescriptor? MatchWildcardUsingRegex(string key, IReadOnlyList executeDescriptor)
{
var group = executeDescriptor.First().Attribute.Group;
if (!_cacheList.TryGetValue(group, out var tmpList))
@@ -223,9 +223,9 @@ namespace DotNetCore.CAP.Internal
private class RegexExecuteDescriptor
{
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
- public T Descriptor { get; set; }
+ public T Descriptor { get; set; } = default!;
}
}
}
diff --git a/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.cs b/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.cs
index baea9af..5954a25 100644
--- a/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.cs
+++ b/src/DotNetCore.CAP/Internal/IConsumerServiceSelector.cs
@@ -22,6 +22,6 @@ namespace DotNetCore.CAP.Internal
///
/// topic or exchange router key.
/// the set of candidates.
- ConsumerExecutorDescriptor SelectBestCandidate(string key, IReadOnlyList candidates);
+ ConsumerExecutorDescriptor? SelectBestCandidate(string key, IReadOnlyList candidates);
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/IMessageSender.Default.cs b/src/DotNetCore.CAP/Internal/IMessageSender.Default.cs
index 76792d6..760c09b 100644
--- a/src/DotNetCore.CAP/Internal/IMessageSender.Default.cs
+++ b/src/DotNetCore.CAP/Internal/IMessageSender.Default.cs
@@ -26,8 +26,7 @@ namespace DotNetCore.CAP.Internal
private readonly IOptions _options;
// ReSharper disable once InconsistentNaming
- protected static readonly DiagnosticListener s_diagnosticListener =
- new DiagnosticListener(CapDiagnosticListenerNames.DiagnosticListenerName);
+ protected static readonly DiagnosticListener s_diagnosticListener = new(CapDiagnosticListenerNames.DiagnosticListenerName);
public MessageSender(
ILogger logger,
@@ -36,10 +35,10 @@ namespace DotNetCore.CAP.Internal
_logger = logger;
_serviceProvider = serviceProvider;
- _options = serviceProvider.GetService>();
- _dataStorage = serviceProvider.GetService();
- _serializer = serviceProvider.GetService();
- _transport = serviceProvider.GetService();
+ _options = serviceProvider.GetRequiredService>();
+ _dataStorage = serviceProvider.GetRequiredService();
+ _serializer = serviceProvider.GetRequiredService();
+ _transport = serviceProvider.GetRequiredService();
}
public async Task SendAsync(MediumMessage message)
@@ -80,9 +79,9 @@ namespace DotNetCore.CAP.Internal
{
TracingError(tracingTimestamp, transportMsg, _transport.BrokerAddress, result);
- var needRetry = await SetFailedState(message, result.Exception);
+ var needRetry = await SetFailedState(message, result.Exception!);
- return (needRetry, OperateResult.Failed(result.Exception));
+ return (needRetry, OperateResult.Failed(result.Exception!));
}
}
diff --git a/src/DotNetCore.CAP/Internal/IMessageSender.cs b/src/DotNetCore.CAP/Internal/IMessageSender.cs
index 94fedc0..de0143a 100644
--- a/src/DotNetCore.CAP/Internal/IMessageSender.cs
+++ b/src/DotNetCore.CAP/Internal/IMessageSender.cs
@@ -3,12 +3,11 @@
using System.Threading.Tasks;
using DotNetCore.CAP.Persistence;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Internal
{
public interface IMessageSender
{
- Task SendAsync([NotNull] MediumMessage message);
+ Task SendAsync(MediumMessage message);
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ISubscribeDispatcher.Default.cs b/src/DotNetCore.CAP/Internal/ISubscribeDispatcher.Default.cs
index 969c848..e80935e 100644
--- a/src/DotNetCore.CAP/Internal/ISubscribeDispatcher.Default.cs
+++ b/src/DotNetCore.CAP/Internal/ISubscribeDispatcher.Default.cs
@@ -25,8 +25,7 @@ namespace DotNetCore.CAP.Internal
// diagnostics listener
// ReSharper disable once InconsistentNaming
- private static readonly DiagnosticListener s_diagnosticListener =
- new DiagnosticListener(CapDiagnosticListenerNames.DiagnosticListenerName);
+ private static readonly DiagnosticListener s_diagnosticListener = new (CapDiagnosticListenerNames.DiagnosticListenerName);
public SubscribeDispatcher(
ILogger logger,
@@ -37,8 +36,8 @@ namespace DotNetCore.CAP.Internal
_logger = logger;
_options = options.Value;
- _dataStorage = _provider.GetService();
- Invoker = _provider.GetService();
+ _dataStorage = _provider.GetRequiredService();
+ Invoker = _provider.GetRequiredService();
}
private ISubscribeInvoker Invoker { get; }
@@ -46,7 +45,7 @@ namespace DotNetCore.CAP.Internal
public Task DispatchAsync(MediumMessage message, CancellationToken cancellationToken)
{
var selector = _provider.GetRequiredService();
- if (!selector.TryGetTopicExecutor(message.Origin.GetName(), message.Origin.GetGroup(), out var executor))
+ if (!selector.TryGetTopicExecutor(message.Origin.GetName(), message.Origin.GetGroup()!, out var executor))
{
var error = $"Message (Name:{message.Origin.GetName()},Group:{message.Origin.GetGroup()}) can not be found subscriber." +
$"{Environment.NewLine} see: https://github.com/dotnetcore/CAP/issues/63";
@@ -186,7 +185,7 @@ namespace DotNetCore.CAP.Internal
if (!string.IsNullOrEmpty(ret.CallbackName))
{
- var header = new Dictionary()
+ var header = new Dictionary()
{
[Headers.CorrelationId] = message.Origin.GetId(),
[Headers.CorrelationSequence] = (message.Origin.GetCorrelationSequence() + 1).ToString()
@@ -249,7 +248,7 @@ namespace DotNetCore.CAP.Internal
}
}
- private void TracingError(long? tracingTimestamp, Message message, MethodInfo method, Exception ex)
+ private void TracingError(long? tracingTimestamp, Message message, MethodInfo? method, Exception ex)
{
if (tracingTimestamp != null && s_diagnosticListener.IsEnabled(CapDiagnosticListenerNames.ErrorSubscriberInvoke))
{
diff --git a/src/DotNetCore.CAP/Internal/ISubscribeInvoker.Default.cs b/src/DotNetCore.CAP/Internal/ISubscribeInvoker.Default.cs
index 2445194..f9a0523 100644
--- a/src/DotNetCore.CAP/Internal/ISubscribeInvoker.Default.cs
+++ b/src/DotNetCore.CAP/Internal/ISubscribeInvoker.Default.cs
@@ -12,22 +12,19 @@ using DotNetCore.CAP.Messages;
using DotNetCore.CAP.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Internal;
-using Microsoft.Extensions.Logging;
namespace DotNetCore.CAP.Internal
{
public class SubscribeInvoker : ISubscribeInvoker
{
- private readonly ILogger _logger;
private readonly IServiceProvider _serviceProvider;
private readonly ISerializer _serializer;
private readonly ConcurrentDictionary _executors;
- public SubscribeInvoker(ILoggerFactory loggerFactory, IServiceProvider serviceProvider, ISerializer serializer)
+ public SubscribeInvoker(IServiceProvider serviceProvider, ISerializer serializer)
{
_serviceProvider = serviceProvider;
_serializer = serializer;
- _logger = loggerFactory.CreateLogger();
_executors = new ConcurrentDictionary();
}
@@ -36,11 +33,11 @@ namespace DotNetCore.CAP.Internal
cancellationToken.ThrowIfCancellationRequested();
var methodInfo = context.ConsumerDescriptor.MethodInfo;
- var reflectedTypeHandle = methodInfo.ReflectedType.TypeHandle.Value;
+ var reflectedTypeHandle = methodInfo.ReflectedType!.TypeHandle.Value;
var methodHandle = methodInfo.MethodHandle.Value;
var key = $"{reflectedTypeHandle}_{methodHandle}";
- var executor = _executors.GetOrAdd(key, x => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo));
+ var executor = _executors.GetOrAdd(key, _ => ObjectMethodExecutor.Create(methodInfo, context.ConsumerDescriptor.ImplTypeInfo));
using var scope = _serviceProvider.CreateScope();
@@ -50,7 +47,7 @@ namespace DotNetCore.CAP.Internal
var message = context.DeliverMessage;
var parameterDescriptors = context.ConsumerDescriptor.Parameters;
- var executeParameters = new object[parameterDescriptors.Count];
+ var executeParameters = new object?[parameterDescriptors.Count];
for (var i = 0; i < parameterDescriptors.Count; i++)
{
var parameterDescriptor = parameterDescriptors[i];
@@ -90,7 +87,7 @@ namespace DotNetCore.CAP.Internal
}
var filter = provider.GetService();
- object resultObj = null;
+ object? resultObj = null;
try
{
if (filter != null)
@@ -155,10 +152,10 @@ namespace DotNetCore.CAP.Internal
var srvType = context.ConsumerDescriptor.ServiceTypeInfo?.AsType();
var implType = context.ConsumerDescriptor.ImplTypeInfo.AsType();
- object obj = null;
+ object? obj = null;
if (srvType != null)
{
- obj = provider.GetServices(srvType).FirstOrDefault(o => o.GetType() == implType);
+ obj = provider.GetServices(srvType).FirstOrDefault(o => o?.GetType() == implType);
}
if (obj == null)
@@ -169,7 +166,7 @@ namespace DotNetCore.CAP.Internal
return obj;
}
- private async Task
/// consumer execute context
/// The object of .
- Task InvokeAsync([NotNull] ConsumerContext context, CancellationToken cancellationToken = default);
+ Task InvokeAsync(ConsumerContext context, CancellationToken cancellationToken = default);
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/LoggerExtensions.cs b/src/DotNetCore.CAP/Internal/LoggerExtensions.cs
index 19b20e9..dc4c75c 100644
--- a/src/DotNetCore.CAP/Internal/LoggerExtensions.cs
+++ b/src/DotNetCore.CAP/Internal/LoggerExtensions.cs
@@ -40,7 +40,7 @@ namespace DotNetCore.CAP.Internal
logger.LogDebug($"Received message. id:{messageId}, name: {name}");
}
- public static void MessagePublishException(this ILogger logger, string messageId, string reason, Exception ex)
+ public static void MessagePublishException(this ILogger logger, string? messageId, string reason, Exception? ex)
{
logger.LogError(ex, $"An exception occured while publishing a message, reason:{reason}. message id:{messageId}");
}
diff --git a/src/DotNetCore.CAP/Internal/MethodMatcherCache.cs b/src/DotNetCore.CAP/Internal/MethodMatcherCache.cs
index 2b1612f..4ae758d 100644
--- a/src/DotNetCore.CAP/Internal/MethodMatcherCache.cs
+++ b/src/DotNetCore.CAP/Internal/MethodMatcherCache.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
namespace DotNetCore.CAP.Internal
@@ -66,8 +67,7 @@ namespace DotNetCore.CAP.Internal
/// The group name of the value to get.
/// topic executor of the value.
/// true if the key was found, otherwise false.
- public bool TryGetTopicExecutor(string topicName, string groupName,
- out ConsumerExecutorDescriptor matchTopic)
+ public bool TryGetTopicExecutor(string topicName, string groupName, [NotNullWhen(true)] out ConsumerExecutorDescriptor? matchTopic)
{
if (Entries == null)
{
diff --git a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/AwaitableInfo.cs b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/AwaitableInfo.cs
index cdf9fc7..efbe9ab 100644
--- a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/AwaitableInfo.cs
+++ b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/AwaitableInfo.cs
@@ -1,128 +1,122 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
-// ReSharper disable once CheckNamespace
-namespace Microsoft.Extensions.Internal
+namespace Microsoft.Extensions.Internal;
+
+internal readonly struct AwaitableInfo
{
- internal readonly struct AwaitableInfo
+ public Type AwaiterType { get; }
+ public PropertyInfo AwaiterIsCompletedProperty { get; }
+ public MethodInfo AwaiterGetResultMethod { get; }
+ public MethodInfo AwaiterOnCompletedMethod { get; }
+ public MethodInfo AwaiterUnsafeOnCompletedMethod { get; }
+ public Type ResultType { get; }
+ public MethodInfo GetAwaiterMethod { get; }
+
+ public AwaitableInfo(
+ Type awaiterType,
+ PropertyInfo awaiterIsCompletedProperty,
+ MethodInfo awaiterGetResultMethod,
+ MethodInfo awaiterOnCompletedMethod,
+ MethodInfo awaiterUnsafeOnCompletedMethod,
+ Type resultType,
+ MethodInfo getAwaiterMethod)
{
- public Type AwaiterType { get; }
- public PropertyInfo AwaiterIsCompletedProperty { get; }
- public MethodInfo AwaiterGetResultMethod { get; }
- public MethodInfo AwaiterOnCompletedMethod { get; }
- public MethodInfo AwaiterUnsafeOnCompletedMethod { get; }
- public Type ResultType { get; }
- public MethodInfo GetAwaiterMethod { get; }
+ AwaiterType = awaiterType;
+ AwaiterIsCompletedProperty = awaiterIsCompletedProperty;
+ AwaiterGetResultMethod = awaiterGetResultMethod;
+ AwaiterOnCompletedMethod = awaiterOnCompletedMethod;
+ AwaiterUnsafeOnCompletedMethod = awaiterUnsafeOnCompletedMethod;
+ ResultType = resultType;
+ GetAwaiterMethod = getAwaiterMethod;
+ }
- public AwaitableInfo(
- Type awaiterType,
- PropertyInfo awaiterIsCompletedProperty,
- MethodInfo awaiterGetResultMethod,
- MethodInfo awaiterOnCompletedMethod,
- MethodInfo awaiterUnsafeOnCompletedMethod,
- Type resultType,
- MethodInfo getAwaiterMethod)
- {
- AwaiterType = awaiterType;
- AwaiterIsCompletedProperty = awaiterIsCompletedProperty;
- AwaiterGetResultMethod = awaiterGetResultMethod;
- AwaiterOnCompletedMethod = awaiterOnCompletedMethod;
- AwaiterUnsafeOnCompletedMethod = awaiterUnsafeOnCompletedMethod;
- ResultType = resultType;
- GetAwaiterMethod = getAwaiterMethod;
- }
+ public static bool IsTypeAwaitable(Type type, out AwaitableInfo awaitableInfo)
+ {
+ // Based on Roslyn code: http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Shared/Extensions/ISymbolExtensions.cs,db4d48ba694b9347
- public static bool IsTypeAwaitable(Type type, out AwaitableInfo awaitableInfo)
+ // Awaitable must have method matching "object GetAwaiter()"
+ var getAwaiterMethod = type.GetRuntimeMethods().FirstOrDefault(m =>
+ m.Name.Equals("GetAwaiter", StringComparison.OrdinalIgnoreCase)
+ && m.GetParameters().Length == 0
+ && m.ReturnType != null);
+ if (getAwaiterMethod == null)
{
- // Based on Roslyn code: http://source.roslyn.io/#Microsoft.CodeAnalysis.Workspaces/Shared/Extensions/ISymbolExtensions.cs,db4d48ba694b9347
+ awaitableInfo = default(AwaitableInfo);
+ return false;
+ }
- // Awaitable must have method matching "object GetAwaiter()"
- var getAwaiterMethod = type.GetRuntimeMethods().FirstOrDefault(m =>
- m.Name.Equals("GetAwaiter", StringComparison.OrdinalIgnoreCase)
- && m.GetParameters().Length == 0);
- if (getAwaiterMethod == null)
- {
- awaitableInfo = default(AwaitableInfo);
- return false;
- }
+ var awaiterType = getAwaiterMethod.ReturnType;
- var awaiterType = getAwaiterMethod.ReturnType;
+ // Awaiter must have property matching "bool IsCompleted { get; }"
+ var isCompletedProperty = awaiterType.GetRuntimeProperties().FirstOrDefault(p =>
+ p.Name.Equals("IsCompleted", StringComparison.OrdinalIgnoreCase)
+ && p.PropertyType == typeof(bool)
+ && p.GetMethod != null);
+ if (isCompletedProperty == null)
+ {
+ awaitableInfo = default(AwaitableInfo);
+ return false;
+ }
- // Awaiter must have property matching "bool IsCompleted { get; }"
- var isCompletedProperty = awaiterType.GetRuntimeProperties().FirstOrDefault(p =>
- p.Name.Equals("IsCompleted", StringComparison.OrdinalIgnoreCase)
- && p.PropertyType == typeof(bool)
- && p.GetMethod != null);
- if (isCompletedProperty == null)
- {
- awaitableInfo = default(AwaitableInfo);
- return false;
- }
+ // Awaiter must implement INotifyCompletion
+ var awaiterInterfaces = awaiterType.GetInterfaces();
+ var implementsINotifyCompletion = awaiterInterfaces.Any(t => t == typeof(INotifyCompletion));
+ if (!implementsINotifyCompletion)
+ {
+ awaitableInfo = default(AwaitableInfo);
+ return false;
+ }
- // Awaiter must implement INotifyCompletion
- var awaiterInterfaces = awaiterType.GetInterfaces();
- var implementsINotifyCompletion = awaiterInterfaces.Any(t => t == typeof(INotifyCompletion));
- if (!implementsINotifyCompletion)
- {
- awaitableInfo = default(AwaitableInfo);
- return false;
- }
+ // INotifyCompletion supplies a method matching "void OnCompleted(Action action)"
+ var onCompletedMethod = typeof(INotifyCompletion).GetRuntimeMethods().Single(m =>
+ m.Name.Equals("OnCompleted", StringComparison.OrdinalIgnoreCase)
+ && m.ReturnType == typeof(void)
+ && m.GetParameters().Length == 1
+ && m.GetParameters()[0].ParameterType == typeof(Action));
- // INotifyCompletion supplies a method matching "void OnCompleted(Action action)"
- var iNotifyCompletionMap = awaiterType
- .GetTypeInfo()
- .GetRuntimeInterfaceMap(typeof(INotifyCompletion));
- var onCompletedMethod = iNotifyCompletionMap.InterfaceMethods.Single(m =>
- m.Name.Equals("OnCompleted", StringComparison.OrdinalIgnoreCase)
+ // Awaiter optionally implements ICriticalNotifyCompletion
+ var implementsICriticalNotifyCompletion = awaiterInterfaces.Any(t => t == typeof(ICriticalNotifyCompletion));
+ MethodInfo unsafeOnCompletedMethod;
+ if (implementsICriticalNotifyCompletion)
+ {
+ // ICriticalNotifyCompletion supplies a method matching "void UnsafeOnCompleted(Action action)"
+ unsafeOnCompletedMethod = typeof(ICriticalNotifyCompletion).GetRuntimeMethods().Single(m =>
+ m.Name.Equals("UnsafeOnCompleted", StringComparison.OrdinalIgnoreCase)
&& m.ReturnType == typeof(void)
&& m.GetParameters().Length == 1
&& m.GetParameters()[0].ParameterType == typeof(Action));
+ }
+ else
+ {
+ unsafeOnCompletedMethod = null;
+ }
- // Awaiter optionally implements ICriticalNotifyCompletion
- var implementsICriticalNotifyCompletion =
- awaiterInterfaces.Any(t => t == typeof(ICriticalNotifyCompletion));
- MethodInfo unsafeOnCompletedMethod;
- if (implementsICriticalNotifyCompletion)
- {
- // ICriticalNotifyCompletion supplies a method matching "void UnsafeOnCompleted(Action action)"
- var iCriticalNotifyCompletionMap = awaiterType
- .GetTypeInfo()
- .GetRuntimeInterfaceMap(typeof(ICriticalNotifyCompletion));
- unsafeOnCompletedMethod = iCriticalNotifyCompletionMap.InterfaceMethods.Single(m =>
- m.Name.Equals("UnsafeOnCompleted", StringComparison.OrdinalIgnoreCase)
- && m.ReturnType == typeof(void)
- && m.GetParameters().Length == 1
- && m.GetParameters()[0].ParameterType == typeof(Action));
- }
- else
- {
- unsafeOnCompletedMethod = null;
- }
-
- // Awaiter must have method matching "void GetResult" or "T GetResult()"
- var getResultMethod = awaiterType.GetRuntimeMethods().FirstOrDefault(m =>
- m.Name.Equals("GetResult")
- && m.GetParameters().Length == 0);
- if (getResultMethod == null)
- {
- awaitableInfo = default(AwaitableInfo);
- return false;
- }
-
- awaitableInfo = new AwaitableInfo(
- awaiterType,
- isCompletedProperty,
- getResultMethod,
- onCompletedMethod,
- unsafeOnCompletedMethod,
- getResultMethod.ReturnType,
- getAwaiterMethod);
- return true;
+ // Awaiter must have method matching "void GetResult" or "T GetResult()"
+ var getResultMethod = awaiterType.GetRuntimeMethods().FirstOrDefault(m =>
+ m.Name.Equals("GetResult")
+ && m.GetParameters().Length == 0);
+ if (getResultMethod == null)
+ {
+ awaitableInfo = default(AwaitableInfo);
+ return false;
}
+
+ awaitableInfo = new AwaitableInfo(
+ awaiterType,
+ isCompletedProperty,
+ getResultMethod,
+ onCompletedMethod,
+ unsafeOnCompletedMethod,
+ getResultMethod.ReturnType,
+ getAwaiterMethod);
+ return true;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/CoercedAwaitableInfo.cs b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/CoercedAwaitableInfo.cs
index 39c3475..d9eaad1 100644
--- a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/CoercedAwaitableInfo.cs
+++ b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/CoercedAwaitableInfo.cs
@@ -1,57 +1,56 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
using System;
using System.Linq.Expressions;
-// ReSharper disable once CheckNamespace
-namespace Microsoft.Extensions.Internal
+namespace Microsoft.Extensions.Internal;
+
+internal readonly struct CoercedAwaitableInfo
{
- internal readonly struct CoercedAwaitableInfo
+ public AwaitableInfo AwaitableInfo { get; }
+ public Expression CoercerExpression { get; }
+ public Type CoercerResultType { get; }
+ public bool RequiresCoercion => CoercerExpression != null;
+
+ public CoercedAwaitableInfo(AwaitableInfo awaitableInfo)
{
- public AwaitableInfo AwaitableInfo { get; }
- public Expression CoercerExpression { get; }
- public Type CoercerResultType { get; }
- public bool RequiresCoercion => CoercerExpression != null;
+ AwaitableInfo = awaitableInfo;
+ CoercerExpression = null;
+ CoercerResultType = null;
+ }
- public CoercedAwaitableInfo(AwaitableInfo awaitableInfo)
- {
- AwaitableInfo = awaitableInfo;
- CoercerExpression = null;
- CoercerResultType = null;
- }
+ public CoercedAwaitableInfo(Expression coercerExpression, Type coercerResultType, AwaitableInfo coercedAwaitableInfo)
+ {
+ CoercerExpression = coercerExpression;
+ CoercerResultType = coercerResultType;
+ AwaitableInfo = coercedAwaitableInfo;
+ }
- public CoercedAwaitableInfo(Expression coercerExpression, Type coercerResultType,
- AwaitableInfo coercedAwaitableInfo)
+ public static bool IsTypeAwaitable(Type type, out CoercedAwaitableInfo info)
+ {
+ if (AwaitableInfo.IsTypeAwaitable(type, out var directlyAwaitableInfo))
{
- CoercerExpression = coercerExpression;
- CoercerResultType = coercerResultType;
- AwaitableInfo = coercedAwaitableInfo;
+ info = new CoercedAwaitableInfo(directlyAwaitableInfo);
+ return true;
}
- public static bool IsTypeAwaitable(Type type, out CoercedAwaitableInfo info)
- {
- if (AwaitableInfo.IsTypeAwaitable(type, out var directlyAwaitableInfo))
- {
- info = new CoercedAwaitableInfo(directlyAwaitableInfo);
- return true;
- }
-
- // It's not directly awaitable, but maybe we can coerce it.
- // Currently we support coercing FSharpAsync.
- if (ObjectMethodExecutorFSharpSupport.TryBuildCoercerFromFSharpAsyncToAwaitable(type,
+ // It's not directly awaitable, but maybe we can coerce it.
+ // Currently we support coercing FSharpAsync.
+ if (ObjectMethodExecutorFSharpSupport.TryBuildCoercerFromFSharpAsyncToAwaitable(type,
out var coercerExpression,
out var coercerResultType))
+ {
+ if (AwaitableInfo.IsTypeAwaitable(coercerResultType, out var coercedAwaitableInfo))
{
- if (AwaitableInfo.IsTypeAwaitable(coercerResultType, out var coercedAwaitableInfo))
- {
- info = new CoercedAwaitableInfo(coercerExpression, coercerResultType, coercedAwaitableInfo);
- return true;
- }
+ info = new CoercedAwaitableInfo(coercerExpression, coercerResultType, coercedAwaitableInfo);
+ return true;
}
-
- info = default(CoercedAwaitableInfo);
- return false;
}
+
+ info = default(CoercedAwaitableInfo);
+ return false;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutor.cs b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutor.cs
index 26708a2..defdc14 100644
--- a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutor.cs
+++ b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutor.cs
@@ -1,338 +1,344 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable enable
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
-// ReSharper disable once CheckNamespace
-namespace Microsoft.Extensions.Internal
+namespace Microsoft.Extensions.Internal;
+
+internal class ObjectMethodExecutor
{
- internal class ObjectMethodExecutor
- {
- // ReSharper disable once InconsistentNaming
- private static readonly ConstructorInfo _objectMethodExecutorAwaitableConstructor =
- typeof(ObjectMethodExecutorAwaitable).GetConstructor(new[]
- {
- typeof(object), // customAwaitable
- typeof(Func), // getAwaiterMethod
- typeof(Func), // isCompletedMethod
- typeof(Func), // getResultMethod
+ private readonly object?[]? _parameterDefaultValues;
+ private readonly MethodExecutorAsync? _executorAsync;
+ private readonly MethodExecutor? _executor;
+
+ private static readonly ConstructorInfo _objectMethodExecutorAwaitableConstructor =
+ typeof(ObjectMethodExecutorAwaitable).GetConstructor(new[] {
+ typeof(object), // customAwaitable
+ typeof(Func), // getAwaiterMethod
+ typeof(Func), // isCompletedMethod
+ typeof(Func), // getResultMethod
typeof(Action), // onCompletedMethod
- typeof(Action) // unsafeOnCompletedMethod
- });
-
- private readonly MethodExecutor _executor;
- private readonly MethodExecutorAsync _executorAsync;
- private readonly object[] _parameterDefaultValues;
+ typeof(Action) // unsafeOnCompletedMethod
+ })!;
- private ObjectMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo, object[] parameterDefaultValues)
+ private ObjectMethodExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo, object?[]? parameterDefaultValues)
+ {
+ if (methodInfo == null)
{
- if (methodInfo == null)
- {
- throw new ArgumentNullException(nameof(methodInfo));
- }
-
- MethodInfo = methodInfo;
- MethodParameters = methodInfo.GetParameters();
- TargetTypeInfo = targetTypeInfo;
- MethodReturnType = methodInfo.ReturnType;
+ throw new ArgumentNullException(nameof(methodInfo));
+ }
- var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(MethodReturnType, out var coercedAwaitableInfo);
+ MethodInfo = methodInfo;
+ MethodParameters = methodInfo.GetParameters();
+ TargetTypeInfo = targetTypeInfo;
+ MethodReturnType = methodInfo.ReturnType;
- IsMethodAsync = isAwaitable;
- AsyncResultType = isAwaitable ? coercedAwaitableInfo.AwaitableInfo.ResultType : null;
+ var isAwaitable = CoercedAwaitableInfo.IsTypeAwaitable(MethodReturnType, out var coercedAwaitableInfo);
- // Upstream code may prefer to use the sync-executor even for async methods, because if it knows
- // that the result is a specific Task where T is known, then it can directly cast to that type
- // and await it without the extra heap allocations involved in the _executorAsync code path.
- _executor = GetExecutor(methodInfo, targetTypeInfo);
+ IsMethodAsync = isAwaitable;
+ AsyncResultType = isAwaitable ? coercedAwaitableInfo.AwaitableInfo.ResultType : null;
- if (IsMethodAsync)
- {
- _executorAsync = GetExecutorAsync(methodInfo, targetTypeInfo, coercedAwaitableInfo);
- }
+ // Upstream code may prefer to use the sync-executor even for async methods, because if it knows
+ // that the result is a specific Task where T is known, then it can directly cast to that type
+ // and await it without the extra heap allocations involved in the _executorAsync code path.
+ _executor = GetExecutor(methodInfo, targetTypeInfo);
- _parameterDefaultValues = parameterDefaultValues;
+ if (IsMethodAsync)
+ {
+ _executorAsync = GetExecutorAsync(methodInfo, targetTypeInfo, coercedAwaitableInfo);
}
- public MethodInfo MethodInfo { get; }
+ _parameterDefaultValues = parameterDefaultValues;
+ }
+
+ private delegate ObjectMethodExecutorAwaitable MethodExecutorAsync(object target, object?[]? parameters);
+
+ private delegate object? MethodExecutor(object target, object?[]? parameters);
- public ParameterInfo[] MethodParameters { get; }
+ private delegate void VoidMethodExecutor(object target, object?[]? parameters);
- public TypeInfo TargetTypeInfo { get; }
+ public MethodInfo MethodInfo { get; }
- public Type AsyncResultType { get; }
+ public ParameterInfo[] MethodParameters { get; }
- // This field is made internal set because it is set in unit tests.
- public Type MethodReturnType { get; internal set; }
+ public TypeInfo TargetTypeInfo { get; }
- public bool IsMethodAsync { get; }
+ public Type? AsyncResultType { get; }
- public static ObjectMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo)
+ // This field is made internal set because it is set in unit tests.
+ public Type MethodReturnType { get; internal set; }
+
+ public bool IsMethodAsync { get; }
+
+ public static ObjectMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo)
+ {
+ return new ObjectMethodExecutor(methodInfo, targetTypeInfo, null);
+ }
+
+ public static ObjectMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo, object?[] parameterDefaultValues)
+ {
+ if (parameterDefaultValues == null)
{
- return new ObjectMethodExecutor(methodInfo, targetTypeInfo, null);
+ throw new ArgumentNullException(nameof(parameterDefaultValues));
}
- public static ObjectMethodExecutor Create(MethodInfo methodInfo, TypeInfo targetTypeInfo,
- object[] parameterDefaultValues)
- {
- if (parameterDefaultValues == null)
- {
- throw new ArgumentNullException(nameof(parameterDefaultValues));
- }
+ return new ObjectMethodExecutor(methodInfo, targetTypeInfo, parameterDefaultValues);
+ }
- return new ObjectMethodExecutor(methodInfo, targetTypeInfo, parameterDefaultValues);
- }
+ ///
+ /// Executes the configured method on . This can be used whether or not
+ /// the configured method is asynchronous.
+ ///
+ ///
+ /// Even if the target method is asynchronous, it's desirable to invoke it using Execute rather than
+ /// ExecuteAsync if you know at compile time what the return type is, because then you can directly
+ /// "await" that value (via a cast), and then the generated code will be able to reference the
+ /// resulting awaitable as a value-typed variable. If you use ExecuteAsync instead, the generated
+ /// code will have to treat the resulting awaitable as a boxed object, because it doesn't know at
+ /// compile time what type it would be.
+ ///
+ /// The object whose method is to be executed.
+ /// Parameters to pass to the method.
+ /// The method return value.
+ public object? Execute(object target, object?[]? parameters)
+ {
+ Debug.Assert(_executor != null, "Sync execution is not supported.");
+ return _executor(target, parameters);
+ }
+
+ ///
+ /// Executes the configured method on . This can only be used if the configured
+ /// method is asynchronous.
+ ///
+ ///
+ /// If you don't know at compile time the type of the method's returned awaitable, you can use ExecuteAsync,
+ /// which supplies an awaitable-of-object. This always works, but can incur several extra heap allocations
+ /// as compared with using Execute and then using "await" on the result value typecasted to the known
+ /// awaitable type. The possible extra heap allocations are for:
+ ///
+ /// 1. The custom awaitable (though usually there's a heap allocation for this anyway, since normally
+ /// it's a reference type, and you normally create a new instance per call).
+ /// 2. The custom awaiter (whether or not it's a value type, since if it's not, you need a new instance
+ /// of it, and if it is, it will have to be boxed so the calling code can reference it as an object).
+ /// 3. The async result value, if it's a value type (it has to be boxed as an object, since the calling
+ /// code doesn't know what type it's going to be).
+ ///
+ /// The object whose method is to be executed.
+ /// Parameters to pass to the method.
+ /// An object that you can "await" to get the method return value.
+ public ObjectMethodExecutorAwaitable ExecuteAsync(object target, object?[]? parameters)
+ {
+ Debug.Assert(_executorAsync != null, "Async execution is not supported.");
+ return _executorAsync(target, parameters);
+ }
- ///
- /// Executes the configured method on . This can be used whether or not
- /// the configured method is asynchronous.
- ///
- ///
- /// Even if the target method is asynchronous, it's desirable to invoke it using Execute rather than
- /// ExecuteAsync if you know at compile time what the return type is, because then you can directly
- /// "await" that value (via a cast), and then the generated code will be able to reference the
- /// resulting awaitable as a value-typed variable. If you use ExecuteAsync instead, the generated
- /// code will have to treat the resulting awaitable as a boxed object, because it doesn't know at
- /// compile time what type it would be.
- ///
- /// The object whose method is to be executed.
- /// Parameters to pass to the method.
- /// The method return value.
- public object Execute(object target, params object[] parameters)
+ public object? GetDefaultValueForParameter(int index)
+ {
+ if (_parameterDefaultValues == null)
{
- return _executor(target, parameters);
+ throw new InvalidOperationException($"Cannot call {nameof(GetDefaultValueForParameter)}, because no parameter default values were supplied.");
}
- ///
- /// Executes the configured method on . This can only be used if the configured
- /// method is asynchronous.
- ///
- ///
- /// If you don't know at compile time the type of the method's returned awaitable, you can use ExecuteAsync,
- /// which supplies an awaitable-of-object. This always works, but can incur several extra heap allocations
- /// as compared with using Execute and then using "await" on the result value typecasted to the known
- /// awaitable type. The possible extra heap allocations are for:
- /// 1. The custom awaitable (though usually there's a heap allocation for this anyway, since normally
- /// it's a reference type, and you normally create a new instance per call).
- /// 2. The custom awaiter (whether or not it's a value type, since if it's not, you need a new instance
- /// of it, and if it is, it will have to be boxed so the calling code can reference it as an object).
- /// 3. The async result value, if it's a value type (it has to be boxed as an object, since the calling
- /// code doesn't know what type it's going to be).
- ///
- /// The object whose method is to be executed.
- /// Parameters to pass to the method.
- /// An object that you can "await" to get the method return value.
- public ObjectMethodExecutorAwaitable ExecuteAsync(object target, params object[] parameters)
+ if (index < 0 || index > MethodParameters.Length - 1)
{
- return _executorAsync(target, parameters);
+ throw new ArgumentOutOfRangeException(nameof(index));
}
- public object GetDefaultValueForParameter(int index)
+ return _parameterDefaultValues[index];
+ }
+
+ private static MethodExecutor GetExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo)
+ {
+ // Parameters to executor
+ var targetParameter = Expression.Parameter(typeof(object), "target");
+ var parametersParameter = Expression.Parameter(typeof(object?[]), "parameters");
+
+ // Build parameter list
+ var paramInfos = methodInfo.GetParameters();
+ var parameters = new List(paramInfos.Length);
+ for (int i = 0; i < paramInfos.Length; i++)
{
- if (_parameterDefaultValues == null)
- {
- throw new InvalidOperationException(
- $"Cannot call {nameof(GetDefaultValueForParameter)}, because no parameter default values were supplied.");
- }
-
- if (index < 0 || index > MethodParameters.Length - 1)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
-
- return _parameterDefaultValues[index];
+ var paramInfo = paramInfos[i];
+ var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
+ var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
+
+ // valueCast is "(Ti) parameters[i]"
+ parameters.Add(valueCast);
}
- private static MethodExecutor GetExecutor(MethodInfo methodInfo, TypeInfo targetTypeInfo)
+ // Call method
+ var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType());
+ var methodCall = Expression.Call(instanceCast, methodInfo, parameters);
+
+ // methodCall is "((Ttarget) target) method((T0) parameters[0], (T1) parameters[1], ...)"
+ // Create function
+ if (methodCall.Type == typeof(void))
{
- // Parameters to executor
- var targetParameter = Expression.Parameter(typeof(object), "target");
- var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
-
- // Build parameter list
- var parameters = new List();
- var paramInfos = methodInfo.GetParameters();
- for (var i = 0; i < paramInfos.Length; i++)
- {
- var paramInfo = paramInfos[i];
- var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
- var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
-
- // valueCast is "(Ti) parameters[i]"
- parameters.Add(valueCast);
- }
-
- // Call method
- var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType());
- var methodCall = Expression.Call(instanceCast, methodInfo, parameters);
-
- // methodCall is "((Ttarget) target) method((T0) parameters[0], (T1) parameters[1], ...)"
- // Create function
- if (methodCall.Type == typeof(void))
- {
- var lambda = Expression.Lambda(methodCall, targetParameter, parametersParameter);
- var voidExecutor = lambda.Compile();
- return WrapVoidMethod(voidExecutor);
- }
- else
- {
- // must coerce methodCall to match ActionExecutor signature
- var castMethodCall = Expression.Convert(methodCall, typeof(object));
- var lambda = Expression.Lambda(castMethodCall, targetParameter, parametersParameter);
- return lambda.Compile();
- }
+ var lambda = Expression.Lambda(methodCall, targetParameter, parametersParameter);
+ var voidExecutor = lambda.Compile();
+ return WrapVoidMethod(voidExecutor);
+ }
+ else
+ {
+ // must coerce methodCall to match ActionExecutor signature
+ var castMethodCall = Expression.Convert(methodCall, typeof(object));
+ var lambda = Expression.Lambda(castMethodCall, targetParameter, parametersParameter);
+ return lambda.Compile();
}
+ }
+
+ private static MethodExecutor WrapVoidMethod(VoidMethodExecutor executor)
+ {
+ return delegate (object target, object?[]? parameters)
+ {
+ executor(target, parameters);
+ return null;
+ };
+ }
- private static MethodExecutor WrapVoidMethod(VoidMethodExecutor executor)
+ private static MethodExecutorAsync GetExecutorAsync(
+ MethodInfo methodInfo,
+ TypeInfo targetTypeInfo,
+ CoercedAwaitableInfo coercedAwaitableInfo)
+ {
+ // Parameters to executor
+ var targetParameter = Expression.Parameter(typeof(object), "target");
+ var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
+
+ // Build parameter list
+ var paramInfos = methodInfo.GetParameters();
+ var parameters = new List(paramInfos.Length);
+ for (int i = 0; i < paramInfos.Length; i++)
{
- return delegate(object target, object[] parameters)
- {
- executor(target, parameters);
- return null;
- };
+ var paramInfo = paramInfos[i];
+ var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
+ var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
+
+ // valueCast is "(Ti) parameters[i]"
+ parameters.Add(valueCast);
}
- private static MethodExecutorAsync GetExecutorAsync(
- MethodInfo methodInfo,
- TypeInfo targetTypeInfo,
- CoercedAwaitableInfo coercedAwaitableInfo)
+ // Call method
+ var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType());
+ var methodCall = Expression.Call(instanceCast, methodInfo, parameters);
+
+ // Using the method return value, construct an ObjectMethodExecutorAwaitable based on
+ // the info we have about its implementation of the awaitable pattern. Note that all
+ // the funcs/actions we construct here are precompiled, so that only one instance of
+ // each is preserved throughout the lifetime of the ObjectMethodExecutor.
+
+ // var getAwaiterFunc = (object awaitable) =>
+ // (object)((CustomAwaitableType)awaitable).GetAwaiter();
+ var customAwaitableParam = Expression.Parameter(typeof(object), "awaitable");
+ var awaitableInfo = coercedAwaitableInfo.AwaitableInfo;
+ var postCoercionMethodReturnType = coercedAwaitableInfo.CoercerResultType ?? methodInfo.ReturnType;
+ var getAwaiterFunc = Expression.Lambda>(
+ Expression.Convert(
+ Expression.Call(
+ Expression.Convert(customAwaitableParam, postCoercionMethodReturnType),
+ awaitableInfo.GetAwaiterMethod),
+ typeof(object)),
+ customAwaitableParam).Compile();
+
+ // var isCompletedFunc = (object awaiter) =>
+ // ((CustomAwaiterType)awaiter).IsCompleted;
+ var isCompletedParam = Expression.Parameter(typeof(object), "awaiter");
+ var isCompletedFunc = Expression.Lambda>(
+ Expression.MakeMemberAccess(
+ Expression.Convert(isCompletedParam, awaitableInfo.AwaiterType),
+ awaitableInfo.AwaiterIsCompletedProperty),
+ isCompletedParam).Compile();
+
+ var getResultParam = Expression.Parameter(typeof(object), "awaiter");
+ Func getResultFunc;
+ if (awaitableInfo.ResultType == typeof(void))
{
- // Parameters to executor
- var targetParameter = Expression.Parameter(typeof(object), "target");
- var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
-
- // Build parameter list
- var parameters = new List();
- var paramInfos = methodInfo.GetParameters();
- for (var i = 0; i < paramInfos.Length; i++)
- {
- var paramInfo = paramInfos[i];
- var valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
- var valueCast = Expression.Convert(valueObj, paramInfo.ParameterType);
-
- // valueCast is "(Ti) parameters[i]"
- parameters.Add(valueCast);
- }
-
- // Call method
- var instanceCast = Expression.Convert(targetParameter, targetTypeInfo.AsType());
- var methodCall = Expression.Call(instanceCast, methodInfo, parameters);
-
- // Using the method return value, construct an ObjectMethodExecutorAwaitable based on
- // the info we have about its implementation of the awaitable pattern. Note that all
- // the funcs/actions we construct here are precompiled, so that only one instance of
- // each is preserved throughout the lifetime of the ObjectMethodExecutor.
-
- // var getAwaiterFunc = (object awaitable) =>
- // (object)((CustomAwaitableType)awaitable).GetAwaiter();
- var customAwaitableParam = Expression.Parameter(typeof(object), "awaitable");
- var awaitableInfo = coercedAwaitableInfo.AwaitableInfo;
- var postCoercionMethodReturnType = coercedAwaitableInfo.CoercerResultType ?? methodInfo.ReturnType;
- var getAwaiterFunc = Expression.Lambda>(
+ // var getResultFunc = (object awaiter) =>
+ // {
+ // ((CustomAwaiterType)awaiter).GetResult(); // We need to invoke this to surface any exceptions
+ // return (object)null;
+ // };
+ getResultFunc = Expression.Lambda>(
+ Expression.Block(
+ Expression.Call(
+ Expression.Convert(getResultParam, awaitableInfo.AwaiterType),
+ awaitableInfo.AwaiterGetResultMethod),
+ Expression.Constant(null)
+ ),
+ getResultParam).Compile();
+ }
+ else
+ {
+ // var getResultFunc = (object awaiter) =>
+ // (object)((CustomAwaiterType)awaiter).GetResult();
+ getResultFunc = Expression.Lambda>(
Expression.Convert(
Expression.Call(
- Expression.Convert(customAwaitableParam, postCoercionMethodReturnType),
- awaitableInfo.GetAwaiterMethod),
+ Expression.Convert(getResultParam, awaitableInfo.AwaiterType),
+ awaitableInfo.AwaiterGetResultMethod),
typeof(object)),
- customAwaitableParam).Compile();
-
- // var isCompletedFunc = (object awaiter) =>
- // ((CustomAwaiterType)awaiter).IsCompleted;
- var isCompletedParam = Expression.Parameter(typeof(object), "awaiter");
- var isCompletedFunc = Expression.Lambda>(
- Expression.MakeMemberAccess(
- Expression.Convert(isCompletedParam, awaitableInfo.AwaiterType),
- awaitableInfo.AwaiterIsCompletedProperty),
- isCompletedParam).Compile();
-
- var getResultParam = Expression.Parameter(typeof(object), "awaiter");
- Func getResultFunc;
- if (awaitableInfo.ResultType == typeof(void))
- {
- getResultFunc = Expression.Lambda>(
- Expression.Block(
- Expression.Call(
- Expression.Convert(getResultParam, awaitableInfo.AwaiterType),
- awaitableInfo.AwaiterGetResultMethod),
- Expression.Constant(null)
- ),
- getResultParam).Compile();
- }
- else
- {
- getResultFunc = Expression.Lambda>(
- Expression.Convert(
- Expression.Call(
- Expression.Convert(getResultParam, awaitableInfo.AwaiterType),
- awaitableInfo.AwaiterGetResultMethod),
- typeof(object)),
- getResultParam).Compile();
- }
-
- // var onCompletedFunc = (object awaiter, Action continuation) => {
- // ((CustomAwaiterType)awaiter).OnCompleted(continuation);
+ getResultParam).Compile();
+ }
+
+ // var onCompletedFunc = (object awaiter, Action continuation) => {
+ // ((CustomAwaiterType)awaiter).OnCompleted(continuation);
+ // };
+ var onCompletedParam1 = Expression.Parameter(typeof(object), "awaiter");
+ var onCompletedParam2 = Expression.Parameter(typeof(Action), "continuation");
+ var onCompletedFunc = Expression.Lambda>(
+ Expression.Call(
+ Expression.Convert(onCompletedParam1, awaitableInfo.AwaiterType),
+ awaitableInfo.AwaiterOnCompletedMethod,
+ onCompletedParam2),
+ onCompletedParam1,
+ onCompletedParam2).Compile();
+
+ Action? unsafeOnCompletedFunc = null;
+ if (awaitableInfo.AwaiterUnsafeOnCompletedMethod != null)
+ {
+ // var unsafeOnCompletedFunc = (object awaiter, Action continuation) => {
+ // ((CustomAwaiterType)awaiter).UnsafeOnCompleted(continuation);
// };
- var onCompletedParam1 = Expression.Parameter(typeof(object), "awaiter");
- var onCompletedParam2 = Expression.Parameter(typeof(Action), "continuation");
- var onCompletedFunc = Expression.Lambda>(
+ var unsafeOnCompletedParam1 = Expression.Parameter(typeof(object), "awaiter");
+ var unsafeOnCompletedParam2 = Expression.Parameter(typeof(Action), "continuation");
+ unsafeOnCompletedFunc = Expression.Lambda>(
Expression.Call(
- Expression.Convert(onCompletedParam1, awaitableInfo.AwaiterType),
- awaitableInfo.AwaiterOnCompletedMethod,
- onCompletedParam2),
- onCompletedParam1,
- onCompletedParam2).Compile();
-
- Action unsafeOnCompletedFunc = null;
- if (awaitableInfo.AwaiterUnsafeOnCompletedMethod != null)
- {
- // var unsafeOnCompletedFunc = (object awaiter, Action continuation) => {
- // ((CustomAwaiterType)awaiter).UnsafeOnCompleted(continuation);
- // };
- var unsafeOnCompletedParam1 = Expression.Parameter(typeof(object), "awaiter");
- var unsafeOnCompletedParam2 = Expression.Parameter(typeof(Action), "continuation");
- unsafeOnCompletedFunc = Expression.Lambda>(
- Expression.Call(
- Expression.Convert(unsafeOnCompletedParam1, awaitableInfo.AwaiterType),
- awaitableInfo.AwaiterUnsafeOnCompletedMethod,
- unsafeOnCompletedParam2),
- unsafeOnCompletedParam1,
- unsafeOnCompletedParam2).Compile();
- }
-
- // If we need to pass the method call result through a coercer function to get an
- // awaitable, then do so.
- var coercedMethodCall = coercedAwaitableInfo.RequiresCoercion
- ? Expression.Invoke(coercedAwaitableInfo.CoercerExpression, methodCall)
- : (Expression) methodCall;
-
- // return new ObjectMethodExecutorAwaitable(
- // (object)coercedMethodCall,
- // getAwaiterFunc,
- // isCompletedFunc,
- // getResultFunc,
- // onCompletedFunc,
- // unsafeOnCompletedFunc);
- var returnValueExpression = Expression.New(
- _objectMethodExecutorAwaitableConstructor,
- Expression.Convert(coercedMethodCall, typeof(object)),
- Expression.Constant(getAwaiterFunc),
- Expression.Constant(isCompletedFunc),
- Expression.Constant(getResultFunc),
- Expression.Constant(onCompletedFunc),
- Expression.Constant(unsafeOnCompletedFunc, typeof(Action)));
-
- var lambda =
- Expression.Lambda(returnValueExpression, targetParameter, parametersParameter);
- return lambda.Compile();
+ Expression.Convert(unsafeOnCompletedParam1, awaitableInfo.AwaiterType),
+ awaitableInfo.AwaiterUnsafeOnCompletedMethod,
+ unsafeOnCompletedParam2),
+ unsafeOnCompletedParam1,
+ unsafeOnCompletedParam2).Compile();
}
- private delegate ObjectMethodExecutorAwaitable MethodExecutorAsync(object target, params object[] parameters);
-
- private delegate object MethodExecutor(object target, params object[] parameters);
-
- private delegate void VoidMethodExecutor(object target, object[] parameters);
+ // If we need to pass the method call result through a coercer function to get an
+ // awaitable, then do so.
+ var coercedMethodCall = coercedAwaitableInfo.RequiresCoercion
+ ? Expression.Invoke(coercedAwaitableInfo.CoercerExpression, methodCall)
+ : (Expression)methodCall;
+
+ // return new ObjectMethodExecutorAwaitable(
+ // (object)coercedMethodCall,
+ // getAwaiterFunc,
+ // isCompletedFunc,
+ // getResultFunc,
+ // onCompletedFunc,
+ // unsafeOnCompletedFunc);
+ var returnValueExpression = Expression.New(
+ _objectMethodExecutorAwaitableConstructor,
+ Expression.Convert(coercedMethodCall, typeof(object)),
+ Expression.Constant(getAwaiterFunc),
+ Expression.Constant(isCompletedFunc),
+ Expression.Constant(getResultFunc),
+ Expression.Constant(onCompletedFunc),
+ Expression.Constant(unsafeOnCompletedFunc, typeof(Action)));
+
+ var lambda = Expression.Lambda(returnValueExpression, targetParameter, parametersParameter);
+ return lambda.Compile();
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorAwaitable.cs b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorAwaitable.cs
index 29012ea..d524167 100644
--- a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorAwaitable.cs
+++ b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorAwaitable.cs
@@ -1,119 +1,115 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
using System;
using System.Runtime.CompilerServices;
-// ReSharper disable once CheckNamespace
-namespace Microsoft.Extensions.Internal
+namespace Microsoft.Extensions.Internal;
+
+///
+/// Provides a common awaitable structure that can
+/// return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
+/// application-defined custom awaitable.
+///
+internal readonly struct ObjectMethodExecutorAwaitable
{
- ///
- /// Provides a common awaitable structure that can
- /// return, regardless of whether the underlying value is a System.Task, an FSharpAsync, or an
- /// application-defined custom awaitable.
- ///
- internal readonly struct ObjectMethodExecutorAwaitable
+ private readonly object _customAwaitable;
+ private readonly Func _getAwaiterMethod;
+ private readonly Func _isCompletedMethod;
+ private readonly Func _getResultMethod;
+ private readonly Action _onCompletedMethod;
+ private readonly Action _unsafeOnCompletedMethod;
+
+ // Perf note: since we're requiring the customAwaitable to be supplied here as an object,
+ // this will trigger a further allocation if it was a value type (i.e., to box it). We can't
+ // fix this by making the customAwaitable type generic, because the calling code typically
+ // does not know the type of the awaitable/awaiter at compile-time anyway.
+ //
+ // However, we could fix it by not passing the customAwaitable here at all, and instead
+ // passing a func that maps directly from the target object (e.g., controller instance),
+ // target method (e.g., action method info), and params array to the custom awaiter in the
+ // GetAwaiter() method below. In effect, by delaying the actual method call until the
+ // upstream code calls GetAwaiter on this ObjectMethodExecutorAwaitable instance.
+ // This optimization is not currently implemented because:
+ // [1] It would make no difference when the awaitable was an object type, which is
+ // by far the most common scenario (e.g., System.Task).
+ // [2] It would be complex - we'd need some kind of object pool to track all the parameter
+ // arrays until we needed to use them in GetAwaiter().
+ // We can reconsider this in the future if there's a need to optimize for ValueTask
+ // or other value-typed awaitables.
+
+ public ObjectMethodExecutorAwaitable(
+ object customAwaitable,
+ Func getAwaiterMethod,
+ Func isCompletedMethod,
+ Func getResultMethod,
+ Action onCompletedMethod,
+ Action unsafeOnCompletedMethod)
+ {
+ _customAwaitable = customAwaitable;
+ _getAwaiterMethod = getAwaiterMethod;
+ _isCompletedMethod = isCompletedMethod;
+ _getResultMethod = getResultMethod;
+ _onCompletedMethod = onCompletedMethod;
+ _unsafeOnCompletedMethod = unsafeOnCompletedMethod;
+ }
+
+ public Awaiter GetAwaiter()
+ {
+ var customAwaiter = _getAwaiterMethod(_customAwaitable);
+ return new Awaiter(customAwaiter, _isCompletedMethod, _getResultMethod, _onCompletedMethod, _unsafeOnCompletedMethod);
+ }
+
+ public readonly struct Awaiter : ICriticalNotifyCompletion
{
- private readonly object _customAwaitable;
- private readonly Func _getAwaiterMethod;
+ private readonly object _customAwaiter;
private readonly Func _isCompletedMethod;
private readonly Func _getResultMethod;
private readonly Action _onCompletedMethod;
private readonly Action _unsafeOnCompletedMethod;
- // Perf note: since we're requiring the customAwaitable to be supplied here as an object,
- // this will trigger a further allocation if it was a value type (i.e., to box it). We can't
- // fix this by making the customAwaitable type generic, because the calling code typically
- // does not know the type of the awaitable/awaiter at compile-time anyway.
- //
- // However, we could fix it by not passing the customAwaitable here at all, and instead
- // passing a func that maps directly from the target object (e.g., controller instance),
- // target method (e.g., action method info), and params array to the custom awaiter in the
- // GetAwaiter() method below. In effect, by delaying the actual method call until the
- // upstream code calls GetAwaiter on this ObjectMethodExecutorAwaitable instance.
- // This optimization is not currently implemented because:
- // [1] It would make no difference when the awaitable was an object type, which is
- // by far the most common scenario (e.g., System.Task).
- // [2] It would be complex - we'd need some kind of object pool to track all the parameter
- // arrays until we needed to use them in GetAwaiter().
- // We can reconsider this in the future if there's a need to optimize for ValueTask
- // or other value-typed awaitables.
-
- public ObjectMethodExecutorAwaitable(
- object customAwaitable,
- Func getAwaiterMethod,
+ public Awaiter(
+ object customAwaiter,
Func isCompletedMethod,
Func getResultMethod,
Action onCompletedMethod,
Action unsafeOnCompletedMethod)
{
- _customAwaitable = customAwaitable;
- _getAwaiterMethod = getAwaiterMethod;
+ _customAwaiter = customAwaiter;
_isCompletedMethod = isCompletedMethod;
_getResultMethod = getResultMethod;
_onCompletedMethod = onCompletedMethod;
_unsafeOnCompletedMethod = unsafeOnCompletedMethod;
}
- public Awaiter GetAwaiter()
+ public bool IsCompleted => _isCompletedMethod(_customAwaiter);
+
+ public object GetResult() => _getResultMethod(_customAwaiter);
+
+ public void OnCompleted(Action continuation)
{
- var customAwaiter = _getAwaiterMethod(_customAwaitable);
- return new Awaiter(customAwaiter, _isCompletedMethod, _getResultMethod, _onCompletedMethod,
- _unsafeOnCompletedMethod);
+ _onCompletedMethod(_customAwaiter, continuation);
}
- public struct Awaiter : ICriticalNotifyCompletion
+ public void UnsafeOnCompleted(Action continuation)
{
- private readonly object _customAwaiter;
- private readonly Func _isCompletedMethod;
- private readonly Func _getResultMethod;
- private readonly Action _onCompletedMethod;
- private readonly Action _unsafeOnCompletedMethod;
-
- public Awaiter(
- object customAwaiter,
- Func isCompletedMethod,
- Func getResultMethod,
- Action onCompletedMethod,
- Action unsafeOnCompletedMethod)
- {
- _customAwaiter = customAwaiter;
- _isCompletedMethod = isCompletedMethod;
- _getResultMethod = getResultMethod;
- _onCompletedMethod = onCompletedMethod;
- _unsafeOnCompletedMethod = unsafeOnCompletedMethod;
- }
-
- public bool IsCompleted => _isCompletedMethod(_customAwaiter);
-
- public object GetResult()
- {
- return _getResultMethod(_customAwaiter);
- }
-
- public void OnCompleted(Action continuation)
- {
- _onCompletedMethod(_customAwaiter, continuation);
- }
-
- public void UnsafeOnCompleted(Action continuation)
- {
- // If the underlying awaitable implements ICriticalNotifyCompletion, use its UnsafeOnCompleted.
- // If not, fall back on using its OnCompleted.
- //
- // Why this is safe:
- // - Implementing ICriticalNotifyCompletion is a way of saying the caller can choose whether it
- // needs the execution context to be preserved (which it signals by calling OnCompleted), or
- // that it doesn't (which it signals by calling UnsafeOnCompleted). Obviously it's faster *not*
- // to preserve and restore the context, so we prefer that where possible.
- // - If a caller doesn't need the execution context to be preserved and hence calls UnsafeOnCompleted,
- // there's no harm in preserving it anyway - it's just a bit of wasted cost. That's what will happen
- // if a caller sees that the proxy implements ICriticalNotifyCompletion but the proxy chooses to
- // pass the call on to the underlying awaitable's OnCompleted method.
+ // If the underlying awaitable implements ICriticalNotifyCompletion, use its UnsafeOnCompleted.
+ // If not, fall back on using its OnCompleted.
+ //
+ // Why this is safe:
+ // - Implementing ICriticalNotifyCompletion is a way of saying the caller can choose whether it
+ // needs the execution context to be preserved (which it signals by calling OnCompleted), or
+ // that it doesn't (which it signals by calling UnsafeOnCompleted). Obviously it's faster *not*
+ // to preserve and restore the context, so we prefer that where possible.
+ // - If a caller doesn't need the execution context to be preserved and hence calls UnsafeOnCompleted,
+ // there's no harm in preserving it anyway - it's just a bit of wasted cost. That's what will happen
+ // if a caller sees that the proxy implements ICriticalNotifyCompletion but the proxy chooses to
+ // pass the call on to the underlying awaitable's OnCompleted method.
- var underlyingMethodToUse = _unsafeOnCompletedMethod ?? _onCompletedMethod;
- underlyingMethodToUse(_customAwaiter, continuation);
- }
+ var underlyingMethodToUse = _unsafeOnCompletedMethod ?? _onCompletedMethod;
+ underlyingMethodToUse(_customAwaiter, continuation);
}
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorFSharpSupport.cs b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorFSharpSupport.cs
index 4164e35..f60c652 100644
--- a/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorFSharpSupport.cs
+++ b/src/DotNetCore.CAP/Internal/ObjectMethodExecutor/ObjectMethodExecutorFSharpSupport.cs
@@ -1,5 +1,7 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#nullable disable
using System;
using System.Linq;
@@ -8,139 +10,141 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
-// ReSharper disable once CheckNamespace
-namespace Microsoft.Extensions.Internal
+namespace Microsoft.Extensions.Internal;
+
+///
+/// Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
+/// an for mapping instances of that type to a C# awaitable.
+///
+///
+/// The main design goal here is to avoid taking a compile-time dependency on
+/// FSharp.Core.dll, because non-F# applications wouldn't use it. So all the references
+/// to FSharp types have to be constructed dynamically at runtime.
+///
+internal static class ObjectMethodExecutorFSharpSupport
{
- ///
- /// Helper for detecting whether a given type is FSharpAsync`1, and if so, supplying
- /// an for mapping instances of that type to a C# awaitable.
- ///
- ///
- /// The main design goal here is to avoid taking a compile-time dependency on
- /// FSharp.Core.dll, because non-F# applications wouldn't use it. So all the references
- /// to FSharp types have to be constructed dynamically at runtime.
- ///
- internal static class ObjectMethodExecutorFSharpSupport
+ private static readonly object _fsharpValuesCacheLock = new object();
+ private static Assembly _fsharpCoreAssembly;
+ private static MethodInfo _fsharpAsyncStartAsTaskGenericMethod;
+ private static PropertyInfo _fsharpOptionOfTaskCreationOptionsNoneProperty;
+ private static PropertyInfo _fsharpOptionOfCancellationTokenNoneProperty;
+
+ public static bool TryBuildCoercerFromFSharpAsyncToAwaitable(
+ Type possibleFSharpAsyncType,
+ out Expression coerceToAwaitableExpression,
+ out Type awaitableType)
{
- private static readonly object _fsharpValuesCacheLock = new object();
- private static Assembly _fsharpCoreAssembly;
- private static MethodInfo _fsharpAsyncStartAsTaskGenericMethod;
- private static PropertyInfo _fsharpOptionOfTaskCreationOptionsNoneProperty;
- private static PropertyInfo _fsharpOptionOfCancellationTokenNoneProperty;
-
- public static bool TryBuildCoercerFromFSharpAsyncToAwaitable(
- Type possibleFSharpAsyncType,
- out Expression coerceToAwaitableExpression,
- out Type awaitableType)
+ var methodReturnGenericType = possibleFSharpAsyncType.IsGenericType
+ ? possibleFSharpAsyncType.GetGenericTypeDefinition()
+ : null;
+
+ if (!IsFSharpAsyncOpenGenericType(methodReturnGenericType))
{
- var methodReturnGenericType = possibleFSharpAsyncType.IsGenericType
- ? possibleFSharpAsyncType.GetGenericTypeDefinition()
- : null;
+ coerceToAwaitableExpression = null;
+ awaitableType = null;
+ return false;
+ }
- if (!IsFSharpAsyncOpenGenericType(methodReturnGenericType))
- {
- coerceToAwaitableExpression = null;
- awaitableType = null;
- return false;
- }
+ var awaiterResultType = possibleFSharpAsyncType.GetGenericArguments().Single();
+ awaitableType = typeof(Task<>).MakeGenericType(awaiterResultType);
+
+ // coerceToAwaitableExpression = (object fsharpAsync) =>
+ // {
+ // return (object)FSharpAsync.StartAsTask(
+ // (Microsoft.FSharp.Control.FSharpAsync)fsharpAsync,
+ // FSharpOption.None,
+ // FSharpOption.None);
+ // };
+ var startAsTaskClosedMethod = _fsharpAsyncStartAsTaskGenericMethod
+ .MakeGenericMethod(awaiterResultType);
+ var coerceToAwaitableParam = Expression.Parameter(typeof(object));
+ coerceToAwaitableExpression = Expression.Lambda(
+ Expression.Convert(
+ Expression.Call(
+ startAsTaskClosedMethod,
+ Expression.Convert(coerceToAwaitableParam, possibleFSharpAsyncType),
+ Expression.MakeMemberAccess(null, _fsharpOptionOfTaskCreationOptionsNoneProperty),
+ Expression.MakeMemberAccess(null, _fsharpOptionOfCancellationTokenNoneProperty)),
+ typeof(object)),
+ coerceToAwaitableParam);
+
+ return true;
+ }
- var awaiterResultType = possibleFSharpAsyncType.GetGenericArguments().Single();
- awaitableType = typeof(Task<>).MakeGenericType(awaiterResultType);
-
- // coerceToAwaitableExpression = (object fsharpAsync) =>
- // {
- // return (object)FSharpAsync.StartAsTask(
- // (Microsoft.FSharp.Control.FSharpAsync)fsharpAsync,
- // FSharpOption.None,
- // FSharpOption.None);
- // };
- var startAsTaskClosedMethod = _fsharpAsyncStartAsTaskGenericMethod
- .MakeGenericMethod(awaiterResultType);
- var coerceToAwaitableParam = Expression.Parameter(typeof(object));
- coerceToAwaitableExpression = Expression.Lambda(
- Expression.Convert(
- Expression.Call(
- startAsTaskClosedMethod,
- Expression.Convert(coerceToAwaitableParam, possibleFSharpAsyncType),
- Expression.MakeMemberAccess(null, _fsharpOptionOfTaskCreationOptionsNoneProperty),
- Expression.MakeMemberAccess(null, _fsharpOptionOfCancellationTokenNoneProperty)),
- typeof(object)),
- coerceToAwaitableParam);
-
- return true;
+ private static bool IsFSharpAsyncOpenGenericType(Type possibleFSharpAsyncGenericType)
+ {
+ var typeFullName = possibleFSharpAsyncGenericType?.FullName;
+ if (!string.Equals(typeFullName, "Microsoft.FSharp.Control.FSharpAsync`1", StringComparison.Ordinal))
+ {
+ return false;
}
- private static bool IsFSharpAsyncOpenGenericType(Type possibleFSharpAsyncGenericType)
+ lock (_fsharpValuesCacheLock)
{
- var typeFullName = possibleFSharpAsyncGenericType?.FullName;
- if (!string.Equals(typeFullName, "Microsoft.FSharp.Control.FSharpAsync`1", StringComparison.Ordinal))
+ if (_fsharpCoreAssembly != null)
{
- return false;
+ // Since we've already found the real FSharpAsync.Core assembly, we just have
+ // to check that the supplied FSharpAsync`1 type is the one from that assembly.
+ return possibleFSharpAsyncGenericType.Assembly == _fsharpCoreAssembly;
}
-
- lock (_fsharpValuesCacheLock)
+ else
{
- if (_fsharpCoreAssembly != null)
- {
- return possibleFSharpAsyncGenericType.Assembly == _fsharpCoreAssembly;
- }
-
+ // We'll keep trying to find the FSharp types/values each time any type called
+ // FSharpAsync`1 is supplied.
return TryPopulateFSharpValueCaches(possibleFSharpAsyncGenericType);
}
}
+ }
- private static bool TryPopulateFSharpValueCaches(Type possibleFSharpAsyncGenericType)
- {
- var assembly = possibleFSharpAsyncGenericType.Assembly;
- var fsharpOptionType = assembly.GetType("Microsoft.FSharp.Core.FSharpOption`1");
- var fsharpAsyncType = assembly.GetType("Microsoft.FSharp.Control.FSharpAsync");
+ private static bool TryPopulateFSharpValueCaches(Type possibleFSharpAsyncGenericType)
+ {
+ var assembly = possibleFSharpAsyncGenericType.Assembly;
+ var fsharpOptionType = assembly.GetType("Microsoft.FSharp.Core.FSharpOption`1");
+ var fsharpAsyncType = assembly.GetType("Microsoft.FSharp.Control.FSharpAsync");
- if (fsharpOptionType == null || fsharpAsyncType == null)
- {
- return false;
- }
+ if (fsharpOptionType == null || fsharpAsyncType == null)
+ {
+ return false;
+ }
- // Get a reference to FSharpOption.None
- var fsharpOptionOfTaskCreationOptionsType = fsharpOptionType
- .MakeGenericType(typeof(TaskCreationOptions));
- _fsharpOptionOfTaskCreationOptionsNoneProperty = fsharpOptionOfTaskCreationOptionsType
- .GetTypeInfo()
- .GetRuntimeProperty("None");
-
- // Get a reference to FSharpOption.None
- var fsharpOptionOfCancellationTokenType = fsharpOptionType
- .MakeGenericType(typeof(CancellationToken));
- _fsharpOptionOfCancellationTokenNoneProperty = fsharpOptionOfCancellationTokenType
- .GetTypeInfo()
- .GetRuntimeProperty("None");
-
- // Get a reference to FSharpAsync.StartAsTask<>
- var fsharpAsyncMethods = fsharpAsyncType
- .GetRuntimeMethods()
- .Where(m => m.Name.Equals("StartAsTask", StringComparison.Ordinal));
- foreach (var candidateMethodInfo in fsharpAsyncMethods)
+ // Get a reference to FSharpOption.None
+ var fsharpOptionOfTaskCreationOptionsType = fsharpOptionType
+ .MakeGenericType(typeof(TaskCreationOptions));
+ _fsharpOptionOfTaskCreationOptionsNoneProperty = fsharpOptionOfTaskCreationOptionsType
+ .GetRuntimeProperty("None");
+
+ // Get a reference to FSharpOption.None
+ var fsharpOptionOfCancellationTokenType = fsharpOptionType
+ .MakeGenericType(typeof(CancellationToken));
+ _fsharpOptionOfCancellationTokenNoneProperty = fsharpOptionOfCancellationTokenType
+ .GetRuntimeProperty("None");
+
+ // Get a reference to FSharpAsync.StartAsTask<>
+ var fsharpAsyncMethods = fsharpAsyncType
+ .GetRuntimeMethods()
+ .Where(m => m.Name.Equals("StartAsTask", StringComparison.Ordinal));
+ foreach (var candidateMethodInfo in fsharpAsyncMethods)
+ {
+ var parameters = candidateMethodInfo.GetParameters();
+ if (parameters.Length == 3
+ && TypesHaveSameIdentity(parameters[0].ParameterType, possibleFSharpAsyncGenericType)
+ && parameters[1].ParameterType == fsharpOptionOfTaskCreationOptionsType
+ && parameters[2].ParameterType == fsharpOptionOfCancellationTokenType)
{
- var parameters = candidateMethodInfo.GetParameters();
- if (parameters.Length == 3
- && TypesHaveSameIdentity(parameters[0].ParameterType, possibleFSharpAsyncGenericType)
- && parameters[1].ParameterType == fsharpOptionOfTaskCreationOptionsType
- && parameters[2].ParameterType == fsharpOptionOfCancellationTokenType)
- {
- // This really does look like the correct method (and hence assembly).
- _fsharpAsyncStartAsTaskGenericMethod = candidateMethodInfo;
- _fsharpCoreAssembly = assembly;
- break;
- }
+ // This really does look like the correct method (and hence assembly).
+ _fsharpAsyncStartAsTaskGenericMethod = candidateMethodInfo;
+ _fsharpCoreAssembly = assembly;
+ break;
}
-
- return _fsharpCoreAssembly != null;
}
- private static bool TypesHaveSameIdentity(Type type1, Type type2)
- {
- return type1.Assembly == type2.Assembly
- && string.Equals(type1.Namespace, type2.Namespace, StringComparison.Ordinal)
- && string.Equals(type1.Name, type2.Name, StringComparison.Ordinal);
- }
+ return _fsharpCoreAssembly != null;
+ }
+
+ private static bool TypesHaveSameIdentity(Type type1, Type type2)
+ {
+ return type1.Assembly == type2.Assembly
+ && string.Equals(type1.Namespace, type2.Namespace, StringComparison.Ordinal)
+ && string.Equals(type1.Name, type2.Name, StringComparison.Ordinal);
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Internal/PublisherSentFailedException.cs b/src/DotNetCore.CAP/Internal/PublisherSentFailedException.cs
index 9be1758..5bcdc1d 100644
--- a/src/DotNetCore.CAP/Internal/PublisherSentFailedException.cs
+++ b/src/DotNetCore.CAP/Internal/PublisherSentFailedException.cs
@@ -11,7 +11,7 @@ namespace DotNetCore.CAP.Internal
{
}
- public PublisherSentFailedException(string message, Exception ex) : base(message, ex)
+ public PublisherSentFailedException(string message, Exception? ex) : base(message, ex)
{
}
}
diff --git a/src/DotNetCore.CAP/Internal/SnowflakeId.cs b/src/DotNetCore.CAP/Internal/SnowflakeId.cs
index d8a96f9..9ea630c 100644
--- a/src/DotNetCore.CAP/Internal/SnowflakeId.cs
+++ b/src/DotNetCore.CAP/Internal/SnowflakeId.cs
@@ -20,7 +20,7 @@ namespace DotNetCore.CAP.Internal
public const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
private const long SequenceMask = -1L ^ (-1L << SequenceBits);
- private static SnowflakeId _snowflakeId;
+ private static SnowflakeId? _snowflakeId;
private readonly object _lock = new object();
private static readonly object SLock = new object();
diff --git a/src/DotNetCore.CAP/Internal/TopicAttribute.cs b/src/DotNetCore.CAP/Internal/TopicAttribute.cs
index 8e462b6..2096478 100644
--- a/src/DotNetCore.CAP/Internal/TopicAttribute.cs
+++ b/src/DotNetCore.CAP/Internal/TopicAttribute.cs
@@ -35,6 +35,6 @@ namespace DotNetCore.CAP.Internal
/// kafka --> groups.id
/// rabbit MQ --> queue.name
///
- public string Group { get; set; }
+ public string Group { get; set; } = default!;
}
}
diff --git a/src/DotNetCore.CAP/Messages/FailedInfo.cs b/src/DotNetCore.CAP/Messages/FailedInfo.cs
index 501307e..c8a9d77 100644
--- a/src/DotNetCore.CAP/Messages/FailedInfo.cs
+++ b/src/DotNetCore.CAP/Messages/FailedInfo.cs
@@ -4,10 +4,10 @@ namespace DotNetCore.CAP.Messages
{
public class FailedInfo
{
- public IServiceProvider ServiceProvider { get; set; }
+ public IServiceProvider ServiceProvider { get; set; } = default!;
public MessageType MessageType { get; set; }
- public Message Message { get; set; }
+ public Message Message { get; set; } = default!;
}
}
diff --git a/src/DotNetCore.CAP/Messages/Message.cs b/src/DotNetCore.CAP/Messages/Message.cs
index 675fdad..104c0f3 100644
--- a/src/DotNetCore.CAP/Messages/Message.cs
+++ b/src/DotNetCore.CAP/Messages/Message.cs
@@ -3,51 +3,50 @@
using System;
using System.Collections.Generic;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Messages
{
public class Message
{
///
- /// System.Text.Json requires that class explicitly has a parameterless constructor
+ /// System.Text.Json requires that class explicitly has a parameter less constructor
/// and public properties have a setter.
///
- public Message() { }
+ public Message()
+ {
+ Headers = new Dictionary();
+ }
- public Message(IDictionary headers, [CanBeNull] object value)
+ public Message(IDictionary headers, object? value)
{
Headers = headers ?? throw new ArgumentNullException(nameof(headers));
Value = value;
}
- public IDictionary Headers { get; set; }
+ public IDictionary Headers { get; set; }
- [CanBeNull]
- public object Value { get; set; }
+ public object? Value { get; set; }
}
public static class MessageExtensions
{
public static string GetId(this Message message)
{
- message.Headers.TryGetValue(Headers.MessageId, out var value);
- return value;
+ return message.Headers[Headers.MessageId]!;
}
public static string GetName(this Message message)
{
- message.Headers.TryGetValue(Headers.MessageName, out var value);
- return value;
+ return message.Headers[Headers.MessageName]!;
}
- public static string GetCallbackName(this Message message)
+ public static string? GetCallbackName(this Message message)
{
message.Headers.TryGetValue(Headers.CallbackName, out var value);
return value;
}
- public static string GetGroup(this Message message)
+ public static string? GetGroup(this Message message)
{
message.Headers.TryGetValue(Headers.Group, out var value);
return value;
diff --git a/src/DotNetCore.CAP/Messages/TransportMessage.cs b/src/DotNetCore.CAP/Messages/TransportMessage.cs
index 47d5ed8..5c2776e 100644
--- a/src/DotNetCore.CAP/Messages/TransportMessage.cs
+++ b/src/DotNetCore.CAP/Messages/TransportMessage.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Messages
{
@@ -13,7 +12,7 @@ namespace DotNetCore.CAP.Messages
[Serializable]
public class TransportMessage
{
- public TransportMessage(IDictionary headers, [CanBeNull] byte[] body)
+ public TransportMessage(IDictionary headers, byte[]? body)
{
Headers = headers ?? throw new ArgumentNullException(nameof(headers));
Body = body;
@@ -22,30 +21,29 @@ namespace DotNetCore.CAP.Messages
///
/// Gets the headers of this message
///
- public IDictionary Headers { get; }
+ public IDictionary Headers { get; }
///
/// Gets the body object of this message
///
- [CanBeNull]
- public byte[] Body { get; }
+ public byte[]? Body { get; }
public string GetId()
{
- return Headers.TryGetValue(Messages.Headers.MessageId, out var value) ? value : null;
+ return Headers[Messages.Headers.MessageId]!;
}
public string GetName()
{
- return Headers.TryGetValue(Messages.Headers.MessageName, out var value) ? value : null;
+ return Headers[Messages.Headers.MessageName]!;
}
- public string GetGroup()
+ public string? GetGroup()
{
return Headers.TryGetValue(Messages.Headers.Group, out var value) ? value : null;
}
- public string GetCorrelationId()
+ public string? GetCorrelationId()
{
return Headers.TryGetValue(Messages.Headers.CorrelationId, out var value) ? value : null;
}
diff --git a/src/DotNetCore.CAP/Monitoring/IMonitoringApi.cs b/src/DotNetCore.CAP/Monitoring/IMonitoringApi.cs
index 1c2343c..eb0b020 100644
--- a/src/DotNetCore.CAP/Monitoring/IMonitoringApi.cs
+++ b/src/DotNetCore.CAP/Monitoring/IMonitoringApi.cs
@@ -11,9 +11,9 @@ namespace DotNetCore.CAP.Monitoring
{
public interface IMonitoringApi
{
- Task GetPublishedMessageAsync(long id);
+ Task GetPublishedMessageAsync(long id);
- Task GetReceivedMessageAsync(long id);
+ Task GetReceivedMessageAsync(long id);
StatisticsDto GetStatistics();
diff --git a/src/DotNetCore.CAP/Monitoring/MessageDto.cs b/src/DotNetCore.CAP/Monitoring/MessageDto.cs
index 5f17e08..2d363b7 100644
--- a/src/DotNetCore.CAP/Monitoring/MessageDto.cs
+++ b/src/DotNetCore.CAP/Monitoring/MessageDto.cs
@@ -7,15 +7,15 @@ namespace DotNetCore.CAP.Monitoring
{
public class MessageDto
{
- public string Id { get; set; }
+ public string Id { get; set; } = default!;
- public string Version { get; set; }
+ public string Version { get; set; } = default!;
- public string Group { get; set; }
+ public string? Group { get; set; }
- public string Name { get; set; }
+ public string Name { get; set; } = default!;
- public string Content { get; set; }
+ public string? Content { get; set; }
public DateTime Added { get; set; }
@@ -23,6 +23,6 @@ namespace DotNetCore.CAP.Monitoring
public int Retries { get; set; }
- public string StatusName { get; set; }
+ public string StatusName { get; set; } = default!;
}
}
\ No newline at end of file
diff --git a/src/DotNetCore.CAP/Monitoring/MessageQueryDto.cs b/src/DotNetCore.CAP/Monitoring/MessageQueryDto.cs
index 5f4e78e..5a19d7d 100644
--- a/src/DotNetCore.CAP/Monitoring/MessageQueryDto.cs
+++ b/src/DotNetCore.CAP/Monitoring/MessageQueryDto.cs
@@ -9,13 +9,13 @@ namespace DotNetCore.CAP.Monitoring
{
public MessageType MessageType { get; set; }
- public string Group { get; set; }
+ public string? Group { get; set; }
- public string Name { get; set; }
+ public string? Name { get; set; }
- public string Content { get; set; }
+ public string? Content { get; set; }
- public string StatusName { get; set; }
+ public string? StatusName { get; set; }
public int CurrentPage { get; set; }
diff --git a/src/DotNetCore.CAP/Monitoring/PagedQueryResult.cs b/src/DotNetCore.CAP/Monitoring/PagedQueryResult.cs
index cd6e486..0195dd4 100644
--- a/src/DotNetCore.CAP/Monitoring/PagedQueryResult.cs
+++ b/src/DotNetCore.CAP/Monitoring/PagedQueryResult.cs
@@ -4,7 +4,7 @@ namespace DotNetCore.CAP.Monitoring
{
public class PagedQueryResult
{
- public IList Items { get; set; }
+ public IList? Items { get; set; }
public long Totals { get; set; }
diff --git a/src/DotNetCore.CAP/OperateResult.cs b/src/DotNetCore.CAP/OperateResult.cs
index 5bd5681..461e294 100644
--- a/src/DotNetCore.CAP/OperateResult.cs
+++ b/src/DotNetCore.CAP/OperateResult.cs
@@ -22,7 +22,7 @@ namespace DotNetCore.CAP
///
public bool Succeeded { get; set; }
- public Exception Exception { get; set; }
+ public Exception? Exception { get; set; }
///
/// An of s containing an errors
diff --git a/src/DotNetCore.CAP/Persistence/IDataStorage.cs b/src/DotNetCore.CAP/Persistence/IDataStorage.cs
index 73bc622..f9c2900 100644
--- a/src/DotNetCore.CAP/Persistence/IDataStorage.cs
+++ b/src/DotNetCore.CAP/Persistence/IDataStorage.cs
@@ -14,7 +14,7 @@ namespace DotNetCore.CAP.Persistence
Task ChangeReceiveStateAsync(MediumMessage message, StatusName state);
- MediumMessage StoreMessage(string name, Message content, object dbTransaction = null);
+ MediumMessage StoreMessage(string name, Message content, object? dbTransaction = null);
void StoreReceivedExceptionMessage(string name, string group, string content);
diff --git a/src/DotNetCore.CAP/Persistence/MediumMessage.cs b/src/DotNetCore.CAP/Persistence/MediumMessage.cs
index f5ff86f..acb1bf0 100644
--- a/src/DotNetCore.CAP/Persistence/MediumMessage.cs
+++ b/src/DotNetCore.CAP/Persistence/MediumMessage.cs
@@ -5,11 +5,11 @@ namespace DotNetCore.CAP.Persistence
{
public class MediumMessage
{
- public string DbId { get; set; }
+ public string DbId { get; set; } = default!;
- public Message Origin { get; set; }
+ public Message Origin { get; set; } = default!;
- public string Content { get; set; }
+ public string Content { get; set; } = default!;
public DateTime Added { get; set; }
diff --git a/src/DotNetCore.CAP/Processor/IDispatcher.Default.cs b/src/DotNetCore.CAP/Processor/IDispatcher.Default.cs
index f88373f..75620fb 100644
--- a/src/DotNetCore.CAP/Processor/IDispatcher.Default.cs
+++ b/src/DotNetCore.CAP/Processor/IDispatcher.Default.cs
@@ -21,10 +21,10 @@ namespace DotNetCore.CAP.Processor
private readonly CapOptions _options;
private readonly ISubscribeDispatcher _executor;
private readonly ILogger _logger;
- private readonly CancellationTokenSource _cts = new CancellationTokenSource();
+ private readonly CancellationTokenSource _cts = new ();
- private Channel _publishedChannel;
- private Channel<(MediumMessage, ConsumerExecutorDescriptor)> _receivedChannel;
+ private Channel _publishedChannel = default!;
+ private Channel<(MediumMessage, ConsumerExecutorDescriptor)> _receivedChannel = default!;
public Dispatcher(ILogger logger,
IMessageSender sender,
@@ -125,7 +125,7 @@ namespace DotNetCore.CAP.Processor
var result = await _sender.SendAsync(message);
if (!result.Succeeded)
{
- _logger.MessagePublishException(message.Origin.GetId(), result.ToString(),
+ _logger.MessagePublishException(message.Origin?.GetId(), result.ToString(),
result.Exception);
}
}
diff --git a/src/DotNetCore.CAP/Processor/IDispatcher.PerGroup.cs b/src/DotNetCore.CAP/Processor/IDispatcher.PerGroup.cs
index 678366f..b3c7484 100644
--- a/src/DotNetCore.CAP/Processor/IDispatcher.PerGroup.cs
+++ b/src/DotNetCore.CAP/Processor/IDispatcher.PerGroup.cs
@@ -22,11 +22,10 @@ namespace DotNetCore.CAP.Processor
private readonly CapOptions _options;
private readonly ISubscribeDispatcher _executor;
private readonly ILogger _logger;
- private readonly CancellationTokenSource _cts = new CancellationTokenSource();
+ private readonly CancellationTokenSource _cts = new ();
- private Channel _publishedChannel;
- // private Channel<(MediumMessage, ConsumerExecutorDescriptor)> _receivedChannel;
- private ConcurrentDictionary> _receivedChannels;
+ private Channel _publishedChannel = default!;
+ private ConcurrentDictionary> _receivedChannels = default!;
private CancellationToken _stoppingToken;
public DispatcherPerGroup(
diff --git a/src/DotNetCore.CAP/Processor/IProcessingServer.Cap.cs b/src/DotNetCore.CAP/Processor/IProcessingServer.Cap.cs
index 93bb698..70da9c3 100644
--- a/src/DotNetCore.CAP/Processor/IProcessingServer.Cap.cs
+++ b/src/DotNetCore.CAP/Processor/IProcessingServer.Cap.cs
@@ -19,8 +19,8 @@ namespace DotNetCore.CAP.Processor
private readonly ILoggerFactory _loggerFactory;
private readonly IServiceProvider _provider;
- private Task _compositeTask;
- private ProcessingContext _context;
+ private Task? _compositeTask;
+ private ProcessingContext _context = default!;
private bool _disposed;
public CapProcessingServer(
diff --git a/src/DotNetCore.CAP/Processor/IProcessor.NeedRetry.cs b/src/DotNetCore.CAP/Processor/IProcessor.NeedRetry.cs
index 0862dd0..dd78c9a 100644
--- a/src/DotNetCore.CAP/Processor/IProcessor.NeedRetry.cs
+++ b/src/DotNetCore.CAP/Processor/IProcessor.NeedRetry.cs
@@ -84,7 +84,7 @@ namespace DotNetCore.CAP.Processor
}
catch (Exception ex)
{
- _logger.LogWarning(1, ex, "Get messages from storage failed. Retrying...", typeof(T).Name);
+ _logger.LogWarning(1, ex, "Get messages from storage failed. Retrying...");
return Enumerable.Empty();
}
diff --git a/src/DotNetCore.CAP/Processor/ProcessingContext.cs b/src/DotNetCore.CAP/Processor/ProcessingContext.cs
index 6a280b2..74b46af 100644
--- a/src/DotNetCore.CAP/Processor/ProcessingContext.cs
+++ b/src/DotNetCore.CAP/Processor/ProcessingContext.cs
@@ -10,11 +10,7 @@ namespace DotNetCore.CAP.Processor
{
public class ProcessingContext : IDisposable
{
- private IServiceScope _scope;
-
- public ProcessingContext()
- {
- }
+ private IServiceScope? _scope;
private ProcessingContext(ProcessingContext other)
{
diff --git a/src/DotNetCore.CAP/Serialization/ISerializer.JsonUtf8.cs b/src/DotNetCore.CAP/Serialization/ISerializer.JsonUtf8.cs
index c070711..958a698 100644
--- a/src/DotNetCore.CAP/Serialization/ISerializer.JsonUtf8.cs
+++ b/src/DotNetCore.CAP/Serialization/ISerializer.JsonUtf8.cs
@@ -34,7 +34,7 @@ namespace DotNetCore.CAP.Serialization
return Task.FromResult(new TransportMessage(message.Headers, jsonBytes));
}
- public Task DeserializeAsync(TransportMessage transportMessage, Type valueType)
+ public Task DeserializeAsync(TransportMessage transportMessage, Type? valueType)
{
if (valueType == null || transportMessage.Body == null)
{
@@ -51,12 +51,12 @@ namespace DotNetCore.CAP.Serialization
return JsonSerializer.Serialize(message, _jsonSerializerOptions);
}
- public Message Deserialize(string json)
+ public Message? Deserialize(string json)
{
return JsonSerializer.Deserialize(json, _jsonSerializerOptions);
}
- public object Deserialize(object value, Type valueType)
+ public object? Deserialize(object value, Type valueType)
{
if (value is JsonElement jsonElement)
{
diff --git a/src/DotNetCore.CAP/Serialization/ISerializer.cs b/src/DotNetCore.CAP/Serialization/ISerializer.cs
index da89e90..4e2342d 100644
--- a/src/DotNetCore.CAP/Serialization/ISerializer.cs
+++ b/src/DotNetCore.CAP/Serialization/ISerializer.cs
@@ -4,7 +4,6 @@
using System;
using System.Threading.Tasks;
using DotNetCore.CAP.Messages;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Serialization
{
@@ -23,17 +22,17 @@ namespace DotNetCore.CAP.Serialization
///
/// Deserialize the given string into a
///
- Message Deserialize(string json);
+ Message? Deserialize(string json);
///
/// Deserialize the given back into a
///
- Task DeserializeAsync(TransportMessage transportMessage, [CanBeNull] Type valueType);
+ Task DeserializeAsync(TransportMessage transportMessage, Type? valueType);
///
/// Deserialize the given object with the given Type into an object
///
- object Deserialize(object value, Type valueType);
+ object? Deserialize(object value, Type valueType);
///
/// Check if the given object is of Json type, e.g. JToken or JsonElement
diff --git a/src/DotNetCore.CAP/Transport/BrokerAddress.cs b/src/DotNetCore.CAP/Transport/BrokerAddress.cs
index d208ab1..7c70f4e 100644
--- a/src/DotNetCore.CAP/Transport/BrokerAddress.cs
+++ b/src/DotNetCore.CAP/Transport/BrokerAddress.cs
@@ -1,11 +1,10 @@
using System.Linq;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Transport
{
public struct BrokerAddress
{
- public BrokerAddress([NotNull]string address)
+ public BrokerAddress(string address)
{
if (address.Contains("$"))
{
@@ -21,7 +20,7 @@ namespace DotNetCore.CAP.Transport
}
}
- public BrokerAddress([NotNull]string name, [CanBeNull]string endpoint)
+ public BrokerAddress(string name, string? endpoint)
{
Name = name;
Endpoint = endpoint;
@@ -29,7 +28,7 @@ namespace DotNetCore.CAP.Transport
public string Name { get; set; }
- public string Endpoint { get; set; }
+ public string? Endpoint { get; set; }
public override string ToString()
{
diff --git a/src/DotNetCore.CAP/Transport/IConsumerClient.cs b/src/DotNetCore.CAP/Transport/IConsumerClient.cs
index cf1d5ed..d750116 100644
--- a/src/DotNetCore.CAP/Transport/IConsumerClient.cs
+++ b/src/DotNetCore.CAP/Transport/IConsumerClient.cs
@@ -6,7 +6,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using DotNetCore.CAP.Messages;
-using JetBrains.Annotations;
namespace DotNetCore.CAP.Transport
{
@@ -23,7 +22,7 @@ namespace DotNetCore.CAP.Transport
///
/// Names of the requested topics
/// Topic identifiers
- ICollection FetchTopics([NotNull] IEnumerable topicNames)
+ ICollection FetchTopics(IEnumerable topicNames)
{
return topicNames.ToList();
}
@@ -32,7 +31,7 @@ namespace DotNetCore.CAP.Transport
/// Subscribe to a set of topics to the message queue
///
///
- void Subscribe([NotNull] IEnumerable topics);
+ void Subscribe(IEnumerable topics);
///
/// Start listening
@@ -42,12 +41,12 @@ namespace DotNetCore.CAP.Transport
///
/// Manual submit message offset when the message consumption is complete
///
- void Commit([NotNull] object sender);
+ void Commit(object sender);
///
/// Reject message and resumption
///
- void Reject([CanBeNull] object sender);
+ void Reject(object? sender);
event EventHandler OnMessageReceived;
diff --git a/src/DotNetCore.CAP/Transport/MqLogType.cs b/src/DotNetCore.CAP/Transport/MqLogType.cs
index 6d95a73..59ea457 100644
--- a/src/DotNetCore.CAP/Transport/MqLogType.cs
+++ b/src/DotNetCore.CAP/Transport/MqLogType.cs
@@ -31,7 +31,7 @@ namespace DotNetCore.CAP.Transport
public class LogMessageEventArgs : EventArgs
{
- public string Reason { get; set; }
+ public string? Reason { get; set; }
public MqLogType LogType { get; set; }
}
diff --git a/test/DotNetCore.CAP.Test/HelperTest.cs b/test/DotNetCore.CAP.Test/HelperTest.cs
index fcb550c..c6ecccf 100644
--- a/test/DotNetCore.CAP.Test/HelperTest.cs
+++ b/test/DotNetCore.CAP.Test/HelperTest.cs
@@ -7,19 +7,6 @@ namespace DotNetCore.CAP.Test
{
public class HelperTest
{
- [Fact]
- public void ToTimestampTest()
- {
- //Arrange
- var time = DateTime.Parse("2018-01-01 00:00:00");
-
- //Act
- var result = Helper.ToTimestamp(time);
-
- //Assert
- Assert.Equal(1514764800, result);
- }
-
[Fact]
public void IsControllerTest()
{
diff --git a/test/DotNetCore.CAP.Test/IntegrationTests/CancellationTokenSubscriberTest.cs b/test/DotNetCore.CAP.Test/IntegrationTests/CancellationTokenSubscriberTest.cs
index 7cf0a6a..deb4973 100644
--- a/test/DotNetCore.CAP.Test/IntegrationTests/CancellationTokenSubscriberTest.cs
+++ b/test/DotNetCore.CAP.Test/IntegrationTests/CancellationTokenSubscriberTest.cs
@@ -25,6 +25,7 @@ namespace DotNetCore.CAP.Test.IntegrationTests
// Explicitly stop Bootstrapper to prove the cancellation token works.
var bootstrapper = Container.GetRequiredService();
+
await bootstrapper.StopAsync(CancellationToken.None);
var (message, token) = HandledMessages
diff --git a/test/DotNetCore.CAP.Test/SubscribeInvokerTest.cs b/test/DotNetCore.CAP.Test/SubscribeInvokerTest.cs
index 5db7959..4b14f9b 100644
--- a/test/DotNetCore.CAP.Test/SubscribeInvokerTest.cs
+++ b/test/DotNetCore.CAP.Test/SubscribeInvokerTest.cs
@@ -37,7 +37,11 @@ namespace DotNetCore.CAP.Test
Parameters = new List()
};
- var header = new Dictionary();
+ var header = new Dictionary()
+ {
+ [Headers.MessageId] = SnowflakeId.Default().NextId().ToString(),
+ [Headers.MessageName] = "fake.output.integer"
+ };
var message = new Message(header, null);
var context = new ConsumerContext(descriptor, message);
diff --git a/test/DotNetCore.CAP.Test/SubscribeInvokerWithCancellation.cs b/test/DotNetCore.CAP.Test/SubscribeInvokerWithCancellation.cs
index 7eb7f20..7517479 100644
--- a/test/DotNetCore.CAP.Test/SubscribeInvokerWithCancellation.cs
+++ b/test/DotNetCore.CAP.Test/SubscribeInvokerWithCancellation.cs
@@ -47,7 +47,11 @@ namespace DotNetCore.CAP.Test
}
};
- var header = new Dictionary();
+ var header = new Dictionary()
+ {
+ [Headers.MessageId] = SnowflakeId.Default().NextId().ToString(),
+ [Headers.MessageName] = "fake.output.withcancellation"
+ };
var message = new Message(header, null);
var context = new ConsumerContext(descriptor, message);