1+ using System . Reflection ;
2+ using RelogicLabs . JSchema . Exceptions ;
3+ using RelogicLabs . JSchema . Tree ;
4+ using RelogicLabs . JSchema . Utilities ;
5+ using static RelogicLabs . JSchema . Message . ErrorCode ;
6+ using static RelogicLabs . JSchema . Message . MessageFormatter ;
7+
8+ namespace RelogicLabs . JSchema . Functions ;
9+
10+ internal static class FunctionLoader
11+ {
12+ public static FunctionMap Load ( Type providerImpl , Context ? context = null )
13+ {
14+ var instance = CreateInstance ( providerImpl , context ) ;
15+ var providerBase = typeof ( FunctionProvider ) ;
16+ var functions = new FunctionMap ( ) ;
17+ foreach ( var m in providerImpl . GetMethods ( ) )
18+ {
19+ // Methods in ancestor class or in base class
20+ if ( ! providerBase . IsAssignableFrom ( m . DeclaringType )
21+ || providerBase == m . DeclaringType ) continue ;
22+ ParameterInfo [ ] parameters = m . GetParameters ( ) ;
23+ if ( ! IsValidReturnType ( m . ReturnType ) ) throw failOnReturnType ( m , context ) ;
24+ if ( parameters . Length == 0 || parameters [ 0 ] . IsParams ( ) )
25+ throw failOnTargetParameter ( m , context ) ;
26+ functions . Add ( new NativeFunction ( m , parameters , instance ) ) ;
27+ }
28+ return functions ;
29+ }
30+
31+ private static FunctionProvider CreateInstance ( Type type , Context ? context )
32+ {
33+ try
34+ {
35+ var instance = ( FunctionProvider ? ) Activator . CreateInstance ( type ) ;
36+ if ( instance != null ) return instance ;
37+ }
38+ catch ( TargetInvocationException ex ) { throw FailOnCreateInstance ( INST01 , ex , type , context ) ; }
39+ catch ( MissingMethodException ex ) { throw FailOnCreateInstance ( INST02 , ex , type , context ) ; }
40+ catch ( MethodAccessException ex ) { throw FailOnCreateInstance ( INST03 , ex , type , context ) ; }
41+ catch ( MemberAccessException ex ) { throw FailOnCreateInstance ( INST04 , ex , type , context ) ; }
42+ catch ( TypeLoadException ex ) { throw FailOnCreateInstance ( INST05 , ex , type , context ) ; }
43+ catch ( FileNotFoundException ex ) { throw FailOnCreateInstance ( INST06 , ex , type , context ) ; }
44+ catch ( NotSupportedException ex ) { throw FailOnCreateInstance ( INST07 , ex , type , context ) ; }
45+ catch ( BadImageFormatException ex ) { throw FailOnCreateInstance ( INST08 , ex , type , context ) ; }
46+ catch ( FileLoadException ex ) { throw FailOnCreateInstance ( INST09 , ex , type , context ) ; }
47+ catch ( Exception ex ) { throw FailOnCreateInstance ( INST10 , ex , type , context ) ; }
48+ throw FailOnCreateInstance ( INST11 , null , type , context ) ;
49+ }
50+
51+ private static bool IsValidReturnType ( Type type )
52+ {
53+ if ( type == typeof ( bool ) ) return true ;
54+ if ( type == typeof ( FutureFunction ) ) return true ;
55+ return false ;
56+ }
57+
58+ private static ClassInstantiationException FailOnCreateInstance ( string code , Exception ? ex ,
59+ Type type , Context ? context )
60+ => new ( FormatForSchema ( code , $ "Fail to create instance of { type . FullName } ", context ) , ex ) ;
61+
62+ private static InvalidFunctionException failOnReturnType ( MethodInfo method , Context ? context )
63+ => new ( FormatForSchema ( FUNC01 , $ "Function [{
64+ method . GetSignature ( ) } ] requires valid return type" , context ) ) ;
65+
66+ private static InvalidFunctionException failOnTargetParameter ( MethodInfo method , Context ? context )
67+ => new ( FormatForSchema ( FUNC02 , $ "Function [{
68+ method . GetSignature ( ) } ] requires valid target parameter" , context ) ) ;
69+ }
0 commit comments