-
Notifications
You must be signed in to change notification settings - Fork 0
/
ObjectSharedArguments.cs
131 lines (120 loc) · 4.47 KB
/
ObjectSharedArguments.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;
using ObjectToTest.Arguments;
namespace ObjectToTest
{
/// <summary>
/// The idea is to detect the set of objects that used more that one time in different target object arguments.
/// It should allow to reuse the argument injecting it into other object's constructors or property setters.
/// </summary>
public class ObjectSharedArguments : IArguments
{
private readonly object _object;
private List<IArgument>? _sharedObjects;
public ObjectSharedArguments(object @object)
{
_object = @object;
}
private List<IArgument> SharedObjects
{
get
{
if (_sharedObjects == null)
{
_sharedObjects = new List<IArgument>();
SharedObjectsRecursive(_object, new List<object>());
}
return _sharedObjects;
}
}
public IArgument? Argument(object argument)
{
return SharedObjects.FirstOrDefault(a => a.Equals(argument));
}
public override string ToString()
{
var arguments = new StringBuilder();
foreach (var argument in SharedObjects)
{
arguments.AppendLine(argument.ToString() + ";");
}
return arguments.ToString();
}
/**
* @todo #12:60m/DEV Make a code refactoring for this method.
* The method is too big and complex. It looks like the Loops for Fields and Properties are pretty the same.
*/
private void SharedObjectsRecursive(object @object, List<object> internalObjects)
{
var currentObjectStates = new List<object>();
foreach (PropertyInfo property in @object.GetType().GetProperties())
{
var propertyObject = @object.Value(property);
if (Skip(propertyObject) || currentObjectStates.Contains(propertyObject))
{
continue;
}
if (internalObjects.Contains(propertyObject))
{
if (!_sharedObjects.Any(so => so.Equals(propertyObject)))
{
_sharedObjects.Add(
new SharedArgument(
new Argument(
VariableName(propertyObject),
propertyObject.ValidConstructor(this)
)
)
);
}
}
else
{
internalObjects.Add(propertyObject);
}
currentObjectStates.Add(propertyObject);
SharedObjectsRecursive(propertyObject, internalObjects);
}
foreach (FieldInfo field in @object.GetType().GetRuntimeFields())
{
var fieldObject = @object.Value(field);
if (Skip(fieldObject) || currentObjectStates.Contains(fieldObject))
{
continue;
}
if (internalObjects.Contains(fieldObject))
{
if (!_sharedObjects.Any(so => so.Equals(fieldObject)))
{
_sharedObjects.Add(
new SharedArgument(
new Argument(
VariableName(fieldObject),
fieldObject.ValidConstructor(this)
)
)
);
}
}
else
{
internalObjects.Add(fieldObject);
}
currentObjectStates.Add(fieldObject);
SharedObjectsRecursive(fieldObject, internalObjects);
}
}
private string VariableName(object @object)
{
return Char.ToLower(@object.GetType().Name[0]) + @object.GetType().Name.Substring(1);
}
private bool Skip(object? @object)
{
return @object == null || @object.IsPrimitive() || @object.IsCollection() || @object is TimeSpan || @object is DateTime;
}
}
}