1- // This software is part of the Autofac IoC container 
2- // Copyright (c) 2007 - 2010 Autofac Contributors 
3- // http://autofac.org 
4- // 
5- // Permission is hereby granted, free of charge, to any person 
6- // obtaining a copy of this software and associated documentation 
7- // files (the "Software"), to deal in the Software without 
8- // restriction, including without limitation the rights to use, 
9- // copy, modify, merge, publish, distribute, sublicense, and/or sell 
10- // copies of the Software, and to permit persons to whom the 
11- // Software is furnished to do so, subject to the following 
12- // conditions: 
13- // 
14- // The above copyright notice and this permission notice shall be 
15- // included in all copies or substantial portions of the Software. 
16- // 
17- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
18- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
19- // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
20- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
21- // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
22- // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
23- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
24- // OTHER DEALINGS IN THE SOFTWARE. 
25- 
26- using  System ; 
27- using  System . Collections . Generic ; 
28- using  System . Diagnostics . CodeAnalysis ; 
29- using  System . Linq ; 
30- using  System . Reflection ; 
31- using  Autofac ; 
32- using  Autofac . Core ; 
33- using  Castle . DynamicProxy ; 
34- 
35- namespace  Autofac . Extras . AggregateService 
36- { 
37-     /// <summary> 
38-     /// Interceptor that resolves types of properties and methods using a <see cref="IComponentContext"/>. 
39-     /// </summary> 
40-     public  class  ResolvingInterceptor  :  IInterceptor 
41-     { 
42-         private  readonly  IComponentContext  _context ; 
43-         private  readonly  Dictionary < MethodInfo ,  Action < IInvocation > >  _invocationMap ; 
44- 
45-         ///<summary> 
46-         /// Initialize <see cref="ResolvingInterceptor"/> with an interface type and a component context. 
47-         ///</summary> 
48-         public  ResolvingInterceptor ( Type  interfaceType ,  IComponentContext  context ) 
49-         { 
50-             _context  =  context ; 
51-             _invocationMap  =  SetupInvocationMap ( interfaceType ) ; 
52-         } 
53- 
54-         /// <summary> 
55-         /// Intercepts a method invocation. 
56-         /// </summary> 
57-         /// <param name="invocation"> 
58-         /// The method invocation to intercept. 
59-         /// </param> 
60-         public  void  Intercept ( IInvocation  invocation ) 
61-         { 
62-             if  ( invocation  ==  null ) 
63-             { 
64-                 throw  new  ArgumentNullException ( "invocation" ) ; 
65-             } 
66-             var  invocationHandler  =  _invocationMap [ invocation . Method ] ; 
67-             invocationHandler ( invocation ) ; 
68-         } 
69- 
70-         private  Dictionary < MethodInfo ,  Action < IInvocation > >  SetupInvocationMap ( Type  interfaceType ) 
71-         { 
72-             var  methods  =  interfaceType 
73-                 . GetUniqueInterfaces ( ) 
74-                 . SelectMany ( x =>  x . GetMethods ( ) ) 
75-                 . ToArray ( ) ; 
76- 
77-             var  methodMap  =  new  Dictionary < MethodInfo ,  Action < IInvocation > > ( methods . Count ( ) ) ; 
78-             foreach  ( var  method  in  methods ) 
79-             { 
80-                 var  returnType  =  method . ReturnType ; 
81- 
82-                 if  ( returnType  ==  typeof ( void ) ) 
83-                 { 
84-                     // Any method with 'void' return type (includes property setters) should throw an exception 
85-                     methodMap . Add ( method ,  InvalidReturnTypeInvocation ) ; 
86-                 } 
87-                 else  if  ( GetProperty ( method )  !=  null ) 
88-                 { 
89-                     // All properties should be resolved at proxy instantiation  
90-                     var  propertyValue  =  _context . Resolve ( returnType ) ; 
91-                     methodMap . Add ( method ,  invocation =>  invocation . ReturnValue  =  propertyValue ) ; 
92-                 } 
93-                 else 
94-                 { 
95-                     // For methods with parameters, cache parameter info for use at invocation time 
96-                     var  parameters  =  method . GetParameters ( ) 
97-                         . OrderBy ( parameterInfo =>  parameterInfo . Position ) 
98-                         . Select ( parameterInfo =>  new  {  parameterInfo . Position ,  parameterInfo . ParameterType  } ) 
99-                         . ToArray ( ) ; 
100- 
101-                     if  ( parameters . Length  >  0 ) 
102-                     { 
103-                         methodMap . Add ( method ,  invocation => 
104-                                                   { 
105-                                                       var  arguments  =  invocation . Arguments ; 
106-                                                       var  typedParameters  =  parameters 
107-                                                           . Select ( info =>  ( Parameter ) new  TypedParameter ( info . ParameterType ,  arguments [ info . Position ] ) ) ; 
108- 
109-                                                       invocation . ReturnValue  =  _context . Resolve ( returnType ,  typedParameters ) ; 
110-                                                   } ) ; 
111-                     } 
112-                     else 
113-                     { 
114-                         var  methodWithoutParams  =  GetType ( ) 
115-                             . GetMethod ( "MethodWithoutParams" ,  BindingFlags . Instance  |  BindingFlags . NonPublic ) 
116-                             . MakeGenericMethod ( new [ ]  {  returnType  } ) ; 
117- 
118-                         var  methodWithoutParamsDelegate  =  ( Action < IInvocation > ) Delegate . CreateDelegate ( typeof ( Action < IInvocation > ) ,  this ,  methodWithoutParams ) ; 
119-                         methodMap . Add ( method ,  methodWithoutParamsDelegate ) ; 
120-                     } 
121-                 } 
122-             } 
123- 
124-             return  methodMap ; 
125-         } 
126- 
127-         // ReSharper disable UnusedMember.Local 
128-         [ SuppressMessage ( "Microsoft.Performance" ,  "CA1811:AvoidUncalledPrivateCode" ,  Justification  =  "This method gets called via reflection." ) ] 
129-         private  void  MethodWithoutParams < TReturnType > ( IInvocation  invocation ) 
130-         // ReSharper restore UnusedMember.Local 
131-         { 
132-             invocation . ReturnValue  =  _context . Resolve < TReturnType > ( ) ; 
133-         } 
134- 
135-         private  static void  InvalidReturnTypeInvocation ( IInvocation  invocation ) 
136-         { 
137-             throw  new  InvalidOperationException ( "The method "  +  invocation . Method  +  " has invalid return type System.Void" ) ; 
138-         } 
139- 
140-         private  static PropertyInfo  GetProperty ( MethodInfo  method ) 
141-         { 
142-             var  takesArg  =  method . GetParameters ( ) . Length  ==  1 ; 
143-             var  hasReturn  =  method . ReturnType  !=  typeof ( void ) ; 
144-             if  ( takesArg  ==  hasReturn )  return  null ; 
145-             // Ignore setters 
146-             //if (takesArg) 
147-             //{ 
148-             //    return method.DeclaringType.GetProperties() 
149-             //        .Where(prop => prop.GetSetMethod() == method).FirstOrDefault(); 
150-             //} 
151- 
152-             return  method . DeclaringType . GetProperties ( ) 
153-                 . Where ( prop =>  prop . GetGetMethod ( )  ==  method ) . FirstOrDefault ( ) ; 
154-         } 
155-     } 
1+ // This software is part of the Autofac IoC container 
2+ // Copyright (c) 2007 - 2010 Autofac Contributors 
3+ // http://autofac.org 
4+ // 
5+ // Permission is hereby granted, free of charge, to any person 
6+ // obtaining a copy of this software and associated documentation 
7+ // files (the "Software"), to deal in the Software without 
8+ // restriction, including without limitation the rights to use, 
9+ // copy, modify, merge, publish, distribute, sublicense, and/or sell 
10+ // copies of the Software, and to permit persons to whom the 
11+ // Software is furnished to do so, subject to the following 
12+ // conditions: 
13+ // 
14+ // The above copyright notice and this permission notice shall be 
15+ // included in all copies or substantial portions of the Software. 
16+ // 
17+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
18+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
19+ // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
20+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
21+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
22+ // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
23+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
24+ // OTHER DEALINGS IN THE SOFTWARE. 
25+ 
26+ using  System ; 
27+ using  System . Collections . Generic ; 
28+ using  System . Diagnostics . CodeAnalysis ; 
29+ using  System . Globalization ; 
30+ using  System . Linq ; 
31+ using  System . Reflection ; 
32+ using  Autofac ; 
33+ using  Autofac . Core ; 
34+ using  Castle . DynamicProxy ; 
35+ 
36+ namespace  Autofac . Extras . AggregateService 
37+ { 
38+     /// <summary> 
39+     /// Interceptor that resolves types of properties and methods using a <see cref="IComponentContext"/>. 
40+     /// </summary> 
41+     public  class  ResolvingInterceptor  :  IInterceptor 
42+     { 
43+         private  readonly  IComponentContext  _context ; 
44+ 
45+         private  readonly  Dictionary < MethodInfo ,  Action < IInvocation > >  _invocationMap ; 
46+ 
47+         /// <summary> 
48+         /// Initialize <see cref="ResolvingInterceptor"/> with an interface type and a component context. 
49+         /// </summary> 
50+         public  ResolvingInterceptor ( Type  interfaceType ,  IComponentContext  context ) 
51+         { 
52+             _context  =  context ; 
53+             _invocationMap  =  SetupInvocationMap ( interfaceType ) ; 
54+         } 
55+ 
56+         /// <summary> 
57+         /// Intercepts a method invocation. 
58+         /// </summary> 
59+         /// <param name="invocation"> 
60+         /// The method invocation to intercept. 
61+         /// </param> 
62+         public  void  Intercept ( IInvocation  invocation ) 
63+         { 
64+             if  ( invocation  ==  null ) 
65+             { 
66+                 throw  new  ArgumentNullException ( "invocation" ) ; 
67+             } 
68+ 
69+             // Generic methods need to use the open generic method definition. 
70+             var  method  =  invocation . Method . IsGenericMethod  ?  invocation . Method . GetGenericMethodDefinition ( )  :  invocation . Method ; 
71+             var  invocationHandler  =  _invocationMap [ method ] ; 
72+             invocationHandler ( invocation ) ; 
73+         } 
74+ 
75+         private  static PropertyInfo  GetProperty ( MethodInfo  method ) 
76+         { 
77+             var  takesArg  =  method . GetParameters ( ) . Length  ==  1 ; 
78+             var  hasReturn  =  method . ReturnType  !=  typeof ( void ) ; 
79+ 
80+             if  ( takesArg  ==  hasReturn ) 
81+             { 
82+                 return  null ; 
83+             } 
84+ 
85+             return  method 
86+                 . DeclaringType 
87+                 . GetProperties ( ) 
88+                 . Where ( prop =>  prop . GetGetMethod ( )  ==  method ) 
89+                 . FirstOrDefault ( ) ; 
90+         } 
91+ 
92+         private  static void  InvalidReturnTypeInvocation ( IInvocation  invocation ) 
93+         { 
94+             throw  new  InvalidOperationException ( String . Format ( CultureInfo . InvariantCulture ,  "The method {0} has invalid return type System.Void" ,  invocation . Method ) ) ; 
95+         } 
96+ 
97+         [ SuppressMessage ( "Microsoft.Performance" ,  "CA1811:AvoidUncalledPrivateCode" ,  Justification  =  "This method gets called via reflection." ) ] 
98+         private  void  MethodWithoutParams ( IInvocation  invocation ) 
99+         { 
100+             // To handle open generics, this resolves the return type of the invocation rather than the scanned method. 
101+             invocation . ReturnValue  =  _context . Resolve ( invocation . Method . ReturnType ) ; 
102+         } 
103+ 
104+         private  Dictionary < MethodInfo ,  Action < IInvocation > >  SetupInvocationMap ( Type  interfaceType ) 
105+         { 
106+             var  methods  =  interfaceType 
107+                 . GetUniqueInterfaces ( ) 
108+                 . SelectMany ( x =>  x . GetMethods ( ) ) 
109+                 . ToArray ( ) ; 
110+ 
111+             var  methodMap  =  new  Dictionary < MethodInfo ,  Action < IInvocation > > ( methods . Count ( ) ) ; 
112+             foreach  ( var  method  in  methods ) 
113+             { 
114+                 var  returnType  =  method . ReturnType ; 
115+ 
116+                 if  ( returnType  ==  typeof ( void ) ) 
117+                 { 
118+                     // Any method with 'void' return type (includes property setters) should throw an exception 
119+                     methodMap . Add ( method ,  InvalidReturnTypeInvocation ) ; 
120+                     continue ; 
121+                 } 
122+ 
123+                 if  ( GetProperty ( method )  !=  null ) 
124+                 { 
125+                     // All properties should be resolved at proxy instantiation 
126+                     var  propertyValue  =  _context . Resolve ( returnType ) ; 
127+                     methodMap . Add ( method ,  invocation =>  invocation . ReturnValue  =  propertyValue ) ; 
128+                     continue ; 
129+                 } 
130+ 
131+                 // For methods with parameters, cache parameter info for use at invocation time 
132+                 var  parameters  =  method . GetParameters ( ) 
133+                     . OrderBy ( parameterInfo =>  parameterInfo . Position ) 
134+                     . Select ( parameterInfo =>  new  {  parameterInfo . Position ,  parameterInfo . ParameterType  } ) 
135+                     . ToArray ( ) ; 
136+ 
137+                 if  ( parameters . Length  >  0 ) 
138+                 { 
139+                     // Methods with parameters 
140+                     methodMap . Add ( method ,  invocation => 
141+                         { 
142+                             var  arguments  =  invocation . Arguments ; 
143+                             var  typedParameters  =  parameters 
144+                                 . Select ( info =>  ( Parameter ) new  TypedParameter ( info . ParameterType ,  arguments [ info . Position ] ) ) ; 
145+ 
146+                             // To handle open generics, this resolves the return type of the invocation rather than the scanned method. 
147+                             invocation . ReturnValue  =  _context . Resolve ( invocation . Method . ReturnType ,  typedParameters ) ; 
148+                         } ) ; 
149+ 
150+                     continue ; 
151+                 } 
152+ 
153+                 // Methods without parameters 
154+                 var  methodWithoutParams  =  this . GetType ( ) . GetMethod ( "MethodWithoutParams" ,  BindingFlags . Instance  |  BindingFlags . NonPublic ) ; 
155+                 var  methodWithoutParamsDelegate  =  ( Action < IInvocation > ) Delegate . CreateDelegate ( typeof ( Action < IInvocation > ) ,  this ,  methodWithoutParams ) ; 
156+                 methodMap . Add ( method ,  methodWithoutParamsDelegate ) ; 
157+             } 
158+ 
159+             return  methodMap ; 
160+         } 
161+     } 
156162} 
0 commit comments