Skip to content
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: 18 additions & 0 deletions Tasks/Test2/Test2.Tests/ExpectedOutput/Output1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
public class TestClass1
{
public System.Int32 testField1;
private static System.String testField2;
public System.Int32 TestMethod1(System.Single attribute1);
public static System.Single TestMethod2();
private System.String TestMethod3(System.String attribute1, System.Int32 attribute2);
public abstract interface INestedInterface
{
public System.Void Foo();
}
private sealed class NestedClass
{
public System.Single testField1;
private static System.String testField2;
public System.Double TestMethod1();
}
}
31 changes: 31 additions & 0 deletions Tasks/Test2/Test2.Tests/ReflectorTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Alexander Bugaev 2024
//
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

namespace Test2.Tests;

using NUnit.Framework;

public static class ReflectorTest
{
private const string ExpectedOutputPath1 = "ExpectedOutput/Output1.txt";
private const string ResultPath = "TestClass1.cs";

[Test]
public static async Task TestReflector_PrintStructure_CompareResults()
{
var expectedOutput = await File.ReadAllTextAsync(ExpectedOutputPath1);
await Reflector.PrintStructure(typeof(TestClass1));
var actualOutput = await File.ReadAllTextAsync(ResultPath);
Assert.That(actualOutput, Is.EqualTo(expectedOutput));
}

[Test]
public static async Task TestReflector_PrintSomeTypes_NotThrowException()
{
await Reflector.PrintStructure(typeof(Int32));
await Reflector.PrintStructure(typeof(String));
}
}
32 changes: 32 additions & 0 deletions Tasks/Test2/Test2.Tests/Test2.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<Content Include="ExpectedOutput/**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../Test2/Test2.csproj" />
</ItemGroup>

</Project>
36 changes: 36 additions & 0 deletions Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) Alexander Bugaev 2024
//
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

namespace Test2.Tests;

public class TestClass1
{
public int testField1 = 0;
private static string testField2 = "a";

Check warning on line 12 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Windows

The field 'TestClass1.testField2' is assigned but its value is never used

Check warning on line 12 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Ubuntu

The field 'TestClass1.testField2' is assigned but its value is never used

Check warning on line 12 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Windows

The field 'TestClass1.testField2' is assigned but its value is never used

Check warning on line 12 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Ubuntu

The field 'TestClass1.testField2' is assigned but its value is never used

public int TestMethod1(float attribute1) => 1;
public static float TestMethod2() => 9090;
private string TestMethod3(string attribute1, int attribute2)
{
return "Hello";
}

public interface INestedInterface
{
void Foo();
}

private sealed class NestedClass
{
public float testField1 = 321;
private static string testField2 = "abc";

Check warning on line 29 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Windows

The field 'TestClass1.NestedClass.testField2' is assigned but its value is never used

Check warning on line 29 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Ubuntu

The field 'TestClass1.NestedClass.testField2' is assigned but its value is never used

Check warning on line 29 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Windows

The field 'TestClass1.NestedClass.testField2' is assigned but its value is never used

Check warning on line 29 in Tasks/Test2/Test2.Tests/TestClasses/TestClass1.cs

View workflow job for this annotation

GitHub Actions / build-Ubuntu

The field 'TestClass1.NestedClass.testField2' is assigned but its value is never used

public double TestMethod1()
{
throw new InvalidDataException();
}
}
}
28 changes: 28 additions & 0 deletions Tasks/Test2/Test2.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

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}") = "Test2", "Test2\Test2.csproj", "{23EF7123-539E-4886-9CDE-D10B48F31D66}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test2.Tests", "Test2.Tests\Test2.Tests.csproj", "{F46F0B0F-FF0D-470B-A0C0-2460BD3B9D3F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{23EF7123-539E-4886-9CDE-D10B48F31D66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23EF7123-539E-4886-9CDE-D10B48F31D66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23EF7123-539E-4886-9CDE-D10B48F31D66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23EF7123-539E-4886-9CDE-D10B48F31D66}.Release|Any CPU.Build.0 = Release|Any CPU
{F46F0B0F-FF0D-470B-A0C0-2460BD3B9D3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F46F0B0F-FF0D-470B-A0C0-2460BD3B9D3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F46F0B0F-FF0D-470B-A0C0-2460BD3B9D3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F46F0B0F-FF0D-470B-A0C0-2460BD3B9D3F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
171 changes: 171 additions & 0 deletions Tasks/Test2/Test2/Reflector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright (c) Alexander Bugaev 2024
//
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT.

namespace Test2;

using System.Reflection;

/// <summary>
/// Class containing utility for printing type signatures using reflection.
/// </summary>
public static class Reflector

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо комментарии

{
private const string Indent = " ";
private const BindingFlags All = (BindingFlags)(-1);

/// <summary>
/// Writes the signature of the given type with all fields, methods and nested classes.
/// Saves the resulting signature to the file with name of the type.
/// </summary>
/// <param name="someType">The type to write signature of.</param>
/// <returns>A task representing the writing process.</returns>
public static async Task PrintStructure(Type someType)
{
using var writer = new StreamWriter($"{someType.Name}.cs");
await PrintStructureInternal(someType, 0, writer);
}

private static async Task PrintStructureInternal(
Type someType, int indentCount, StreamWriter writer)
{
var indent = GetIndent(indentCount);
await WriteClassInfo(someType, indentCount, writer);
await writer.WriteLineAsync(indent + '{');

var fields = someType.GetFields(All);
var methods = someType.GetMethods(All);
var nestedTypes = someType.GetNestedTypes(All);

foreach (var field in fields)
{
await PrintField(field, indentCount + 1, writer);
}

foreach (var method in methods)
{
await PrintMethod(method, indentCount + 1, writer);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Конструкторы не поддерживаются вроде


foreach (var nestedType in nestedTypes)
{
await PrintStructureInternal(nestedType, indentCount + 1, writer);
}

await writer.WriteLineAsync(indent + '}');
}

private static async Task WriteClassInfo(
Type classInfo, int indentCount, StreamWriter writer)
{
var indent = GetIndent(indentCount);
var signature = GetClassSignature(classInfo);
await writer.WriteLineAsync(indent + signature);
}

private static async Task PrintField(
FieldInfo field, int indentCount, StreamWriter writer)
{
var indent = GetIndent(indentCount);
var signature = GetFieldSignature(field);
await writer.WriteLineAsync(indent + signature);
}

private static async Task PrintMethod(
MethodInfo method, int indentCount, StreamWriter writer)
{
var indent = GetIndent(indentCount);
var signature = GetMethodSignature(method);
await writer.WriteLineAsync(indent + signature);
}

private static string GetClassSignature(Type classInfo)
{
var signature = "";
if (classInfo.IsPublic || classInfo.IsNestedPublic)
{
signature += "public ";
}
else if (classInfo.IsNestedPrivate)
{
signature += "private ";
}
else if (!classInfo.IsVisible)
{
signature += "internal ";
}
if (classInfo.IsAbstract)
{
signature += "abstract ";
}
if (classInfo.IsSealed)
{
signature += "sealed ";
}
if (classInfo.IsClass)
{
signature += "class ";
}
else if (classInfo.IsInterface)
{
signature += "interface ";
}

signature += classInfo.Name;
return signature;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ещё неплохо бы наследование и реализацию интерфейсов

}

private static string GetFieldSignature(FieldInfo field)
{
var signature = "";
if (field.IsPublic)
{
signature += "public ";
}
else if (field.IsPrivate)
{
signature += "private ";
}
if (field.IsStatic)
{
signature += "static ";
}

signature += $"{field.FieldType} {field.Name};";
return signature;
}

private static string GetMethodSignature(MethodInfo method)
{
var signature = "";
if (method.IsPublic)
{
signature += "public ";
}
else if (method.IsPrivate)
{
signature += "private ";
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protected не поддерживаете? Правильно, protected зло.

if (method.IsStatic)
{
signature += "static ";
}

signature += $"{method.ReturnType} {method.Name}";
signature += '(';
var parameters = new List<string>();
foreach (var parameter in method.GetParameters())
{
parameters.Add($"{parameter.ParameterType} {parameter.Name}");
}

signature += string.Join(", ", parameters);
signature += ");";
return signature;
}

private static string GetIndent(int indentCount)
=> string.Concat(Enumerable.Repeat(Indent, indentCount));
}
9 changes: 9 additions & 0 deletions Tasks/Test2/Test2/Test2.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>