33using System . Diagnostics ;
44using System . Diagnostics . Contracts ;
55using System . IO ;
6+ using ReClassNET . CodeGenerator ;
67using ReClassNET . Core ;
8+ using ReClassNET . DataExchange . ReClass ;
79using ReClassNET . Extensions ;
810using ReClassNET . Logger ;
911using ReClassNET . Native ;
10- using ReClassNET . Util ;
12+ using ReClassNET . Nodes ;
13+ using ReClassNET . UI ;
1114
1215namespace ReClassNET . Plugins
1316{
@@ -87,6 +90,9 @@ private void LoadPlugins(IEnumerable<FileInfo> files, ILogger logger, bool check
8790 {
8891 continue ;
8992 }
93+
94+ RegisterNodeInfoReaders ( pi ) ;
95+ RegisterCustomNodeTypes ( pi ) ;
9096 }
9197 else
9298 {
@@ -109,7 +115,17 @@ private void LoadPlugins(IEnumerable<FileInfo> files, ILogger logger, bool check
109115
110116 public void UnloadAllPlugins ( )
111117 {
112- plugins . ForEach ( p => p . Dispose ( ) ) ;
118+ foreach ( var pi in plugins )
119+ {
120+ if ( pi . Interface != null ) // Exclude native plugins
121+ {
122+ DeregisterNodeInfoReaders ( pi ) ;
123+ DeregisterCustomNodeTypes ( pi ) ;
124+ }
125+
126+ pi . Dispose ( ) ;
127+ }
128+
113129 plugins . Clear ( ) ;
114130 }
115131
@@ -140,5 +156,83 @@ private static IntPtr CreateNativePluginInstance(string filePath)
140156 }
141157 return handle ;
142158 }
159+
160+ private static void RegisterNodeInfoReaders ( PluginInfo pluginInfo )
161+ {
162+ Contract . Requires ( pluginInfo != null ) ;
163+
164+ var nodeInfoReaders = pluginInfo . Interface . GetNodeInfoReaders ( ) ;
165+
166+ if ( nodeInfoReaders == null || nodeInfoReaders . Count == 0 )
167+ {
168+ return ;
169+ }
170+
171+ pluginInfo . NodeInfoReaders = nodeInfoReaders ;
172+
173+ BaseNode . NodeInfoReader . AddRange ( nodeInfoReaders ) ;
174+ }
175+
176+ private static void DeregisterNodeInfoReaders ( PluginInfo pluginInfo )
177+ {
178+ Contract . Requires ( pluginInfo != null ) ;
179+
180+ if ( pluginInfo . NodeInfoReaders == null )
181+ {
182+ return ;
183+ }
184+
185+ foreach ( var reader in pluginInfo . NodeInfoReaders )
186+ {
187+ BaseNode . NodeInfoReader . Remove ( reader ) ;
188+ }
189+ }
190+
191+ private static void RegisterCustomNodeTypes ( PluginInfo pluginInfo )
192+ {
193+ Contract . Requires ( pluginInfo != null ) ;
194+
195+ var customNodeTypes = pluginInfo . Interface . GetCustomNodeTypes ( ) ;
196+
197+ if ( customNodeTypes == null )
198+ {
199+ return ;
200+ }
201+
202+ if ( customNodeTypes . NodeTypes == null || customNodeTypes . Serializer == null || customNodeTypes . CodeGenerator == null )
203+ {
204+ throw new ArgumentException ( ) ; // TODO
205+ }
206+
207+ foreach ( var nodeType in customNodeTypes . NodeTypes )
208+ {
209+ if ( ! nodeType . IsSubclassOf ( typeof ( BaseNode ) ) )
210+ {
211+ throw new ArgumentException ( $ "Type '{ nodeType } ' is not a valid node.") ;
212+ }
213+ }
214+
215+ pluginInfo . CustomNodeTypes = customNodeTypes ;
216+
217+ NodeTypesBuilder . AddPluginNodeGroup ( pluginInfo . Interface , customNodeTypes . NodeTypes ) ;
218+
219+ CustomNodeSerializer . Add ( customNodeTypes . Serializer ) ;
220+ CustomCodeGenerator . Add ( customNodeTypes . CodeGenerator ) ;
221+ }
222+
223+ private static void DeregisterCustomNodeTypes ( PluginInfo pluginInfo )
224+ {
225+ Contract . Requires ( pluginInfo != null ) ;
226+
227+ if ( pluginInfo . CustomNodeTypes == null )
228+ {
229+ return ;
230+ }
231+
232+ NodeTypesBuilder . RemovePluginNodeGroup ( pluginInfo . Interface ) ;
233+
234+ CustomNodeSerializer . Remove ( pluginInfo . CustomNodeTypes . Serializer ) ;
235+ CustomCodeGenerator . Remove ( pluginInfo . CustomNodeTypes . CodeGenerator ) ;
236+ }
143237 }
144238}
0 commit comments