2.2.1. Write the business logic
2.2.2. Testing the business logic
2.2.4. Introducing defensive programming
2.3.1. Requirements will change
2.4.1. Start simple and isolate the logging
2.4.2. Refactor defensive programming
Chapter 3. Call this instead: intercepting methods
3.2. Real-world example: data transactions
3.2.1. Ensuring data integrity with begin and commit
3.3. Real-world example: threading
3.3.1. The basics of .NET threading
Chapter 4. Before and after: boundary aspects
4.1.1. PostSharp method bounding
4.2. Real-world example: detecting mobile users
4.3. Real-world example: caching
4.3.2. An application that could benefit from caching
Chapter 5. Get this instead: intercepting locations
5.2. Real-world example: lazy loading
5.2.1. Lazy loading approaches in .NET
5.3. Real-world example: INotifyPropertyChanged
5.3.1. Using INotifyPropertyChanged in a desktop application
Chapter 6. Unit testing aspects
6.2. Castle DynamicProxy testing
Chapter 7. AOP implementation types
7.4. Runtime versus compile-time weaving
Chapter 8. Using AOP as an architectural tool
8.1. Compile-time initialization and validation
8.1.1. Initializing at compile time
8.2. Architectural constraints
Chapter 9. Aspect composition: example and execution
9.2. Aspect roles with PostSharp
9.3. Composing aspects with DynamicProxy
9.4. Real-world example: caching and authorization
Appendix A. Ecosystem of .NET AOP tools