16 changed files with 682 additions and 253 deletions
@ -0,0 +1,28 @@ |
|||
using System.Collections.Specialized; |
|||
using System.Reflection; |
|||
|
|||
namespace System; |
|||
|
|||
/// <summary>
|
|||
/// long<see cref="long"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class LongExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 时间戳转本地时间-时间戳精确到秒
|
|||
/// </summary>
|
|||
public static DateTime ToLocalTimeDateBySeconds(this long unix) |
|||
{ |
|||
var dto = DateTimeOffset.FromUnixTimeSeconds(unix); |
|||
return dto.ToLocalTime().DateTime; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 时间戳转本地时间-时间戳精确到毫秒
|
|||
/// </summary>
|
|||
public static DateTime ToLocalTimeDateByMilliseconds(this long unix) |
|||
{ |
|||
var dto = DateTimeOffset.FromUnixTimeMilliseconds(unix); |
|||
return dto.ToLocalTime().DateTime; |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
namespace System.Reflection; |
|||
|
|||
/// <summary>
|
|||
/// 属性<see cref="MethodInfo"/>的扩展辅助操作方法
|
|||
/// </summary>
|
|||
public static class PropertyInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 返回当前属性信息是否为virtual
|
|||
/// </summary>
|
|||
public static bool IsVirtual(this PropertyInfo property) |
|||
{ |
|||
var accessor = property.GetAccessors().FirstOrDefault(); |
|||
if (accessor == null) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return accessor.IsVirtual && !accessor.IsFinal; |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
using System.Text; |
|||
|
|||
namespace System; |
|||
|
|||
public class ExceptionExtensionsTests |
|||
{ |
|||
[Fact] |
|||
public void FormatMessage_ReturnsFormattedString() |
|||
{ |
|||
// Arrange
|
|||
var exception = new Exception("Test exception"); |
|||
exception.Data["CustomData"] = "Custom value"; |
|||
var isHideStackTrace = false; |
|||
var expectedMessage = new StringBuilder() |
|||
.AppendLine("异常消息:Test exception") |
|||
.AppendLine("异常类型:System.Exception") |
|||
.AppendLine("异常方法:") |
|||
.AppendLine("异常源:") |
|||
.AppendLine("异常堆栈: at YourNamespace.Tests.ExceptionExtensionsTests.FormatMessage_ReturnsFormattedString()") |
|||
.AppendLine("内部异常:") |
|||
.ToString(); |
|||
|
|||
// Act
|
|||
var result = exception.FormatMessage(isHideStackTrace); |
|||
|
|||
// Assert
|
|||
result.ShouldBe(expectedMessage); |
|||
} |
|||
|
|||
// [Fact]
|
|||
// public void ReThrow_RethrowsException()
|
|||
// {
|
|||
// // Arrange
|
|||
// var originalException = new Exception("Original exception");
|
|||
//
|
|||
// // Act & Assert
|
|||
// Should.Throw<Exception>(() => originalException.ReThrow());
|
|||
// }
|
|||
//
|
|||
|
|||
[Fact] |
|||
public void ThrowIf_ThrowsExceptionIfConditionIsTrue() |
|||
{ |
|||
// Arrange
|
|||
var exception = new InvalidOperationException("Test exception"); |
|||
var isThrow = true; |
|||
|
|||
// Act & Assert
|
|||
Should.Throw<InvalidOperationException>(() => exception.ThrowIf(isThrow)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowIf_DoesNotThrowExceptionIfConditionIsFalse() |
|||
{ |
|||
// Arrange
|
|||
var exception = new InvalidOperationException("Test exception"); |
|||
var isThrow = false; |
|||
|
|||
// Act & Assert
|
|||
exception.ThrowIf(isThrow); // Should not throw an exception
|
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowIf_ThrowsExceptionIfConditionFunctionIsTrue() |
|||
{ |
|||
// Arrange
|
|||
var exception = new InvalidOperationException("Test exception"); |
|||
|
|||
// Act & Assert
|
|||
Should.Throw<InvalidOperationException>(() => exception.ThrowIf(() => true)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ThrowIf_DoesNotThrowExceptionIfConditionFunctionIsFalse() |
|||
{ |
|||
// Arrange
|
|||
var exception = new InvalidOperationException("Test exception"); |
|||
|
|||
// Act & Assert
|
|||
exception.ThrowIf(() => false); // Should not throw an exception
|
|||
} |
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
using System.ComponentModel; |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace System.Reflection; |
|||
|
|||
public class MemberInfoExtensionsTests |
|||
{ |
|||
private class TestClass |
|||
{ |
|||
[Description("Test property")] |
|||
public string TestProperty { get; set; } |
|||
|
|||
[DisplayName("Test method")] |
|||
public void TestMethod() {} |
|||
|
|||
[Display(Name = "Test field")] |
|||
public int TestField; |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetDescription_ReturnsDescriptionAttribute_WhenExists() |
|||
{ |
|||
// Arrange
|
|||
var memberInfo = typeof(TestClass).GetProperty(nameof(TestClass.TestProperty)); |
|||
|
|||
// Act
|
|||
var result = memberInfo.GetDescription(); |
|||
|
|||
// Assert
|
|||
result.ShouldBe("Test property"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetDescription_ReturnsDisplayNameAttribute_WhenDescriptionAttributeNotExists() |
|||
{ |
|||
// Arrange
|
|||
var memberInfo = typeof(TestClass).GetMethod(nameof(TestClass.TestMethod)); |
|||
|
|||
// Act
|
|||
var result = memberInfo.GetDescription(); |
|||
|
|||
// Assert
|
|||
result.ShouldBe("Test method"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetDescription_ReturnsDisplayAttribute_WhenBothDescriptionAndDisplayNameAttributesNotExists() |
|||
{ |
|||
// Arrange
|
|||
var memberInfo = typeof(TestClass).GetField(nameof(TestClass.TestField)); |
|||
|
|||
// Act
|
|||
var result = memberInfo.GetDescription(); |
|||
|
|||
// Assert
|
|||
result.ShouldBe("Test field"); |
|||
} |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
namespace System.Reflection; |
|||
|
|||
public class MethodInfoExtensionsTests |
|||
{ |
|||
private abstract class BaseClass |
|||
{ |
|||
public virtual void Method1() {} |
|||
|
|||
public virtual async Task<int> Method2Async() { await Task.Delay(1); return 42; } |
|||
|
|||
public void Method3() {} |
|||
} |
|||
|
|||
private class DerivedClass : BaseClass |
|||
{ |
|||
public override void Method1() {} |
|||
|
|||
public override async Task<int> Method2Async() { await Task.Delay(1); return 43; } |
|||
|
|||
public new void Method3() {} |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsAsync_ReturnsFalse_WhenReturnTypeIsNotTask() |
|||
{ |
|||
// Arrange
|
|||
var methodInfo = typeof(BaseClass).GetMethod(nameof(BaseClass.Method1)); |
|||
|
|||
// Act
|
|||
var result = methodInfo.IsAsync(); |
|||
|
|||
// Assert
|
|||
result.ShouldBeFalse(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsAsync_ReturnsTrue_WhenReturnTypeIsTaskOfT() |
|||
{ |
|||
// Arrange
|
|||
var methodInfo = typeof(BaseClass).GetMethod(nameof(BaseClass.Method2Async)); |
|||
|
|||
// Act
|
|||
var result = methodInfo.IsAsync(); |
|||
|
|||
// Assert
|
|||
result.ShouldBeTrue(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsOverridden_ReturnsFalse_WhenMethodIsNotOverridden() |
|||
{ |
|||
// Arrange
|
|||
var methodInfo = typeof(BaseClass).GetMethod(nameof(BaseClass.Method3)); |
|||
|
|||
// Act
|
|||
var result = methodInfo.IsOverridden(); |
|||
|
|||
// Assert
|
|||
result.ShouldBeFalse(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsOverridden_ReturnsTrue_WhenMethodIsOverridden() |
|||
{ |
|||
// Arrange
|
|||
var methodInfo = typeof(DerivedClass).GetMethod(nameof(DerivedClass.Method1)); |
|||
|
|||
// Act
|
|||
var result = methodInfo.IsOverridden(); |
|||
|
|||
// Assert
|
|||
result.ShouldBeTrue(); |
|||
} |
|||
|
|||
[Fact] |
|||
public void IsOverridden_ReturnsFalse_WhenMethodIsHiddenByNew() |
|||
{ |
|||
// Arrange
|
|||
var methodInfo = typeof(DerivedClass).GetMethod(nameof(DerivedClass.Method3)); |
|||
|
|||
// Act
|
|||
var result = methodInfo.IsOverridden(); |
|||
|
|||
// Assert
|
|||
result.ShouldBeFalse(); |
|||
} |
|||
} |
|||
@ -1,58 +1,91 @@ |
|||
namespace System.Text; |
|||
|
|||
namespace System.Text |
|||
{ |
|||
public class StringBuilderExtensionsTest |
|||
{ |
|||
[Fact] |
|||
public void TrimTest() |
|||
public void TrimStart_RemovesLeadingWhitespace() |
|||
{ |
|||
var sb = new StringBuilder(" hello world "); |
|||
sb.Trim().ToString().ShouldBe("hello world"); |
|||
var sb = new StringBuilder(" hello"); |
|||
sb.TrimStart(); |
|||
sb.ToString().ShouldBe("hello"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void TrimStartTest() |
|||
public void TrimStart_RemovesLeadingChar() |
|||
{ |
|||
var sb = new StringBuilder(); |
|||
sb.TrimStart('a').ToString().ShouldBe(string.Empty); |
|||
|
|||
sb.Append("asdfgef"); |
|||
sb.TrimStart('a').ToString().ShouldBe("sdfgef"); |
|||
|
|||
sb.Insert(0, " "); |
|||
sb.TrimStart().ToString().ShouldBe("sdfgef"); |
|||
|
|||
sb.TrimStart("sdf").ToString().ShouldBe("gef"); |
|||
|
|||
sb.TrimStart("gef").ToString().ShouldBe(string.Empty); |
|||
var sb = new StringBuilder("***hello"); |
|||
sb.TrimStart('*'); |
|||
sb.ToString().ShouldBe("hello"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void TrimEndTest() |
|||
public void TrimStart_RemovesLeadingChars() |
|||
{ |
|||
var sb = new StringBuilder("asdfgef"); |
|||
var sb = new StringBuilder("###hello"); |
|||
sb.TrimStart(new char[] { '#' }); |
|||
sb.ToString().ShouldBe("hello"); |
|||
} |
|||
|
|||
sb.TrimEnd((string)null).ToString().ShouldBe("asdfgef"); |
|||
[Fact] |
|||
public void TrimStart_RemovesLeadingString() |
|||
{ |
|||
var sb = new StringBuilder("world of warcraft"); |
|||
sb.TrimStart("world of"); |
|||
sb.ToString().ShouldBe(" warcraft"); |
|||
} |
|||
|
|||
sb.TrimEnd('a').ToString().ShouldBe("asdfgef"); |
|||
[Fact] |
|||
public void TrimEnd_RemovesTrailingWhitespace() |
|||
{ |
|||
var sb = new StringBuilder("world "); |
|||
sb.TrimEnd(); |
|||
sb.ToString().ShouldBe("world"); |
|||
} |
|||
|
|||
sb.TrimEnd('f').ToString().ShouldBe("asdfge"); |
|||
[Fact] |
|||
public void TrimEnd_RemovesTrailingChar() |
|||
{ |
|||
var sb = new StringBuilder("hello***"); |
|||
sb.TrimEnd('*'); |
|||
sb.ToString().ShouldBe("hello"); |
|||
} |
|||
|
|||
sb.Append(" "); |
|||
sb.TrimEnd().ToString().ShouldBe("asdfge"); |
|||
[Fact] |
|||
public void TrimEnd_RemovesTrailingChars() |
|||
{ |
|||
var sb = new StringBuilder("hello###"); |
|||
sb.TrimEnd(new char[] { '#' }); |
|||
sb.ToString().ShouldBe("hello"); |
|||
} |
|||
|
|||
sb.TrimEnd(new[] { 'g', 'e' }).ToString().ShouldBe("asdf"); |
|||
sb.TrimEnd("asdf").ToString().ShouldBe(string.Empty); |
|||
[Fact] |
|||
public void TrimEnd_RemovesTrailingString() |
|||
{ |
|||
var sb = new StringBuilder("world of warcraft"); |
|||
sb.TrimEnd("of warcraft"); |
|||
sb.ToString().ShouldBe("world "); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SubStringTest() |
|||
public void Trim_RemovesLeadingAndTrailingWhitespace() |
|||
{ |
|||
var sb = new StringBuilder("asdfgef"); |
|||
Should.Throw<ArgumentOutOfRangeException>(() => |
|||
var sb = new StringBuilder(" foo "); |
|||
sb.Trim(); |
|||
sb.ToString().ShouldBe("foo"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Substring_ReturnsSubstringWithCorrectLength() |
|||
{ |
|||
sb.SubString(0, 8); |
|||
}); |
|||
sb.SubString(0, 3).ToString().ShouldBe("asd"); |
|||
var sb = new StringBuilder("abcdefg"); |
|||
sb.SubString(1, 3).ShouldBe("bcd"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Substring_ThrowsExceptionWhenStartPlusLengthIsGreaterThanLength() |
|||
{ |
|||
var sb = new StringBuilder("abcdefg"); |
|||
Should.Throw<ArgumentOutOfRangeException>(() => sb.SubString(2, 6)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue