Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a lot more extension methods #12

Merged
merged 1 commit into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ dotnet_diagnostic.sa1111.severity = none
# Reason: We don't want to force this
dotnet_diagnostic.sa1116.severity = none

# Purpose: The parameters should all be placed on the same line or each parameter should be placed on its own lin
# Reason: We don't want to force this
dotnet_diagnostic.sa1117.severity = none

# Purpose: Use an overload of 'Contains' that has a StringComparison parameter
# Reason: Ignored since we force invariant culture on the csproj level
dotnet_diagnostic.ma0001.severity = none
Expand Down Expand Up @@ -296,6 +300,10 @@ dotnet_diagnostic.sa1413.severity = none
# Reason: We don't want to force this
dotnet_diagnostic.av1130.severity = none

# Purpose: A property, method or local function should do only one thing
# Reason: We don't want to force this
dotnet_diagnostic.av1115.severity = suggestion

# Purpose: Method contains 8 statements, which exceeds the maximum of 7 statements
# Reason: We don't want to force this
dotnet_diagnostic.av1500.severity = none
Expand All @@ -304,9 +312,13 @@ dotnet_diagnostic.av1500.severity = none
# Reason: We don't want to completely prevent this.
dotnet_diagnostic.av1532.severity = suggestion

# Purpose: AV1555 : Parameter in the call is invoked with a named argument
# Reason: False positives. See https://github.com/bkoelman/CSharpGuidelinesAnalyzer/issues/145
dotnet_diagnostic.av1555.severity = none
# Purpose: Call the more overloaded method from other overloads
# Reason: We don't want to force this
dotnet_diagnostic.av1551.severity = none

# Purpose: Argument for parameter 'param' in method calls nested method
# Reason: Not a real issue in Rider anymore
dotnet_diagnostic.av1580.severity = none

# Purpose: Argument for parameter 'param' in method calls nested method
# Reason: Not a real issue in Rider anymore
Expand Down
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

## What's this about?

Reflectify offers a bunch of extension methods to provide information such as the properties or fields a type exposes and metadata about those members. It supports all major .NET versions and even understands explicltly implemented properties or properties coming from default interface implementations, a C# 8 feature.
Reflectify offers a bunch of extension methods to provide information such as the properties or fields a type exposes and metadata about those members, and many other details about classes, records and interfaces. It supports all major .NET versions and even understands explicltly implemented properties or properties coming from default interface implementations, a C# 8 feature.

## What's so special about that?

Expand All @@ -33,14 +33,28 @@ var properties = typeof(SuperClass).GetProperties(

You can take any of the options `Public`, `Internal`, `ExplictlyImplemented` and `DefaultInterfaceProperties`.

If you need the fields, use `GetFields` (which obviously cannot be explicitly implemented, nor be part of interfaces), and if you need the members, use `GetMembers`.
If you need the fields, use `GetFields` (which obviously cannot be explicitly implemented, nor be part of interfaces), and if you need the members, use `GetMembers`. You can also request individual members by name, like `GetProperty("Name", MemberKind.Public)` or `GetField("Name", MemberKind.Internal)`.

To get more metadata from a `PropertyInfo`, you can use extensions methods like:

* `IsExplictlyImplemented`
* `IsIndexer`
* `HasAttribute` and `HasAttributeInHierarchy`

More will follow in time.
Similarly, you can find indexers using `FindIndexers`, conversion operators through `FindImplicitConversionOperators` and `FindExplicitConversionOperators`, and methods via `FindMethod`, `FindParameterlessMethod` and `HasMethod`.

Other extension methods act on `Type` directly and include:

* `IsDerivedFromOpenGeneric` and `GetClosedGenericInterfaces`
* Various `HasAttribute`, `HasAttributeInHierarchy` and `GetMatchingAttributes` overloads, with and without additional filtering.
* `OverridesEquals` to determine if a type implements value semantics
* `IsSameOrInherits` to see if a type is the same as or derives from another (open-generic) type
* `IsCompilerGenerated` and `HasFriendlyName` to see if a type is (partially) generated by the compiler, like records, tuples, etc.
* `IsAnonymous`, `IsTuple`, `IsRecord`, `IsRecordClass`,`IsRecordStruct`, `IsKeyValuePair` to find these types.

Additionally, Reflectify offers some helpers such as

* `NullableOrActualType` to get the actual type of a nullable type or the type itself if it's not nullable.

> [!TIP]
> If you like this package, consider sponsoring me through [Github Sponsors](https://github.com/sponsors/dennisdoomen)
Expand Down
5 changes: 5 additions & 0 deletions Reflectify.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reflectify.Specs", "tests\R
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "build\_build.csproj", "{506022A4-AD68-43A1-A670-F2798A4091FB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Files", "Files", "{4D180A10-CB16-4781-BEB7-EAE2038A0993}"
ProjectSection(SolutionItems) = preProject
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down
3 changes: 3 additions & 0 deletions Reflectify.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@
<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FRESOURCE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>

<s:String x:Key="/Default/Environment/Editor/MatchingBraceHighlighting/Style/@EntryValue">OUTLINE</s:String>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002Aspecs_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002Aspecs_003B_002A_003B_002A_003B_002A/@EntryIndexRemoved">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002ESpecs_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:String x:Key="/Default/Environment/Hierarchy/PsiConfigurationSettingsKey/LocationType/@EntryValue">SOLUTION_FOLDER</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002EDaemon_002ESettings_002EMigration_002ESwaWarningsModeSettingsMigrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
Expand Down
30 changes: 11 additions & 19 deletions build/Build.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System;
using System.Linq;
using Nuke.Common;
using Nuke.Common.CI;
using Nuke.Common.CI.GitHubActions;
using Nuke.Common.Execution;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
Expand All @@ -12,10 +10,6 @@
using Nuke.Common.Tools.ReportGenerator;
using Nuke.Common.Utilities.Collections;
using Nuke.Components;
using YamlDotNet.Serialization;
using static Nuke.Common.EnvironmentInfo;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.ReportGenerator.ReportGeneratorTasks;
using static Serilog.Log;
Expand All @@ -27,8 +21,7 @@ class Build : NukeBuild
/// - JetBrains Rider https://nuke.build/rider
/// - Microsoft VisualStudio https://nuke.build/visualstudio
/// - Microsoft VSCode https://nuke.build/vscode

public static int Main () => Execute<Build>(x => x.Default);
public static int Main() => Execute<Build>(x => x.Default);

[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
Expand All @@ -41,15 +34,11 @@ class Build : NukeBuild

string PullRequestBase => GitHubActions?.BaseRef;

[Parameter("The key to push to Nuget")]
[Secret]
readonly string NuGetApiKey;
[Parameter("The key to push to Nuget")][Secret] readonly string NuGetApiKey;

[Solution(GenerateProjects = true)]
readonly Solution Solution;
[Solution(GenerateProjects = true)] readonly Solution Solution;

[GitVersion(Framework = "net6.0", NoFetch = true)]
readonly GitVersion GitVersion;
[GitVersion(Framework = "net6.0", NoFetch = true)] readonly GitVersion GitVersion;

AbsolutePath ArtifactsDirectory => RootDirectory / "Artifacts";

Expand All @@ -67,7 +56,10 @@ class Build : NukeBuild
"Branch spec {branchspec} is a pull request. Adding build number {buildnumber}",
BranchSpec, BuildNumber);

SemVer = string.Join('.', GitVersion.SemVer.Split('.').Take(3).Union(new[] { BuildNumber }));
SemVer = string.Join('.', GitVersion.SemVer.Split('.').Take(3).Union(new[]
{
BuildNumber
}));
}

Information("SemVer = {semver}", SemVer);
Expand Down Expand Up @@ -113,9 +105,9 @@ class Build : NukeBuild
.SetResultsDirectory(TestResultsDirectory)
.SetProjectFile(Solution.Reflectify_Specs)
.CombineWith(Solution.Reflectify_Specs.GetTargetFrameworks(),
(ss, framework) => ss
.SetFramework(framework)
.AddLoggers($"trx;LogFileName={framework}.trx")
(ss, framework) => ss
.SetFramework(framework)
.AddLoggers($"trx;LogFileName={framework}.trx")
));
});

Expand Down
6 changes: 2 additions & 4 deletions build/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System;
using System.ComponentModel;
using System.Linq;
using Nuke.Common.Tooling;

[TypeConverter(typeof(TypeConverter<Configuration>))]
public class Configuration : Enumeration
{
public static Configuration Debug = new Configuration { Value = nameof(Debug) };
public static Configuration Release = new Configuration { Value = nameof(Release) };
public static Configuration Debug = new() { Value = nameof(Debug) };
public static Configuration Release = new() { Value = nameof(Release) };

public static implicit operator string(Configuration configuration)
{
Expand Down
Loading