1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MicroKernel
.ModelBuilder
.Inspectors
18 using System
.Configuration
;
20 using Castle
.MicroKernel
.Proxy
;
21 using Castle
.MicroKernel
.SubSystems
.Conversion
;
24 /// Inspects the component configuration and type looking for information
25 /// that can influence the generation of a proxy for that component.
27 /// We specifically look for <c>useSingleInterfaceProxy</c> and <c>marshalByRefProxy</c>
28 /// on the component configuration or the <see cref="ComponentProxyBehaviorAttribute"/>
33 public class ComponentProxyInspector
: IContributeComponentModelConstruction
36 /// Seaches for proxy behavior in the configuration and, if unsuccessful
37 /// look for the <see cref="ComponentProxyBehaviorAttribute"/> attribute in
38 /// the implementation type.
40 public virtual void ProcessModel(IKernel kernel
, ComponentModel model
)
42 ReadProxyBehavior(kernel
, model
);
46 /// Reads the proxy behavior associated with the
47 /// component configuration/type and applies it to the model.
49 /// <exception cref="System.Configuration.ConfigurationException">
50 /// If the conversion fails
52 /// <param name="kernel"></param>
53 /// <param name="model"></param>
54 protected virtual void ReadProxyBehavior(IKernel kernel
, ComponentModel model
)
56 ComponentProxyBehaviorAttribute proxyBehaviorAtt
= GetProxyBehaviorFromType(model
.Implementation
);
58 if (proxyBehaviorAtt
== null)
60 proxyBehaviorAtt
= new ComponentProxyBehaviorAttribute();
63 string useSingleInterfaceProxyAttrib
= model
.Configuration
!= null ? model
.Configuration
.Attributes
["useSingleInterfaceProxy"] : null;
64 string marshalByRefProxyAttrib
= model
.Configuration
!= null ? model
.Configuration
.Attributes
["marshalByRefProxy"] : null;
66 ITypeConverter converter
= (ITypeConverter
)kernel
.GetSubSystem(SubSystemConstants
.ConversionManagerKey
);
68 if (useSingleInterfaceProxyAttrib
!= null)
72 proxyBehaviorAtt
.UseSingleInterfaceProxy
= (bool)
73 converter
.PerformConversion(useSingleInterfaceProxyAttrib
, typeof(bool));
75 catch(ConverterException ex
)
77 throw new ConfigurationErrorsException("Could not convert attribute " +
78 "'useSingleInterfaceProxy' to bool. Value is " + useSingleInterfaceProxyAttrib
, ex
);
82 if (marshalByRefProxyAttrib
!= null)
86 proxyBehaviorAtt
.UseMarshalByRefProxy
= (bool)
87 converter
.PerformConversion(marshalByRefProxyAttrib
, typeof(bool));
89 catch(ConverterException ex
)
91 throw new ConfigurationErrorsException("Could not convert attribute " +
92 "'marshalByRefProxy' to bool. Value is " + marshalByRefProxyAttrib
, ex
);
96 ApplyProxyBehavior(proxyBehaviorAtt
, model
);
100 /// Returns a <see cref="ComponentProxyBehaviorAttribute"/> instance if the type
101 /// uses the attribute. Otherwise returns null.
103 /// <param name="implementation"></param>
104 protected virtual ComponentProxyBehaviorAttribute
GetProxyBehaviorFromType(Type implementation
)
106 object[] attributes
= implementation
.GetCustomAttributes(
107 typeof(ComponentProxyBehaviorAttribute
), true);
109 if (attributes
.Length
!= 0)
111 return (ComponentProxyBehaviorAttribute
) attributes
[0];
117 private static void ApplyProxyBehavior(ComponentProxyBehaviorAttribute behavior
, ComponentModel model
)
119 if (behavior
.UseSingleInterfaceProxy
|| behavior
.UseMarshalByRefProxy
)
121 EnsureComponentRegisteredWithInterface(model
);
124 ProxyOptions options
= ProxyUtil
.ObtainProxyOptions(model
, true);
126 options
.UseSingleInterfaceProxy
= behavior
.UseSingleInterfaceProxy
;
127 options
.UseMarshalByRefAsBaseClass
= behavior
.UseMarshalByRefProxy
;
128 options
.AddAdditionalInterfaces(behavior
.AdditionalInterfaces
);
131 private static void EnsureComponentRegisteredWithInterface(ComponentModel model
)
133 if (!model
.Service
.IsInterface
)
135 String message
= String
.Format("The class {0} requested a single interface proxy, " +
136 "however the service {1} does not represent an interface",
137 model
.Implementation
.FullName
, model
.Service
.FullName
);
139 throw new ComponentRegistrationException(message
);