Skip to content

Commit 72a7959

Browse files
committed
Refactor service registration and add hex conversion
Refactored service registration logic in ServiceRegistrar.cs for improved clarity and maintainability. Added ToHexStringLower extension to ByteArrayExtensions.cs for efficient lowercase hex conversion. Updated StreamExtensions.cs to use the new method for SHA-256 and SHA-512 hash outputs and enhanced XML docs. Removed redundant tests from StringHelperTests.cs.
1 parent 7fe7f1c commit 72a7959

4 files changed

Lines changed: 111 additions & 40 deletions

File tree

Sources/EasyExtensions.Mediator/Registration/ServiceRegistrar.cs

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,29 @@ private static void ConnectImplementationsToTypesClosing(Type openRequestInterfa
135135
MediatorServiceConfiguration configuration,
136136
CancellationToken cancellationToken = default)
137137
{
138-
var concretions = new List<Type>();
139-
var interfaces = new HashSet<Type>();
140-
var genericConcretions = new List<Type>();
141-
var genericInterfaces = new HashSet<Type>();
138+
GatherTypesClosing(openRequestInterface, assembliesToScan, configuration,
139+
out var concretions,
140+
out var interfaces,
141+
out var genericConcretions,
142+
out var genericInterfaces);
143+
144+
RegisterClosedMatches(services, concretions, interfaces, addIfAlreadyExists);
145+
RegisterGenericMatches(services, assembliesToScan, genericConcretions, genericInterfaces, cancellationToken);
146+
}
147+
148+
private static void GatherTypesClosing(
149+
Type openRequestInterface,
150+
IEnumerable<Assembly> assembliesToScan,
151+
MediatorServiceConfiguration configuration,
152+
out List<Type> concretions,
153+
out HashSet<Type> interfaces,
154+
out List<Type> genericConcretions,
155+
out HashSet<Type> genericInterfaces)
156+
{
157+
concretions = new List<Type>();
158+
interfaces = new HashSet<Type>();
159+
genericConcretions = new List<Type>();
160+
genericInterfaces = new HashSet<Type>();
142161

143162
var types = assembliesToScan
144163
.SelectMany(a => a.DefinedTypes)
@@ -150,48 +169,65 @@ private static void ConnectImplementationsToTypesClosing(Type openRequestInterfa
150169
foreach (var type in types)
151170
{
152171
var interfaceTypes = type.FindInterfacesThatClose(openRequestInterface).ToArray();
153-
154-
if (!type.IsOpenGeneric())
155-
{
156-
concretions.Add(type);
157-
AddRangeDistinct(interfaces, interfaceTypes);
158-
}
159-
else
172+
if (type.IsOpenGeneric())
160173
{
161174
genericConcretions.Add(type);
162175
AddRangeDistinct(genericInterfaces, interfaceTypes);
176+
continue;
163177
}
178+
179+
concretions.Add(type);
180+
AddRangeDistinct(interfaces, interfaceTypes);
164181
}
182+
}
165183

184+
private static void RegisterClosedMatches(
185+
IServiceCollection services,
186+
List<Type> concretions,
187+
IEnumerable<Type> interfaces,
188+
bool addIfAlreadyExists)
189+
{
166190
foreach (var iface in interfaces)
167191
{
168192
var exactMatches = concretions.Where(x => x.CanBeCastTo(iface)).ToList();
169-
if (addIfAlreadyExists)
170-
{
171-
foreach (var type in exactMatches)
172-
{
173-
services.AddTransient(iface, type);
174-
}
175-
}
176-
else
177-
{
178-
if (exactMatches.Count > 1)
179-
{
180-
exactMatches.RemoveAll(m => !IsMatchingWithInterface(m, iface));
181-
}
182-
183-
foreach (var type in exactMatches)
184-
{
185-
services.TryAddTransient(iface, type);
186-
}
187-
}
193+
RegisterMatches(services, iface, exactMatches, addIfAlreadyExists);
188194

189195
if (!iface.IsOpenGeneric())
190196
{
191197
AddConcretionsThatCouldBeClosed(iface, concretions, services);
192198
}
193199
}
200+
}
201+
202+
private static void RegisterMatches(IServiceCollection services, Type iface, List<Type> exactMatches, bool addIfAlreadyExists)
203+
{
204+
if (addIfAlreadyExists)
205+
{
206+
foreach (var type in exactMatches)
207+
{
208+
services.AddTransient(iface, type);
209+
}
210+
return;
211+
}
194212

213+
if (exactMatches.Count > 1)
214+
{
215+
exactMatches.RemoveAll(m => !IsMatchingWithInterface(m, iface));
216+
}
217+
218+
foreach (var type in exactMatches)
219+
{
220+
services.TryAddTransient(iface, type);
221+
}
222+
}
223+
224+
private static void RegisterGenericMatches(
225+
IServiceCollection services,
226+
IEnumerable<Assembly> assembliesToScan,
227+
List<Type> genericConcretions,
228+
IEnumerable<Type> genericInterfaces,
229+
CancellationToken cancellationToken)
230+
{
195231
foreach (var iface in genericInterfaces)
196232
{
197233
var exactMatches = genericConcretions.Where(x => x.CanBeCastTo(iface)).ToList();

Sources/EasyExtensions.Tests/StringHelperTests.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ public void IsMatch_ValidInput_MustBeFalse()
3131
Assert.That(StringHelpers.IsMatch(left, right, threshold: 0.8), Is.False);
3232
}
3333

34-
3534
[Test]
3635
public void IsMatch_ValidInputZeroThresholdSameStrings_MustBeTrue()
3736
{
@@ -40,7 +39,6 @@ public void IsMatch_ValidInputZeroThresholdSameStrings_MustBeTrue()
4039
Assert.That(StringHelpers.IsMatch(left, right, threshold: 0), Is.True);
4140
}
4241

43-
4442
[Test]
4543
public void IsMatch_ValidInputZeroThresholdDiffStrings_MustBeTrue()
4644
{

Sources/EasyExtensions/Extensions/ByteArrayExtensions.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,33 @@ public static string Sha512(this byte[] bytes)
3131
using MemoryStream memoryStream = new MemoryStream(bytes);
3232
return memoryStream.Sha512();
3333
}
34+
35+
/// <summary>
36+
/// Converts the specified byte array to its equivalent lowercase hexadecimal string representation.
37+
/// </summary>
38+
/// <param name="bytes">The array of bytes to convert to a hexadecimal string. Cannot be null.</param>
39+
/// <returns>A string containing the lowercase hexadecimal representation of the input byte array, or an empty string if
40+
/// the array is empty.</returns>
41+
public static string ToHexStringLower(this byte[] bytes)
42+
{
43+
if (bytes.Length == 0)
44+
{
45+
return string.Empty;
46+
}
47+
48+
char[] chars = new char[bytes.Length * 2];
49+
int c = 0;
50+
for (int i = 0; i < bytes.Length; i++)
51+
{
52+
byte b = bytes[i];
53+
int hi = b >> 4;
54+
int lo = b & 0xF;
55+
56+
chars[c++] = (char)(hi < 10 ? '0' + hi : 'a' + (hi - 10));
57+
chars[c++] = (char)(lo < 10 ? '0' + lo : 'a' + (lo - 10));
58+
}
59+
60+
return new string(chars);
61+
}
3462
}
3563
}

Sources/EasyExtensions/Extensions/StreamExtensions.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,36 @@ public static async Task<byte[]> ReadToEndAsync(this Stream stream, bool leaveOp
5555
}
5656

5757
/// <summary>
58-
/// Calculate SHA256 hash of byte stream.
58+
/// Computes the SHA-256 hash of the data in the specified stream and returns it as a lowercase hexadecimal
59+
/// string.
5960
/// </summary>
60-
/// <param name="stream"> Data to calculate hash. </param>
61-
/// <returns> SHA256 hash of byte stream. </returns>
61+
/// <remarks>The method reads from the current position of the stream to the end. After the
62+
/// operation, the stream's position will be at the end of the stream. The caller is responsible for managing
63+
/// the stream's position and lifetime.</remarks>
64+
/// <param name="stream">The input stream containing the data to hash. The stream must be readable and positioned at the start of the
65+
/// data to hash.</param>
66+
/// <returns>A lowercase hexadecimal string representation of the SHA-256 hash of the stream's contents.</returns>
6267
public static string Sha256(this Stream stream)
6368
{
6469
using SHA256 sha = SHA256.Create();
6570
byte[] array = sha.ComputeHash(stream);
66-
return BitConverter.ToString(array).Replace("-", string.Empty).ToLower();
71+
return array.ToHexStringLower();
6772
}
6873

6974
/// <summary>
70-
/// Calculate SHA512 hash of byte stream.
75+
/// Computes the SHA-512 hash of the data in the specified stream and returns it as a lowercase hexadecimal
76+
/// string.
7177
/// </summary>
72-
/// <param name="stream"> Data to calculate hash. </param>
73-
/// <returns> SHA512 hash of byte stream. </returns>
78+
/// <remarks>The method does not reset the position of the stream after computing the hash. The
79+
/// caller is responsible for managing the stream's position and lifetime.</remarks>
80+
/// <param name="stream">The input stream containing the data to hash. The stream must be readable and positioned at the start of the
81+
/// data to hash.</param>
82+
/// <returns>A lowercase hexadecimal string representing the SHA-512 hash of the stream's contents.</returns>
7483
public static string Sha512(this Stream stream)
7584
{
7685
using SHA512 sha = SHA512.Create();
7786
byte[] array = sha.ComputeHash(stream);
78-
return BitConverter.ToString(array).Replace("-", string.Empty).ToLower();
87+
return array.ToHexStringLower();
7988
}
8089
}
8190
}

0 commit comments

Comments
 (0)