Fixing an issue with output parameters that are of type IntPtr
[castle.git] / AspectSharp / docs / tutorial.html
blob1528de53d5733e3dd0555099d5e387c6e460b300
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2 <html>
4 <head>
5 <meta content="text/html;charset=ISO-8859-1" http-equiv="content-type">
6 <meta content="en" http-equiv="content-language">
7 <meta name="robots" content="index, follow/">
8 <meta name="keywords" content="AOP, Aspect, Aspect Oriented Programming, .NET, DotNet, C#, Aspect .Net, Aspect Sharp, AspectSharp, Aspect #, Aspect#, AOP .Net, Aspect Oriented Programming .NET " />
9 <meta name="description" content="A .NET AOP Framework, it uses Dynamic Proxies and XML configuration files as basis." />
10 <title>Aspect# - Two minutes tutorial</title>
11 <style type="text/css">
12 <!--
13 body
15 font-family: verdana;
16 font-size:x-small;
20 color: navy;
22 a:hover
24 color: blue;
28 color:green;
30 table
32 font-size:x-small;
34 .code
36 font-family:"Lucida Console", "Courier New", Courier;
37 font-size:small;
38 background-color: #DDDDDD;
39 width: 100%;
40 border: 2px dashed #000000;
41 margin: 2pt;
42 padding: 2pt;
44 -->
45 </style>
46 </head>
49 <body>
50 <table border="1" cellspacing="0" bordercolor="black" width="100%">
51 <tr>
52 <td>Aspect# - An AOP framework for the .NET</td>
53 </tr>
54 </table>
56 <h1><img src="http://aspectsharp.sourceforge.net/logo.gif" alt="Aspect# Logo. By Ricardo Aloise." /></h1>
58 <p></p>
61 <h3>A two minutes tutorial</h3>
63 <p> So you think your project might benefit from some AOP approach. This tutorial
64 introduces the Aspect# approach for AOP. Basically we are going to talk about
65 the Aspect# built-in language for declaring aspects, mixins and interceptors.</p>
66 <h4>An hypothetical (?) situation</h4>
67 <p>To make things more interesting, lets suppose you're working on a specific
68 application. You're creating a revolutionary Content Management System, and
69 you probably end up with a big although simple and nice object model. The most
70 important components implement IContentProvider and IView. The first is obviously
71 responsible for gathering content from some source like database, Xml, RSS,
72 Excel files and the former is responsible for displaying it in a specific way
73 for a specific channel. </p>
74 <p>Everything is fine and you almost done with your four thousands of ContentProviders
75 and Views that covers all existing communications channels available in the
76 world today. Suddently, the sales guy - always blame the sales guy - comes with,
77 from his standpoint, an non-important requirement. He needs security checking
78 for providers and views, and he already sold it as done for an important customer,
79 lets say BBC. Your company's future depends on it completed by the end of the
80 day!</p>
81 <h4>The available solutions</h4>
82 <p>You need to expose your objects as sensitive resource for your security framework.
83 To easy the burden of having to change every single ContentProvider and View
84 you think about a few possibilities:</p>
85 <p>- Create a property on IContentProvider and on IView exposing the IResource
86 information.</p>
87 <p>- Create an &quot;IResourceable&quot; and making IContentProvider and IView
88 extend from it.. Then modifing its bases classes, although you're not sure whether
89 such base class exists.</p>
90 <p>- You're on the ninth floor, so jump off the window could solve things for
91 a while...</p>
92 <p>The problem with these possibilities is that it will bungle your nice and clean
93 object model. In your conception security doesn't have anything to do with content
94 providers and views, but for some of them it makes sense. So, for those that
95 make sense you'd like to introduce the ISecurityResource interface and implementation.</p>
96 <p>Well, c'mon! You only have a few hours, start to modify those components now!
97 Not so fast, let's use AOP for it.</p>
98 <h4>The Mixin solution</h4>
99 <p>A lot of AOP frameworks nowadays implements the mixin functionality, although
100 it's not really an AOP conception, but while this is introducing something to
101 a class of a set of classes, then its all right, we can call it AOP.</p>
102 <p>The idea here is to make all ContentProvider in a given namespace implement
103 the ISecurityResource interface which a valid implementation, of course. We
104 can do this like this</p>
107 <p class="code">public class SecurityResourceImpl : ISecurityResource<br/>
108 {<br/>
109 &nbsp;&nbsp;public SecurityResourceImpl()<br/>
110 &nbsp;&nbsp;{<br/>
111 &nbsp;&nbsp;}
112 <br/><br/>
113 &nbsp;&nbsp;public String ResourceName<br/>
114 &nbsp;&nbsp;{<br/>
115 &nbsp;&nbsp;&nbsp;&nbsp;get { return "Content"; }<br/>
116 &nbsp;&nbsp;}<br/>
117 }</p>
119 <p>Now we need to apply this to a particular class or to a set of classes in our
120 project.</p>
121 <h4>Describing your aspect configuration</h4>
122 <p>We use a built-in language (Ruby like) to configure the aspects. You can keep
123 this configuration in a external file, in your code (not recommended) or in
124 the .config file associated with your application.</p>
125 <pre class="code">
126 import YourCompany.CMS.ContentProviders in YourCompanyAssembly
128 aspect SecurityAspect for RSSContentProvider
130 include Mixins.SecurityResourceImpl in MyMixinsAssembly
133 </pre>
134 <p>This aspect targets the RSSContentProvider class and includes the SecurityResourceImpl
135 class. What does it mean? Well, when you get your RSSContentProvider instance
136 it will have the ISecurityResource interface implemented by the SecurityResourceImpl.
137 You mixed them, hence Mixin :-)
138 </p>
139 <p>Instead of targeting a specific class, you can targets a set of classes
140 like all the classes in the given namespace:</p>
141 <pre class="code">
142 import YourCompany.CMS.ContentProviders in YourCompanyAssembly
144 aspect SecurityAspect for [ YourCompany.CMS.ContentProviders ]
146 include Mixins.SecurityResourceImpl in MyMixinsAssembly
149 </pre>
150 <p>Now we need to create an Aspect# engine to do this magic:</p>
152 <p class="code">
153 StreamReader reader = new StreamReader( configfile );<br/>
154 AspectEngineBuilder builder = new AspectLanguageEngineBuilder(reader);<br/><br/>
156 AspectEngine engine = builder.Build();<br/>
157 RSSContentProvider provider = engine.Wrap( new RSSContentProvider() );<br/>
158 </p>
161 "<i>But wait a minute! This is a very naive implementation of ISecurityResource. And if
162 the security resource needs to access something from the content provider or the view? Gotcha!"</i>
163 </p>
165 Not really. If your mixin needs to access the underlying component it must implements the IProxyAware interface:
166 </p>
167 <p class="code">public class SecurityResourceImpl : ISecurityResource, <b>IProxyAware</b><br/>
168 {<br/>
169 &nbsp;&nbsp;private String _name;
170 <br/><br/>
171 &nbsp;&nbsp;public SecurityResourceImpl()<br/>
172 &nbsp;&nbsp;{<br/>
173 &nbsp;&nbsp;}
174 <br/><br/>
175 &nbsp;&nbsp;<b>public void SetProxy(object proxy)<br/>
176 &nbsp;&nbsp;{<br/>
177 &nbsp;&nbsp;&nbsp;&nbsp;if (proxy is IContentProvider)<br/>
178 &nbsp;&nbsp;&nbsp;&nbsp;{<br/>
179 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name = (proxy as IContentProvider).Name;<br/>
180 &nbsp;&nbsp;&nbsp;&nbsp;}<br/>
181 &nbsp;&nbsp;&nbsp;&nbsp;else if (proxy is IView)<br/>
182 &nbsp;&nbsp;&nbsp;&nbsp;{<br/>
183 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name = (proxy as IView).Name;<br/>
184 &nbsp;&nbsp;&nbsp;&nbsp;}<br/>
185 &nbsp;&nbsp;}</b>
186 <br/><br/>
187 &nbsp;&nbsp;public String Name<br/>
188 &nbsp;&nbsp;{<br/>
189 &nbsp;&nbsp;&nbsp;&nbsp;get { return _name; }<br/>
190 &nbsp;&nbsp;&nbsp;&nbsp;set { _name = value; }<br/>
191 &nbsp;&nbsp;}
192 <br/><br/>
193 &nbsp;&nbsp;public String ResourceName<br/>
194 &nbsp;&nbsp;{<br/>
195 &nbsp;&nbsp;&nbsp;&nbsp;get { return Name; }<br/>
196 &nbsp;&nbsp;}<br/>
197 }</p>
199 <p>Your mixin doesn't need to implement or expose anything, but if it does
200 implement some interface then the Wrap'ed
201 instance will expose them and forward the calls.
202 Your mixin must have a default constructor, though.
203 </p>
206 <h4>Intercepting calls</h4>
209 The most sensitive method in IContentProvider is the RetrieveContent method, so
210 for every content provider, which implements the ISecurityResource interface, it is a good idea
211 to invoke the ISecurityResource.Demand() to fire all security checks.
212 </p>
214 Time to change the content provider code... well wait! Maybe Aspect# can help us implementing this
215 check for us.
216 </p>
218 You're right! All we need to do is intercept the methods we want to and performing the check.
219 First we need a pointcut which will select the methods or properties. Within a pointcut you can
220 add advices that will performe some action on the resulting Joinpoints.
221 </p>
223 What a lot of new words! Ok, so lets get things clear:
224 <ul>
225 <li>Pointcut: selects methods and|or properties within a type (including the mixins)
226 <li>Joinpoints: method or properties that matched the pointcut
227 <li>Advice: some code that will be performed before|after the joinpoint.
228 </ul>
229 </p>
231 Aspect# supports only one type of advice: MethodInterceptor. MethodInterceptors allow
232 you to execute some code before and|or after a target method. Lets do it:
233 </p>
235 <p class="code">
237 import YourCompany.CMS.ContentProviders in YourCompanyAssembly<br/>
238 import YourCompany.CMS.Aop.Interceptors<br/><br/>
240 aspect SecurityAspect for RSSContentProvider<br/><br/>
241 &nbsp;&nbsp;include Mixins.SecurityResourceImpl in MyMixinsAssembly<br/>
242 <br/>
243 &nbsp;&nbsp;pointcut method(* RetrieveContent(*))<br/>
244 &nbsp;&nbsp;&nbsp;&nbsp;advice(SecurityCheckInterceptor)<br/>
245 &nbsp;&nbsp;end<br/><br/>
248 </p>
250 Our pointcut states 'I don't care about the return value, just match
251 all methods named RetrieveContent and I don't care about its arguments either'.
252 So we don't have to worry about others methods being checked unnecessarily.
253 </p>
255 And now for something completely different: our MethodInterceptor implementation:
256 </p>
258 <pre class="code">
260 public class SecurityCheckInterceptor : IMethodInterceptor
262 public object Invoke(IMethodInvocation invocation)
264 ISecurityResource target = invocation.GetThis() as ISecurityResource;
265 target.Demand(); // Can throw a SecurityException
267 return invocation.Proceed(); // All right, get on with it
271 </pre>
274 This implementation is pretty straightforward. Please note that the GetThis
275 returns the proxy, so if you, for instance, invoke RetrieveContent within
276 the interceptor then your
277 interceptor will be called again and you can end up with a stack overflow.
278 </p>
283 <h4>Conclusion</h4>
285 <p>Now our two minutes tutorial is over. If you're complaining that you spent more than two minutes
286 reading this, well.. I'm a slow reader myself :-)</p>
288 <h4>Where to go from here?</h4>
291 <ul>
292 <li><a href="languageref.html">Aspect# Language Documentation</a>
293 <li><a href="">Aspect# Documentation</a>
294 </ul>
295 </p>
297 <hr noshade>
298 <p>20-09-04 - The Aspect# Team
299 </p>
302 </body>
303 </html>