feat: * 泛型特性本地化资源描述 * 添加测试项目

This commit is contained in:
nsnail 2023-02-08 22:15:56 +08:00
parent f846b7bdbf
commit 1f17375915
29 changed files with 170 additions and 77 deletions

View File

@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<CodeAnalysisRuleSet>../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>../../StyleCopAnalyzers.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<MSBuildTreatWarningsAsErrors>true</MSBuildTreatWarningsAsErrors>

View File

@ -1,35 +1,13 @@
<Project>
<PropertyGroup>
<AssemblyOriginatorKeyFile>../key.snk</AssemblyOriginatorKeyFile>
<!-- $(XXX) 定义有顺序 排序请注意-->
<SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
<Authors>nsnail</Authors>
<BaseIntermediateOutputPath>../dist</BaseIntermediateOutputPath>
<BaseOutputPath>../dist</BaseOutputPath>
<BaseIntermediateOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/obj</BaseIntermediateOutputPath>
<BaseOutputPath>$(SolutionDir)/dist/$(MSBuildProjectName)/bin</BaseOutputPath>
<Copyright>© 2006-2023 nsnail</Copyright>
<DelaySign>false</DelaySign>
<Description>A .NET extension function library</Description>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<EnableBaseIntermediateOutputPathMismatchWarning>false</EnableBaseIntermediateOutputPathMismatchWarning>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<ImplicitUsings>enable</ImplicitUsings>
<IncludeSymbols>true</IncludeSymbols>
<IntermediateOutputPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</IntermediateOutputPath>
<IsPackable>true</IsPackable>
<MSBuildProjectExtensionsPath>$(BaseIntermediateOutputPath)/$(MSBuildProjectName)/obj</MSBuildProjectExtensionsPath>
<OutputPath>$(BaseOutputPath)/$(MSBuildProjectName)/bin</OutputPath>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
<PackageTags>extensions</PackageTags>
<Product>NSExt</Product>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
<SignAssembly>true</SignAssembly>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<Title>$(AssemblyName)</Title>
</PropertyGroup>
</Project>

View File

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\NSExt.csproj", "{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-FC0A-4C1D-92DE-38D0662C257D}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@ -30,6 +28,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "meta", "meta", "{85E669CB-F
StyleCopAnalyzers.ruleset = StyleCopAnalyzers.ruleset
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt.Tests", "src\NSExt.Tests\NSExt.Tests.csproj", "{557FBEF6-E6D5-4531-86DF-D772A10E2261}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NSExt", "src\NSExt\NSExt.csproj", "{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -39,9 +41,13 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70DD1C27-7ACB-4BE0-A9CD-D781E4050DE5}.Release|Any CPU.Build.0 = Release|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Debug|Any CPU.Build.0 = Debug|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.ActiveCfg = Release|Any CPU
{557FBEF6-E6D5-4531-86DF-D772A10E2261}.Release|Any CPU.Build.0 = Release|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA0982BE-6E57-4AAF-9778-F9B2EB46F505}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -1,29 +0,0 @@
using System.Reflection;
using NSExt.Attributes;
namespace NSExt.Extensions;
/// <summary>
/// EnumExtensions
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// 获取枚举的description属性
/// </summary>
/// <param name="e">枚举对象</param>
/// <returns>description属性</returns>
public static string Desc(this Enum e)
{
var t = e.GetType();
var fi = t.GetField(Enum.GetName(t, e)!);
var descAttr = fi!.GetCustomAttribute<DescriptionAttribute>(true);
if (descAttr is null) {
return Enum.GetName(t, e);
}
var str = descAttr.Description;
var locAttr = fi!.GetCustomAttribute<LocalizationAttribute>(true);
return locAttr is null ? str : locAttr.ResourceClass.GetProperty(str)?.GetValue(default) as string ?? str;
}
}

View File

@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0-preview-20221221-03" />
<PackageReference Include="xunit" Version="2.4.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\NSExt\NSExt.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,41 @@
using NSExt.Attributes;
using NSExt.Extensions;
using Xunit;
using Xunit.Abstractions;
namespace NSExt.Tests;
/// <summary>
/// 测试用例
/// </summary>
public class TestCase
{
private readonly ITestOutputHelper _testOutputHelper;
public TestCase(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}
public enum MyEnum
{
[ResourceDescription<TestCase>(nameof(Description))]
Online = 1
, Offline = 2
}
public static string Description { get; set; } = "123";
/// <summary>
/// Case1
/// </summary>
[Fact]
public void Case1()
{
var test = MyEnum.Online.ResDesc<TestCase>();
_testOutputHelper.WriteLine(test);
Assert.True(test is not null);
}
}

View File

@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../CodeQuality.props"/>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
<PackageReference Include="MinVer" Version="4.3.0-beta.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="../logo.png" Pack="true" PackagePath=""/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
namespace NSExt.Attributes;
/// <summary>
/// 本地化资源描述特性
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Field)]
public class ResourceDescriptionAttribute<T> : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="ResourceDescriptionAttribute{T}" /> class.
/// </summary>
public ResourceDescriptionAttribute(string resourceName)
{
ResourceName = resourceName;
}
/// <summary>
/// 资源名称
/// </summary>
public string ResourceName { get; set; }
/// <summary>
/// 资源对象
/// </summary>
public T ResourceObject { get; set; }
}

View File

@ -0,0 +1,42 @@
using System.Reflection;
using NSExt.Attributes;
namespace NSExt.Extensions;
/// <summary>
/// EnumExtensions
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// 获取枚举的description属性
/// </summary>
/// <param name="e">枚举对象</param>
/// <returns>description属性</returns>
public static string Desc(this Enum e)
{
var typeOfEnum = e.GetType();
var typeOfField = typeOfEnum.GetField(Enum.GetName(typeOfEnum, e)!);
var descAttr = typeOfField!.GetCustomAttribute<DescriptionAttribute>(true);
if (descAttr is null) {
return Enum.GetName(typeOfEnum, e);
}
var str = descAttr.Description;
var locAttr = typeOfField!.GetCustomAttribute<LocalizationAttribute>(true);
return locAttr is null ? str : locAttr.ResourceClass.GetProperty(str)?.GetValue(default) as string ?? str;
}
/// <summary>
/// 获取枚举的本地化资源描述
/// </summary>
public static string ResDesc<T>(this Enum e)
{
var typeOfEnum = e.GetType();
var typeOfField = typeOfEnum.GetField(Enum.GetName(typeOfEnum, e)!);
var resDescAttr = typeOfField!.GetCustomAttribute<ResourceDescriptionAttribute<T>>(true);
return resDescAttr is null
? Enum.GetName(typeOfEnum, e)
: typeof(T).GetProperty(resDescAttr.ResourceName)?.GetValue(default) as string;
}
}

35
src/NSExt/NSExt.csproj Normal file
View File

@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../../CodeQuality.props" />
<PropertyGroup>
<AssemblyOriginatorKeyFile>../../key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign>
<Description>A .NET extension function library</Description>
<EmbedAllSources>true</EmbedAllSources>
<EmbedUntrackedSource>true</EmbedUntrackedSource>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<IncludeSymbols>true</IncludeSymbols>
<IsPackable>true</IsPackable>
<PackageIcon>logo.png</PackageIcon>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/nsnail/ns-ext.git</PackageProjectUrl>
<PackageTags>extensions</PackageTags>
<Product>NSExt</Product>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/nsnail/ns-ext.git</RepositoryUrl>
<SignAssembly>true</SignAssembly>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Title>$(AssemblyName)</Title>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="MinVer" Version="4.3.0-beta.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Include="../../logo.png" Pack="true" PackagePath="" />
</ItemGroup>
</Project>