-
Notifications
You must be signed in to change notification settings - Fork 0
Кр 3 #28
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
base: master
Are you sure you want to change the base?
Кр 3 #28
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 17 | ||
| VisualStudioVersion = 17.4.33403.182 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kr3", "Kr3\Kr3.csproj", "{5B9C8390-F227-4F23-81BA-AB1885C1DF32}" | ||
| EndProject | ||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestsReflector", "TestsReflector\TestsReflector.csproj", "{15B74937-BD20-4D2E-BBC1-49BA7ABDCF10}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|Any CPU = Debug|Any CPU | ||
| Release|Any CPU = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {5B9C8390-F227-4F23-81BA-AB1885C1DF32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {5B9C8390-F227-4F23-81BA-AB1885C1DF32}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {5B9C8390-F227-4F23-81BA-AB1885C1DF32}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {5B9C8390-F227-4F23-81BA-AB1885C1DF32}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| {15B74937-BD20-4D2E-BBC1-49BA7ABDCF10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {15B74937-BD20-4D2E-BBC1-49BA7ABDCF10}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {15B74937-BD20-4D2E-BBC1-49BA7ABDCF10}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {15B74937-BD20-4D2E-BBC1-49BA7ABDCF10}.Release|Any CPU.Build.0 = Release|Any CPU | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ExtensibilityGlobals) = postSolution | ||
| SolutionGuid = {B0556365-C55B-4AF6-8ACA-ACBA1E439626} | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net7.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| <OutputType>Library</OutputType> | ||
| </PropertyGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,249 @@ | ||||||||||||
| using System.Linq.Expressions; | ||||||||||||
| using System.Reflection; | ||||||||||||
|
|
||||||||||||
| namespace Kr3; | ||||||||||||
|
|
||||||||||||
| public class Reflector | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Надо комментарии |
||||||||||||
| { | ||||||||||||
| private readonly string filePath; | ||||||||||||
|
|
||||||||||||
| public Reflector(string filePath) => this.filePath = filePath; | ||||||||||||
|
|
||||||||||||
| private static string GetVisibilityFromClass(Type someClass) | ||||||||||||
| { | ||||||||||||
| if (someClass.IsNestedPrivate) | ||||||||||||
| { | ||||||||||||
| return "private "; | ||||||||||||
| } | ||||||||||||
| else if (someClass.IsNestedPublic) | ||||||||||||
| { | ||||||||||||
| return "public "; | ||||||||||||
| } | ||||||||||||
| else if (someClass.IsNestedFamily) | ||||||||||||
| { | ||||||||||||
| return "protected "; | ||||||||||||
| } | ||||||||||||
| else if (someClass.IsNestedAssembly) | ||||||||||||
| { | ||||||||||||
| return "internal "; | ||||||||||||
| } | ||||||||||||
| return ""; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static string GetStaticOrNotFromClass(Type someClass) | ||||||||||||
| { | ||||||||||||
| return someClass.IsAbstract && someClass.IsSealed ? "static " : ""; | ||||||||||||
| } | ||||||||||||
|
Comment on lines
+33
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут и ниже лучше через |
||||||||||||
|
|
||||||||||||
| private static string GetVisibilityFromField(FieldInfo someField) | ||||||||||||
| { | ||||||||||||
| if (someField.IsPrivate) | ||||||||||||
| { | ||||||||||||
| return "private "; | ||||||||||||
| } | ||||||||||||
| else if (someField.IsPublic) | ||||||||||||
| { | ||||||||||||
| return "public "; | ||||||||||||
| } | ||||||||||||
| else if (someField.IsFamily) | ||||||||||||
| { | ||||||||||||
| return "protected "; | ||||||||||||
| } | ||||||||||||
| else if (someField.IsAssembly) | ||||||||||||
| { | ||||||||||||
| return "internal "; | ||||||||||||
| } | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Кстати, есть ещё protected internal :) |
||||||||||||
| return ""; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static string GetStaticOrNotFromField(FieldInfo someField) | ||||||||||||
| { | ||||||||||||
| return someField.IsStatic ? "static " : ""; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static string GetStaticOrNotFromMethod(MethodInfo someMethod) | ||||||||||||
| { | ||||||||||||
| return someMethod.IsStatic ? "static " : ""; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static string GetVisibilityFromMethod(MethodInfo someMethod) | ||||||||||||
| { | ||||||||||||
| if (someMethod.IsPrivate) | ||||||||||||
| { | ||||||||||||
| return "private "; | ||||||||||||
| } | ||||||||||||
| else if (someMethod.IsPublic) | ||||||||||||
| { | ||||||||||||
| return "public "; | ||||||||||||
| } | ||||||||||||
| else if (someMethod.IsFamily) | ||||||||||||
| { | ||||||||||||
| return "protected "; | ||||||||||||
| } | ||||||||||||
| else if (someMethod.IsAssembly) | ||||||||||||
| { | ||||||||||||
| return "internal "; | ||||||||||||
| } | ||||||||||||
| return ""; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static string GetVisibilityFromConstructor(ConstructorInfo constructorInfo) | ||||||||||||
| { | ||||||||||||
| if (constructorInfo.IsPrivate) | ||||||||||||
| { | ||||||||||||
| return "private "; | ||||||||||||
| } | ||||||||||||
| else if (constructorInfo.IsPublic) | ||||||||||||
| { | ||||||||||||
| return "public "; | ||||||||||||
| } | ||||||||||||
| else if (constructorInfo.IsFamily) | ||||||||||||
| { | ||||||||||||
| return "protected "; | ||||||||||||
| } | ||||||||||||
| else if (constructorInfo.IsAssembly) | ||||||||||||
| { | ||||||||||||
| return "internal "; | ||||||||||||
| } | ||||||||||||
| return ""; | ||||||||||||
| } | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Так-то MethodInfo и ConstructorInfo — потомки MethodBase (потому что они суть методы), и IsPrivate/IsPublic/и т.д. — это свойства MethodBase. Так что один из этих двух методов не нужен. |
||||||||||||
|
|
||||||||||||
| private void WriteParameters(StreamWriter writer, ParameterInfo[] parameters) | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно было бы сделать решение несколько более ООПшным, если бы разделить читалку структуры класса и писалку результатов в разные классы. |
||||||||||||
| { | ||||||||||||
| var first = true; | ||||||||||||
| foreach (var parameter in parameters) | ||||||||||||
| { | ||||||||||||
| if (first) | ||||||||||||
| { | ||||||||||||
| writer.Write($"{parameter.ParameterType} {parameter.Name}"); | ||||||||||||
| first = false; | ||||||||||||
| } | ||||||||||||
| else | ||||||||||||
| { | ||||||||||||
| writer.Write($" ,{parameter.Name}"); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public void PrintStructure(Type someClass) | ||||||||||||
| { | ||||||||||||
| string className = someClass.Name; | ||||||||||||
| string file = $"{filePath}\\{className}.cs"; | ||||||||||||
|
|
||||||||||||
| using var writer = new StreamWriter(file); | ||||||||||||
|
|
||||||||||||
| var visibility = GetVisibilityFromClass(someClass); | ||||||||||||
| var staticOrNotStatic = GetStaticOrNotFromClass(someClass); | ||||||||||||
| var interfaces = someClass.GetInterfaces(); | ||||||||||||
| if (interfaces.Length == 0) | ||||||||||||
| { | ||||||||||||
| writer.WriteLine($"{visibility}{staticOrNotStatic}class {className}"); | ||||||||||||
| } | ||||||||||||
| else | ||||||||||||
| { | ||||||||||||
| writer.Write($"{visibility}{staticOrNotStatic}class {className} : "); | ||||||||||||
| var first = true; | ||||||||||||
| foreach (var element in interfaces) | ||||||||||||
| { | ||||||||||||
| if (first) | ||||||||||||
| { | ||||||||||||
| writer.Write($"{element.Name}"); | ||||||||||||
| first = false; | ||||||||||||
| } | ||||||||||||
| else | ||||||||||||
| { | ||||||||||||
| writer.Write($" : {element.Name}"); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| writer.WriteLine(); | ||||||||||||
| } | ||||||||||||
| writer.WriteLine("{"); | ||||||||||||
|
|
||||||||||||
| var constructors = someClass.GetConstructors(); | ||||||||||||
| foreach (var constructor in constructors) | ||||||||||||
| { | ||||||||||||
| writer.Write($"\t{GetVisibilityFromConstructor(constructor)}{className}("); | ||||||||||||
| WriteParameters(writer, constructor.GetParameters()); | ||||||||||||
| writer.WriteLine(") {}"); | ||||||||||||
| } | ||||||||||||
| var fields = someClass.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); | ||||||||||||
| foreach (var field in fields) | ||||||||||||
| { | ||||||||||||
| writer.WriteLine($"\t{GetVisibilityFromField(field)}{GetStaticOrNotFromField(field)}{field};"); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| var methods = someClass.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); | ||||||||||||
| foreach (var method in methods) | ||||||||||||
| { | ||||||||||||
| writer.Write($"\t{GetVisibilityFromMethod(method)}{GetStaticOrNotFromMethod(method)}{method.Name} ("); | ||||||||||||
| WriteParameters(writer, method.GetParameters()); | ||||||||||||
| writer.WriteLine(") {throw new OperationCanceledException()}"); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| var nestedClasses = someClass.GetNestedTypes(); | ||||||||||||
| foreach (var nestedClass in nestedClasses) | ||||||||||||
| { | ||||||||||||
| PrintStructure(nestedClass); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| writer.WriteLine("}"); | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static bool CheckIfThereIsMethodFromOneClassInAnother(MethodInfo[] methodsB, MethodInfo methodA) | ||||||||||||
| { | ||||||||||||
| var methodB = methodsB.FirstOrDefault(m => m.Name == methodA.Name && m.GetParameters(). | ||||||||||||
| Select(p => p.ParameterType).SequenceEqual(methodA.GetParameters().Select(p => p.ParameterType))); | ||||||||||||
| return methodB != null; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static void WriteDifferentMethods(StreamWriter writer, | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ну и механизм диффов, видимо, можно было бы в отдельный класс вынести. Тут у Вас принцип единственности ответственности настолько нарушен, насколько это возможно. |
||||||||||||
| MethodInfo[] methodsFirst, MethodInfo[] methodsSecond) | ||||||||||||
| { | ||||||||||||
| foreach (var methodA in methodsFirst) | ||||||||||||
| { | ||||||||||||
| if (!CheckIfThereIsMethodFromOneClassInAnother(methodsSecond, methodA)) | ||||||||||||
| { | ||||||||||||
| writer.Write($"{methodA.Name}\n"); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| private static void WriteDifferentFields(StreamWriter writer, | ||||||||||||
|
Comment on lines
+209
to
+210
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||
| FieldInfo[] fieldsFirst, FieldInfo[] fieldsSecond) | ||||||||||||
| { | ||||||||||||
| foreach (var fieldA in fieldsFirst) | ||||||||||||
| { | ||||||||||||
| if (!CheckIfThereIsFieldFromOneClassInAnother(fieldsSecond, fieldA)) | ||||||||||||
| { | ||||||||||||
| writer.Write($"{fieldA.Name}\n"); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| private static bool CheckIfThereIsFieldFromOneClassInAnother(FieldInfo[] fieldsB, FieldInfo fieldA) | ||||||||||||
| { | ||||||||||||
| var fieldB = fieldsB.FirstOrDefault(f => f.Name == fieldA.Name && f.FieldType == fieldA.FieldType); | ||||||||||||
| return fieldB != null; | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public void DiffClasses(Type a, Type b) | ||||||||||||
| { | ||||||||||||
| string file = $"{filePath}/difference.txt"; | ||||||||||||
|
|
||||||||||||
| using var writer = new StreamWriter(file); | ||||||||||||
|
|
||||||||||||
| WriteDifferentFields(writer, a.GetFields(), b.GetFields()); | ||||||||||||
| WriteDifferentFields(writer, b.GetFields(), a.GetFields()); | ||||||||||||
| WriteDifferentMethods(writer, a.GetMethods(), b.GetMethods()); | ||||||||||||
| WriteDifferentMethods(writer, b.GetMethods(), a.GetMethods()); | ||||||||||||
|
|
||||||||||||
| var nestedClassesA = a.GetNestedTypes(); | ||||||||||||
| var nestedClassesB = b.GetNestedTypes(); | ||||||||||||
| foreach (var nestedClassA in nestedClassesA) | ||||||||||||
| { | ||||||||||||
| foreach (var nestedClassB in nestedClassesB) | ||||||||||||
| { | ||||||||||||
| DiffClasses(nestedClassA, nestedClassB); | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| namespace TestsReflector; | ||
|
|
||
| public class AnotherSum | ||
| { | ||
| private int val; | ||
|
|
||
| public AnotherSum(int value) | ||
| { | ||
| val = value; | ||
| } | ||
|
|
||
| public void AddToSum(int num) | ||
| { | ||
| val += num; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| namespace TestsReflector; | ||
|
|
||
| public class TestClassSum | ||
| { | ||
| private int val; | ||
|
|
||
| public TestClassSum(int value) | ||
| { | ||
| val = value; | ||
| } | ||
|
|
||
| public void Add(int num) | ||
| { | ||
| val += num; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| namespace TestsReflector; | ||
|
|
||
| using Kr3; | ||
| using System.Net.WebSockets; | ||
|
|
||
| public class Tests | ||
| { | ||
| [Test] | ||
| public void TestWithTestPrintStructure() | ||
| { | ||
| var sum = new TestClassSum(0); | ||
| var typeSum = sum.GetType(); | ||
| var reflector = new Reflector(Path.Combine(TestContext.CurrentContext.TestDirectory, "forTests")); | ||
| reflector.PrintStructure(typeSum); | ||
| using var reader = new StreamReader((Path.Combine(TestContext.CurrentContext.TestDirectory, "forTests", "CheckTestClassSum.cs"))); | ||
| var linesForCheck = reader.ReadToEnd().Split('\n'); | ||
| using var anotherReader = new StreamReader((Path.Combine(TestContext.CurrentContext.TestDirectory, "forTests", "TestClassSum.cs"))); | ||
| var linesFromReflector = anotherReader.ReadToEnd().Split('\r'); | ||
|
|
||
| var arrayStringsWithoutSpecialSymbols = new string[linesFromReflector.Length]; | ||
|
|
||
| var i = 0; | ||
| foreach (var line in linesFromReflector) | ||
| { | ||
| var newLine = line.Replace("\n", ""); | ||
| arrayStringsWithoutSpecialSymbols[i] = newLine; | ||
| i++; | ||
| } | ||
|
|
||
| i = 0; | ||
| var j = 0; | ||
| while (i < linesForCheck.Length || j < arrayStringsWithoutSpecialSymbols.Length) | ||
| { | ||
| Assert.That(linesForCheck[i], Is.EqualTo(arrayStringsWithoutSpecialSymbols[j])); | ||
| ++i; | ||
| ++j; | ||
| } | ||
| } | ||
|
|
||
| [Test] | ||
| public void TestWithTestClassDiffClasses() | ||
| { | ||
| var sum = new TestClassSum(0); | ||
| var typeSum = sum.GetType(); | ||
| var anotherSum = new AnotherSum(0); | ||
| var typeAnotherSum= anotherSum.GetType(); | ||
| var reflector = new Reflector(Path.Combine(TestContext.CurrentContext.TestDirectory,"forTests")); | ||
| reflector.DiffClasses(typeSum, typeAnotherSum); | ||
| using var reader = new StreamReader((Path.Combine(TestContext.CurrentContext.TestDirectory, "forTests", "difference.txt"))); | ||
| var lines = reader.ReadToEnd().Split('\n'); | ||
| Assert.That(lines[0], Is.EqualTo("Add")); | ||
| Assert.That(lines[1], Is.EqualTo("AddToSum")); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
namespace лучше писать первой строкой в файле, хотя дело вкуса