Skip to content

Commit 99aab1a

Browse files
committed
Optimized provider by adding caches in multiple places
1 parent 35a87d1 commit 99aab1a

2 files changed

Lines changed: 83 additions & 28 deletions

File tree

src/NodeDev.Core/NodeProvider.cs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,29 +63,27 @@ IEnumerable<NodeSearchResult> GetPropertiesAndFields(TypeBase type, string text)
6363
// find if the method exists
6464
var methods = type.GetMethods().Where(x => x.Name.Contains(methodCallSplit[^1], StringComparison.OrdinalIgnoreCase));
6565

66+
// only keep the methods that are using the startConnection type, if provided
67+
if (startConnection?.Type?.IsExec == false)
68+
methods = methods.Where(x => x.GetParameters().Any(y => startConnection.Type.IsAssignableTo(y.ParameterType, out _)));
69+
6670
results = results.Concat(methods.Select(x => new MethodCallNode(typeof(MethodCall), x)));
6771

68-
results = results.Concat(GetPropertiesAndFields(type, methodCallSplit[1]));
72+
if (startConnection == null)
73+
results = results.Concat(GetPropertiesAndFields(type, methodCallSplit[1]));
6974
}
7075
}
71-
else if (startConnection?.Type is RealType realType)
76+
else if (startConnection?.Type.IsExec == false)
7277
{
7378
// find if the method exists
74-
IEnumerable<MethodInfo> methods = realType.BackendType.GetMethods(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance);
79+
var methods = startConnection.Type.GetMethods().Where(x => x.Name.Contains(text, StringComparison.OrdinalIgnoreCase) && !x.IsStatic);
7580
// get extensions methods for the realType.BackendType
7681

77-
methods = methods.Concat(GetExtensionMethods(realType, project.TypeFactory)).Where(x => string.IsNullOrWhiteSpace(text) || x.Name.Contains(text, StringComparison.OrdinalIgnoreCase));
78-
79-
results = results.Concat(methods.Select(x => new MethodCallNode(typeof(MethodCall), new RealMethodInfo(project.TypeFactory, x, realType))));
82+
methods = methods.Concat(GetExtensionMethods(startConnection.Type, project.TypeFactory)).Where(x => string.IsNullOrWhiteSpace(text) || x.Name.Contains(text, StringComparison.OrdinalIgnoreCase));
8083

81-
results = results.Concat(GetPropertiesAndFields(realType, text));
82-
}
83-
else if (startConnection?.Type is NodeClassType nodeClassType)
84-
{
85-
// get the properties in that object
86-
results = results.Concat(nodeClassType.NodeClass.Properties.Select(x => new GetPropertyOrFieldNode(typeof(GetPropertyOrField), x)));
84+
results = results.Concat(methods.Select(x => new MethodCallNode(typeof(MethodCall), x)));
8785

88-
results = results.Concat(nodeClassType.NodeClass.Methods.Select(x => new MethodCallNode(typeof(MethodCall), x)));
86+
results = results.Concat(GetPropertiesAndFields(startConnection.Type, text));
8987
}
9088

9189
// add methods, get properties and set properties
@@ -105,18 +103,27 @@ IEnumerable<NodeSearchResult> GetPropertiesAndFields(TypeBase type, string text)
105103
return (object)result;
106104
});
107105

108-
109106
return results;
110107
}
111108

112-
private static IEnumerable<MethodInfo> GetExtensionMethods(TypeBase t, TypeFactory typeFactory)
109+
private static readonly Dictionary<Assembly, List<RealMethodInfo>> ExtensionMethodsMethodsPerType = [];
110+
private static IEnumerable<IMethodInfo> GetExtensionMethods(TypeBase t, TypeFactory typeFactory)
113111
{
114112
var query = AppDomain.CurrentDomain.GetAssemblies()
115113
.Where(x => !x.IsDynamic) // dirty patch to prevent loading types from the generated assemblies
116-
.SelectMany(x => x.GetTypes())
117-
.Where(type => !type.IsGenericType)
118-
.SelectMany(type => type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
119-
.Where(method => method.IsDefined(typeof(ExtensionAttribute), false) && t.IsAssignableTo(typeFactory.Get(method.GetParameters()[0].ParameterType, null), out _));
114+
.SelectMany(assembly =>
115+
{
116+
if (ExtensionMethodsMethodsPerType.TryGetValue(assembly, out var methods))
117+
return methods;
118+
119+
return ExtensionMethodsMethodsPerType[assembly] = assembly
120+
.GetTypes()
121+
.Where(type => !type.IsGenericType)
122+
.SelectMany(x => x.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
123+
.Where(method => method.IsDefined(typeof(ExtensionAttribute), false) && t.IsAssignableTo(typeFactory.Get(method.GetParameters()[0].ParameterType, null), out _))
124+
.Select(x => new RealMethodInfo(typeFactory, x, typeFactory.Get(x.DeclaringType!, null)))
125+
.ToList();
126+
});
120127

121128
return query;
122129
}

src/NodeDev.Core/Types/RealType.cs

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,18 @@ public override string? DefaultTextboxValue
8181
}
8282
}
8383

84-
public override IEnumerable<IMemberInfo> GetMembers()
84+
private readonly Lazy<List<RealMemberInfo>> Members;
85+
private readonly Lazy<List<RealMethodInfo>> Methods;
86+
87+
public override IEnumerable<IMemberInfo> GetMembers() => Members.Value;
88+
89+
private List<RealMemberInfo> GetMembers_()
8590
{
86-
var properties = BackendType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
87-
var fields = BackendType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
91+
var properties = BackendType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
92+
var fields = BackendType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
8893

89-
return properties.Select(x => new RealMemberInfo(x, this)).Concat(fields.Select(x => new RealMemberInfo(x, this)));
90-
}
94+
return properties.Select(x => new RealMemberInfo(x, this)).Concat(fields.Select(x => new RealMemberInfo(x, this))).ToList();
95+
}
9196

9297
public override TypeBase CloneWithGenerics(TypeBase[] newGenerics)
9398
{
@@ -118,29 +123,72 @@ private string GetFriendlyName(TypeBase t)
118123
private string GetFriendlyName(Type t)
119124
{
120125
if (Generics.Length == 0)
126+
{
127+
if (t == typeof(void))
128+
return "void";
129+
else if (t == typeof(string))
130+
return "string";
131+
else if (t.IsPrimitive)
132+
{
133+
if (t == typeof(int))
134+
return "int";
135+
if (t == typeof(bool))
136+
return "bool";
137+
if (t == typeof(double))
138+
return "double";
139+
if (t == typeof(float))
140+
return "float";
141+
if (t == typeof(long))
142+
return "long";
143+
if (t == typeof(decimal))
144+
return "decimal";
145+
if (t == typeof(byte))
146+
return "byte";
147+
if (t == typeof(short))
148+
return "short";
149+
if (t == typeof(uint))
150+
return "uint";
151+
if (t == typeof(ulong))
152+
return "ulong";
153+
if (t == typeof(ushort))
154+
return "ushort";
155+
if (t == typeof(sbyte))
156+
return "sbyte";
157+
if (t == typeof(char))
158+
return "char";
159+
}
160+
121161
return t.Name;
162+
}
122163

123164
// return the name of 't' without the ` and the number, replaced with the actual generic type names
124165
var name = t.Name[..t.Name.IndexOf('`')];
125166
return $"{name}<{string.Join(", ", Generics.Select(GetFriendlyName))}>";
126167
}
127168
public override string FriendlyName => GetFriendlyName(BackendType);
128169

129-
public override IEnumerable<IMethodInfo> GetMethods()
170+
private List<RealMethodInfo> GetMethods_()
171+
{
172+
return BackendType.GetMethods().Select(x => new RealMethodInfo(TypeFactory, x, this)).ToList();
173+
}
174+
175+
public override IEnumerable<IMethodInfo> GetMethods()
130176
{
131-
return BackendType.GetMethods().Select(x => new RealMethodInfo(TypeFactory, x, this));
177+
return Methods.Value;
132178
}
133179

134180
public override IEnumerable<IMethodInfo> GetMethods(string name)
135181
{
136-
return BackendType.GetMethods().Where(x => x.Name == name).Select(x => new RealMethodInfo(TypeFactory, x, this));
182+
return GetMethods().Where(x => x.Name == name);
137183
}
138184

139185
internal RealType(TypeFactory typeFactory, Type backendType, TypeBase[]? generics)
140186
{
141187
TypeFactory = typeFactory;
188+
Members = new Lazy<List<RealMemberInfo>>(GetMembers_);
189+
Methods = new Lazy<List<RealMethodInfo>>(GetMethods_);
142190

143-
if (generics == null)
191+
if (generics == null)
144192
{
145193
if (backendType.IsGenericType && !backendType.IsConstructedGenericType)
146194
throw new Exception("Unable to create real type with undefined generics. To do so you must manually specify the generics through the 'generics' parameter in the RealType constructor");

0 commit comments

Comments
 (0)