diff --git a/2014.02.February/AOP/Demo/.nuget/NuGet.Config b/2014.02.February/AOP/Demo/.nuget/NuGet.Config
new file mode 100644
index 0000000..67f8ea0
--- /dev/null
+++ b/2014.02.February/AOP/Demo/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/.nuget/NuGet.exe b/2014.02.February/AOP/Demo/.nuget/NuGet.exe
new file mode 100644
index 0000000..9cba6ed
Binary files /dev/null and b/2014.02.February/AOP/Demo/.nuget/NuGet.exe differ
diff --git a/2014.02.February/AOP/Demo/.nuget/NuGet.targets b/2014.02.February/AOP/Demo/.nuget/NuGet.targets
new file mode 100644
index 0000000..2c3545b
--- /dev/null
+++ b/2014.02.February/AOP/Demo/.nuget/NuGet.targets
@@ -0,0 +1,151 @@
+
+
+
+ $(MSBuildProjectDirectory)\..\
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
+
+
+
+
+ $(SolutionDir).nuget
+
+
+
+ packages.$(MSBuildProjectName.Replace(' ', '_')).config
+
+
+
+
+
+ $(PackagesProjectConfig)
+
+
+
+
+ packages.config
+
+
+
+
+
+
+ $(NuGetToolsPath)\NuGet.exe
+ @(PackageSource)
+
+ "$(NuGetExePath)"
+ mono --runtime=v4.0.30319 $(NuGetExePath)
+
+ $(TargetDir.Trim('\\'))
+
+ -RequireConsent
+ -NonInteractive
+
+ "$(SolutionDir) "
+ "$(SolutionDir)"
+
+
+ $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
+ $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
+
+
+
+ RestorePackages;
+ $(BuildDependsOn);
+
+
+
+
+ $(BuildDependsOn);
+ BuildPackage;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/2014.02.February/AOP/Demo/Aop.sln b/2014.02.February/AOP/Demo/Aop.sln
new file mode 100644
index 0000000..efa1248
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop.sln
@@ -0,0 +1,27 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aop", "Aop\Aop.csproj", "{79BC310C-CD80-4B6D-B965-38A6207186F7}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{6AAFDAC4-6347-4EF9-AAAD-1A791A7BD33C}"
+ ProjectSection(SolutionItems) = preProject
+ .nuget\NuGet.Config = .nuget\NuGet.Config
+ .nuget\NuGet.exe = .nuget\NuGet.exe
+ .nuget\NuGet.targets = .nuget\NuGet.targets
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {79BC310C-CD80-4B6D-B965-38A6207186F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {79BC310C-CD80-4B6D-B965-38A6207186F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {79BC310C-CD80-4B6D-B965-38A6207186F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {79BC310C-CD80-4B6D-B965-38A6207186F7}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/2014.02.February/AOP/Demo/Aop/Advantage/Exceptions.cs b/2014.02.February/AOP/Demo/Aop/Advantage/Exceptions.cs
new file mode 100644
index 0000000..4b8a2dd
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Advantage/Exceptions.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Aop.Advantage
+{
+ public static class Exceptions
+ {
+ public static bool Handle(Exception ex)
+ {
+ // exception handling
+ if (ex.GetType() == typeof(ArithmeticException))
+ return false;
+ if (ex.GetType() == typeof(TimeoutException))
+ return true;
+
+ // etc...
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Advantage/FakeAdvantageWebCapsule.cs b/2014.02.February/AOP/Demo/Aop/Advantage/FakeAdvantageWebCapsule.cs
new file mode 100644
index 0000000..afa645a
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Advantage/FakeAdvantageWebCapsule.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aop.Advantage
+{
+ public class FakeAdvantageWebCapsule : IAdvantageWebCapsule
+ {
+ public void AddSubscription(int customerId, string pubCode)
+ {
+ throw new Exception();
+ Console.WriteLine("Adding '{0}' subscription for customer with id: '{1}'", pubCode, customerId);
+ }
+
+ public IList GetSubscriptions(int customerId)
+ {
+ return new List
+ {
+ "ABC",
+ "DEF",
+ "GHI"
+ };
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Advantage/IAdvantageWebCapsule.cs b/2014.02.February/AOP/Demo/Aop/Advantage/IAdvantageWebCapsule.cs
new file mode 100644
index 0000000..cdd9382
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Advantage/IAdvantageWebCapsule.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace Aop.Advantage
+{
+ public interface IAdvantageWebCapsule
+ {
+ void AddSubscription(int customerId, string pubCode);
+ IList GetSubscriptions(int customerId);
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Aop.csproj b/2014.02.February/AOP/Demo/Aop/Aop.csproj
new file mode 100644
index 0000000..0325016
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Aop.csproj
@@ -0,0 +1,128 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {79BC310C-CD80-4B6D-B965-38A6207186F7}
+ Exe
+ Properties
+ Aop
+ Aop
+ v4.5
+ 512
+ True
+ ..\
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Autofac.3.3.0\lib\net40\Autofac.dll
+
+
+ ..\packages\Autofac.Extras.DynamicProxy2.3.0.3\lib\net40\Autofac.Extras.DynamicProxy2.dll
+
+
+ ..\packages\Castle.Core.3.2.2\lib\net45\Castle.Core.dll
+
+
+ ..\packages\EnyimMemcached.2.12\lib\net35\Enyim.Caching.dll
+
+
+
+ ..\packages\Moq.4.2.1402.2112\lib\net40\Moq.dll
+
+
+ ..\packages\NLog.2.1.0\lib\net45\NLog.dll
+
+
+ True
+ ..\packages\PostSharp.3.1.31\lib\net20\PostSharp.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/App.config b/2014.02.February/AOP/Demo/Aop/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/Domain/ILoggable.cs b/2014.02.February/AOP/Demo/Aop/Business/Domain/ILoggable.cs
new file mode 100644
index 0000000..5de962f
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/Domain/ILoggable.cs
@@ -0,0 +1,7 @@
+namespace Aop.Business.Domain
+{
+ public interface ILoggable
+ {
+ string LogInformation();
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/Domain/Subscription.cs b/2014.02.February/AOP/Demo/Aop/Business/Domain/Subscription.cs
new file mode 100644
index 0000000..94215b2
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/Domain/Subscription.cs
@@ -0,0 +1,15 @@
+namespace Aop.Business.Domain
+{
+ public class Subscription : ILoggable
+ {
+ public int CustomerId { get; set; }
+ public string PubCode { get; set; }
+
+ public string LogInformation()
+ {
+ return "Customer Id: " + CustomerId
+ + "\n" +
+ "Pub Code: " + PubCode;
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/Services/AdvantageService.cs b/2014.02.February/AOP/Demo/Aop/Business/Services/AdvantageService.cs
new file mode 100644
index 0000000..ebad0be
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/Services/AdvantageService.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Transactions;
+using Aop.Advantage;
+using Aop.Business.Domain;
+
+namespace Aop.Business.Services
+{
+ public class AdvantageService : IAdvantageService
+ {
+ private readonly IAdvantageWebCapsule _advantageWebCapsule;
+
+ public AdvantageService(IAdvantageWebCapsule advantageWebCapsule)
+ {
+ _advantageWebCapsule = advantageWebCapsule;
+ }
+
+ #region V1 No Cross Cutting
+
+ public void AddSubscriptionV1(Subscription subscription)
+ {
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+ }
+
+ #endregion V1
+
+ #region V2 With Logging
+
+ public void AddSubscriptionV2(Subscription subscription)
+ {
+ // logging
+ Console.WriteLine("AddSubscription: {0}", DateTime.Now);
+ Console.WriteLine("Customer Id: {0}", subscription.CustomerId);
+ Console.WriteLine("Pub Code: {0}", subscription.PubCode);
+
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+
+ // logging
+ Console.WriteLine("AddSubscription complete: {0}", DateTime.Now);
+ }
+
+ #endregion V2 With Logging
+
+ #region V3 With Logging, Defensive Programming
+
+ public void AddSubscriptionV3(Subscription subscription)
+ {
+ // defensive programming
+ if (subscription == null) throw new ArgumentNullException("subscription");
+
+ // logging
+ Console.WriteLine("AddSubscription: {0}", DateTime.Now);
+ Console.WriteLine("Customer Id: {0}", subscription.CustomerId);
+ Console.WriteLine("Pub Code: {0}", subscription.PubCode);
+
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+
+ // logging
+ Console.WriteLine("AddSubscription complete: {0}", DateTime.Now);
+ }
+
+ #endregion V3 With Logging, Defensive Programming
+
+ #region V4 With Logging, Defensive Programming, Transactions
+
+ public void AddSubscriptionV4(Subscription subscription)
+ {
+ // defensive programming
+ if (subscription == null) throw new ArgumentNullException("subscription");
+
+ // logging
+ Console.WriteLine("AddSubscription: {0}", DateTime.Now);
+ Console.WriteLine("Customer Id: {0}", subscription.CustomerId);
+ Console.WriteLine("Pub Code: {0}", subscription.PubCode);
+
+ // start new transaction
+ using (var scope = new TransactionScope())
+ {
+ try
+ {
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+
+ // complete transaction
+ scope.Complete();
+ }
+ catch
+ {
+ throw;
+ }
+ }
+
+ // logging
+ Console.WriteLine("AddSubscription complete: {0}", DateTime.Now);
+ }
+
+ #endregion V4 With Logging, Defensive Programming, Transactions
+
+ #region V5 With Logging, Defensive Programming, Transactions, Retries And Exception Handling
+
+ public void AddSubscriptionV5(Subscription subscription)
+ {
+ // defensive programming
+ if (subscription == null) throw new ArgumentNullException("subscription");
+
+ // logging
+ Console.WriteLine("AddSubscription: {0}", DateTime.Now);
+ Console.WriteLine("Customer Id: {0}", subscription.CustomerId);
+ Console.WriteLine("Pub Code: {0}", subscription.PubCode);
+
+ // exception handling
+ try
+ {
+ // start new transaction
+ using (var scope = new TransactionScope())
+ {
+ // retry up to three times
+ var retries = 3;
+ var succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+
+ // complete transaction
+ scope.Complete();
+ succeeded = true;
+ }
+ catch
+ {
+ // don't re-throw until the
+ // retry limit is reached
+ if (retries >= 0)
+ retries--;
+ else
+ throw;
+ }
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // exception handling
+ if (!Exceptions.Handle(ex))
+ {
+ throw;
+ }
+ }
+
+ // logging
+ Console.WriteLine("AddSubscription complete: {0}", DateTime.Now);
+ }
+
+ #endregion V5 With Logging, Defensive Programming, Transactions, Retries And Exception Handling
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/Services/IAdvantageService.cs b/2014.02.February/AOP/Demo/Aop/Business/Services/IAdvantageService.cs
new file mode 100644
index 0000000..2038f11
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/Services/IAdvantageService.cs
@@ -0,0 +1,13 @@
+using Aop.Business.Domain;
+
+namespace Aop.Business.Services
+{
+ public interface IAdvantageService
+ {
+ void AddSubscriptionV1(Subscription subscription);
+ void AddSubscriptionV2(Subscription subscription);
+ void AddSubscriptionV3(Subscription subscription);
+ void AddSubscriptionV4(Subscription subscription);
+ void AddSubscriptionV5(Subscription subscription);
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/AdvantageServiceDynamicProxy.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/AdvantageServiceDynamicProxy.cs
new file mode 100644
index 0000000..bbfc027
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/AdvantageServiceDynamicProxy.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.Linq;
+using Aop.Advantage;
+using Aop.Business.Domain;
+using Aop.Business.ServicesDynamicProxy.Aspects;
+
+namespace Aop.Business.ServicesDynamicProxy
+{
+ public class AdvantageServiceDynamicProxy : IAdvantageServiceDynamicProxy
+ {
+ private readonly IAdvantageWebCapsule _advantageWebCapsule;
+
+ public AdvantageServiceDynamicProxy(IAdvantageWebCapsule advantageWebCapsule)
+ {
+ _advantageWebCapsule = advantageWebCapsule;
+ }
+
+ [DefensiveProgramming]
+ [Logging]
+ [TransactionManagement]
+ [ExceptionHandling]
+ public virtual void AddSubscription(Subscription subscription)
+ {
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+ }
+
+ public virtual IList GetSubscriptions(int customerId)
+ {
+ return
+ _advantageWebCapsule.GetSubscriptions(customerId)
+ .Select(s => new Subscription {CustomerId = customerId, PubCode = s})
+ .ToList();
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/DefensiveProgramming.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/DefensiveProgramming.cs
new file mode 100644
index 0000000..7c4a545
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/DefensiveProgramming.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Linq;
+using Castle.DynamicProxy;
+
+namespace Aop.Business.ServicesDynamicProxy.Aspects
+{
+ public class DefensiveProgramming : IInterceptor
+ {
+ public void Intercept(IInvocation invocation)
+ {
+ if (!invocation.MethodInvocationTarget.GetCustomAttributes(typeof(DefensiveProgrammingAttribute), false).Any())
+ {
+ invocation.Proceed();
+ return;
+ }
+
+ foreach (var argument in invocation.Arguments)
+ {
+ if (argument == null)
+ throw new ArgumentNullException();
+ if (argument is int && (int)argument <= 0)
+ throw new ArgumentException();
+ }
+
+ invocation.Proceed();
+ }
+ }
+
+ public class DefensiveProgrammingAttribute : Attribute { }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/ExceptionHandling.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/ExceptionHandling.cs
new file mode 100644
index 0000000..1156258
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/ExceptionHandling.cs
@@ -0,0 +1,26 @@
+using System;
+using Aop.Advantage;
+using Castle.DynamicProxy;
+
+namespace Aop.Business.ServicesDynamicProxy.Aspects
+{
+ public class ExceptionHandling : IInterceptor
+ {
+ public void Intercept(IInvocation invocation)
+ {
+ try
+ {
+ invocation.Proceed();
+ }
+ catch (Exception ex)
+ {
+ if (!Exceptions.Handle(ex))
+ {
+ throw;
+ }
+ }
+ }
+ }
+
+ public class ExceptionHandlingAttribute : Attribute { }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/Logging.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/Logging.cs
new file mode 100644
index 0000000..b0bb853
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/Logging.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Linq;
+using Aop.Business.Domain;
+using Castle.DynamicProxy;
+
+namespace Aop.Business.ServicesDynamicProxy.Aspects
+{
+ public class Logging : IInterceptor
+ {
+ public void Intercept(IInvocation invocation)
+ {
+ if (!invocation.MethodInvocationTarget.GetCustomAttributes(typeof(LoggingAttribute), false).Any())
+ {
+ invocation.Proceed();
+ return;
+ }
+
+ Console.WriteLine("{0}: {1}", invocation.Method.Name, DateTime.Now);
+
+ foreach (var argument in invocation.Arguments)
+ {
+ var loggable = argument as ILoggable;
+ if (loggable != null)
+ {
+ Console.WriteLine(loggable.LogInformation());
+ }
+ }
+
+ invocation.Proceed();
+
+ Console.WriteLine("{0} complete: {1}", invocation.Method.Name, DateTime.Now);
+ }
+ }
+
+ public class LoggingAttribute : Attribute { }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/TransactionManagement.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/TransactionManagement.cs
new file mode 100644
index 0000000..07d087c
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/Aspects/TransactionManagement.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Linq;
+using System.Transactions;
+using Castle.DynamicProxy;
+
+namespace Aop.Business.ServicesDynamicProxy.Aspects
+{
+ public class TransactionManagement :IInterceptor
+ {
+ public void Intercept(IInvocation invocation)
+ {
+ if (!invocation.MethodInvocationTarget.GetCustomAttributes(typeof(TransactionManagementAttribute), false).Any())
+ {
+ invocation.Proceed();
+ return;
+ }
+
+ Console.WriteLine("Starting transaction");
+ // start new transaction
+ using (var scope = new TransactionScope())
+ {
+ // retry up to three times
+ var retries = 3;
+ var succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ invocation.Proceed();
+
+ // complete transaction
+ scope.Complete();
+ succeeded = true;
+ }
+ catch
+ {
+ // don't re-throw until the
+ // retry limit is reached
+ if (retries >= 0)
+ retries--;
+ else
+ throw;
+ }
+ }
+ }
+ Console.WriteLine("Transaction complete");
+ }
+ }
+
+ public class TransactionManagementAttribute : Attribute { }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/IAdvantageServiceDynamicProxy.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/IAdvantageServiceDynamicProxy.cs
new file mode 100644
index 0000000..d3c6c14
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesDynamicProxy/IAdvantageServiceDynamicProxy.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using Aop.Business.Domain;
+
+namespace Aop.Business.ServicesDynamicProxy
+{
+ public interface IAdvantageServiceDynamicProxy
+ {
+ void AddSubscription(Subscription subscription);
+ IList GetSubscriptions(int customerId);
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/AdvantageServicePostSharp.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/AdvantageServicePostSharp.cs
new file mode 100644
index 0000000..e848bc3
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/AdvantageServicePostSharp.cs
@@ -0,0 +1,37 @@
+using System.Collections.Generic;
+using System.Linq;
+using Aop.Advantage;
+using Aop.Business.Domain;
+using Aop.Business.ServicesPostSharp.Aspects;
+using Aop.Caching;
+
+namespace Aop.Business.ServicesPostSharp
+{
+ public class AdvantageServicePostSharp : IAdvantageServicePostSharp
+ {
+ private readonly IAdvantageWebCapsule _advantageWebCapsule;
+
+ public AdvantageServicePostSharp(IAdvantageWebCapsule advantageWebCapsule)
+ {
+ _advantageWebCapsule = advantageWebCapsule;
+ }
+
+ [Logging(AspectPriority = 1)]
+ [DefensiveProgramming(AspectPriority = 2)]
+ [ExceptionHandling(AspectPriority = 3)]
+ [TransactionManagement(AspectPriority = 4)]
+ public void AddSubscription(Subscription subscription)
+ {
+ _advantageWebCapsule.AddSubscription(subscription.CustomerId, subscription.PubCode);
+ }
+
+ [Cache(CacheStore = CacheStore.Memory, Minutes = 60)]
+ public IList GetSubscriptions(int customerId)
+ {
+ return
+ _advantageWebCapsule.GetSubscriptions(customerId)
+ .Select(s => new Subscription {CustomerId = customerId, PubCode = s})
+ .ToList();
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/DefensiveProgramming.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/DefensiveProgramming.cs
new file mode 100644
index 0000000..e61e77d
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/DefensiveProgramming.cs
@@ -0,0 +1,22 @@
+using System;
+using PostSharp.Aspects;
+
+namespace Aop.Business.ServicesPostSharp.Aspects
+{
+ [Serializable]
+ public class DefensiveProgramming : OnMethodBoundaryAspect
+ {
+ public override void OnEntry(MethodExecutionArgs args)
+ {
+ var parameters = args.Method.GetParameters();
+ var arguments = args.Arguments;
+ for (int i = 0; i < arguments.Count; i++)
+ {
+ if (arguments[i] == null)
+ throw new ArgumentNullException(parameters[i].Name);
+ if (arguments[i] is int && (int)arguments[i] <= 0)
+ throw new ArgumentException("", parameters[i].Name);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/ExceptionHandling.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/ExceptionHandling.cs
new file mode 100644
index 0000000..a125e4a
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/ExceptionHandling.cs
@@ -0,0 +1,18 @@
+using System;
+using Aop.Advantage;
+using PostSharp.Aspects;
+
+namespace Aop.Business.ServicesPostSharp.Aspects
+{
+ [Serializable]
+ public class ExceptionHandling : OnExceptionAspect
+ {
+ public override void OnException(MethodExecutionArgs args)
+ {
+ if (Exceptions.Handle(args.Exception))
+ {
+ args.FlowBehavior = FlowBehavior.Continue;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/Logging.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/Logging.cs
new file mode 100644
index 0000000..d410b6e
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/Logging.cs
@@ -0,0 +1,29 @@
+using System;
+using Aop.Business.Domain;
+using PostSharp.Aspects;
+
+namespace Aop.Business.ServicesPostSharp.Aspects
+{
+ [Serializable]
+ public class Logging : OnMethodBoundaryAspect
+ {
+ public override void OnEntry(MethodExecutionArgs args)
+ {
+ Console.WriteLine("{0}: {1}", args.Method.Name, DateTime.Now);
+
+ foreach (var argument in args.Arguments)
+ {
+ var loggable = argument as ILoggable;
+ if (loggable != null)
+ {
+ Console.WriteLine(loggable.LogInformation());
+ }
+ }
+ }
+
+ public override void OnSuccess(MethodExecutionArgs args)
+ {
+ Console.WriteLine("{0} complete: {1}", args.Method.Name, DateTime.Now);
+ }
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/TransactionManagement.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/TransactionManagement.cs
new file mode 100644
index 0000000..a8e5f8b
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/Aspects/TransactionManagement.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Transactions;
+using PostSharp.Aspects;
+
+namespace Aop.Business.ServicesPostSharp.Aspects
+{
+ [Serializable]
+ public class TransactionManagement : MethodInterceptionAspect
+ {
+ public override void OnInvoke(MethodInterceptionArgs args)
+ {
+ Console.WriteLine("Starting transaction");
+ // start new transaction
+ using (var scope = new TransactionScope())
+ {
+ // retry up to three times
+ var retries = 3;
+ var succeeded = false;
+ while (!succeeded)
+ {
+ try
+ {
+ args.Proceed();
+
+ // complete transaction
+ scope.Complete();
+ succeeded = true;
+ }
+ catch
+ {
+ // don't re-throw until the
+ // retry limit is reached
+ if (retries >= 0)
+ retries--;
+ else
+ throw;
+ }
+ }
+ }
+ Console.WriteLine("Transaction complete");
+ }
+ }
+}
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/IAdvantageServicePostSharp.cs b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/IAdvantageServicePostSharp.cs
new file mode 100644
index 0000000..1d46595
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Business/ServicesPostSharp/IAdvantageServicePostSharp.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using Aop.Business.Domain;
+
+namespace Aop.Business.ServicesPostSharp
+{
+ public interface IAdvantageServicePostSharp
+ {
+ void AddSubscription(Subscription subscription);
+ IList GetSubscriptions(int customerId);
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheAttribute.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheAttribute.cs
new file mode 100644
index 0000000..565d432
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheAttribute.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Aop.PostSharpTestsWithIoC;
+using Autofac;
+using PostSharp.Aspects;
+
+namespace Aop.Caching
+{
+ [Serializable]
+ public class CacheAttribute : MethodInterceptionAspect
+ {
+ [NonSerialized]
+ private ICache _cache;
+
+ #region Properties
+
+ ///
+ /// Type of cache store to use
+ ///
+ public CacheStore CacheStore { get; set; }
+
+ ///
+ /// Days the element to be cached should live in the cache
+ ///
+ public int Days { get; set; }
+
+ ///
+ /// Hours the element to be cached should live in the cache
+ ///
+ public int Hours { get; set; }
+
+ ///
+ /// Minutes the element to be cached should live in the cache
+ ///
+ public int Minutes { get; set; }
+
+ ///
+ /// Seconds the items should live in the cache
+ ///
+ public int Seconds { get; set; }
+
+ ///
+ /// Lifespan of the response in the cache
+ ///
+ public TimeSpan LifeSpan
+ {
+ get
+ {
+ // Default 1 hour
+ if (Days == 0 && Hours == 0 && Minutes == 0 && Seconds == 0)
+ {
+ return new TimeSpan(1, 0, 0);
+ }
+ return new TimeSpan(Days, Hours, Minutes, Seconds);
+ }
+ }
+
+ public static Func GetInstanceStore { get; set; }
+
+ #endregion
+
+ public override void OnInvoke(MethodInterceptionArgs args)
+ {
+ if (!AspectSettings.On)
+ {
+ args.ReturnValue = args.Invoke(args.Arguments);
+ return;
+ }
+
+ var key = CacheKeyBuilder.BuildCacheKey(args.Arguments, _methodName);
+
+ var container = new CacheContainer();
+ _cache = container.GetCache(CacheStore);
+
+ var value = _cache.Get(key, ((MethodInfo) args.Method).ReturnType);
+ if (value == null)
+ {
+ lock (_syncRoot)
+ {
+ value = _cache.Get(key, ((MethodInfo) args.Method).ReturnType);
+ if (value == null)
+ {
+ value = args.Invoke(args.Arguments);
+ _cache.Set(key, value, LifeSpan);
+ }
+ }
+ }
+
+ args.ReturnValue = value;
+ }
+
+ #region Initialization Logic
+
+ [NonSerialized]
+ private object _syncRoot;
+ private string _methodName;
+
+ public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
+ {
+ _methodName = method.Name;
+ }
+
+ public override void RuntimeInitialize(MethodBase method)
+ {
+ _syncRoot = new object();
+ }
+
+ #endregion
+
+ #region Type Validation Logic
+
+ public override bool CompileTimeValidate(MethodBase method)
+ {
+ var methodInfo = method as MethodInfo;
+ if (methodInfo != null)
+ {
+ var returnType = methodInfo.ReturnType;
+ if (IsDisallowedCacheReturnType(returnType))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static readonly IList DisallowedTypes = new List
+ {
+ typeof (Stream),
+ typeof (IEnumerable),
+ typeof (IQueryable)
+ };
+
+ private static bool IsDisallowedCacheReturnType(Type returnType)
+ {
+ return DisallowedTypes.Any(t => t == returnType);
+ }
+
+ #endregion
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheContainer.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheContainer.cs
new file mode 100644
index 0000000..a5550ce
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheContainer.cs
@@ -0,0 +1,37 @@
+using System;
+using Aop.Caching.CacheStores;
+using Autofac;
+using Enyim.Caching;
+
+namespace Aop.Caching
+{
+ public class CacheContainer
+ {
+ public static Func GetScope { get; set; }
+
+ public ICache GetCache(CacheStore type)
+ {
+ ICache cache;
+ switch (type)
+ {
+ case CacheStore.Memcached:
+ {
+ cache = GetScope().Resolve(new NamedParameter("cache", GetScope().Resolve()));
+ break;
+ }
+ case CacheStore.Null:
+ {
+ cache = GetScope().Resolve();
+ break;
+ }
+ default:
+ {
+ cache = GetScope().Resolve();
+ break;
+ }
+ }
+
+ return cache;
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheKeyManager.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheKeyManager.cs
new file mode 100644
index 0000000..957465c
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheKeyManager.cs
@@ -0,0 +1,19 @@
+using System.Text;
+using PostSharp.Aspects;
+
+namespace Aop.Caching
+{
+ public static class CacheKeyBuilder
+ {
+ public static string BuildCacheKey(Arguments arguments, string methodName)
+ {
+ var sb = new StringBuilder();
+ sb.Append(methodName);
+ foreach (var argument in arguments.ToArray())
+ {
+ sb.Append(argument == null ? "_" : argument.ToString());
+ }
+ return sb.ToString();
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemcachedCache.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemcachedCache.cs
new file mode 100644
index 0000000..cafa568
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemcachedCache.cs
@@ -0,0 +1,55 @@
+using System;
+using Enyim.Caching;
+using Enyim.Caching.Memcached;
+
+namespace Aop.Caching.CacheStores
+{
+ public class MemcachedCache : ICache
+ {
+ #region Private Variables
+
+ private readonly IMemcachedClient _cache;
+
+ #endregion
+
+ #region Constructor
+
+ public MemcachedCache(IMemcachedClient cache)
+ {
+ if (cache == null) throw new ArgumentNullException("cache");
+
+ _cache = cache;
+ }
+
+ #endregion
+
+ #region Interface Members
+
+ public void Set(string key, object value, DateTime expiresAt)
+ {
+ _cache.Store(StoreMode.Set, key, value, expiresAt);
+ }
+
+ public void Set(string key, object value, TimeSpan validFor)
+ {
+ _cache.Store(StoreMode.Set, key, value, validFor);
+ }
+
+ public object Get(string key, Type type)
+ {
+ return _cache.Get(key);
+ }
+
+ public void Remove(string key)
+ {
+ _cache.Remove(key);
+ }
+
+ public void Clear()
+ {
+ _cache.FlushAll();
+ }
+
+ #endregion
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemoryCache.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemoryCache.cs
new file mode 100644
index 0000000..6d46507
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/MemoryCache.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Runtime.Caching;
+
+namespace Aop.Caching.CacheStores
+{
+ public class MemoryCache : ICache
+ {
+ #region Private Variables
+
+ private readonly System.Runtime.Caching.MemoryCache _cache;
+
+ #endregion
+
+ #region Constructor
+
+ public MemoryCache()
+ {
+ _cache = System.Runtime.Caching.MemoryCache.Default;
+ }
+
+ #endregion
+
+ #region Interface Members
+
+ public object Get(string key, Type type)
+ {
+ return _cache[key];
+ }
+
+ public void Set(string key, object data, TimeSpan lifespan)
+ {
+ if (data == null)
+ {
+ return;
+ }
+
+ var expiresAt = DateTime.UtcNow.Add(lifespan);
+ Set(key, data, expiresAt);
+ }
+
+ public void Set(string key, object data, DateTime expiresAt)
+ {
+ if (data == null)
+ {
+ return;
+ }
+
+ var policy = new CacheItemPolicy { AbsoluteExpiration = expiresAt };
+ Set(key, data, policy);
+ }
+
+ public void Remove(string key)
+ {
+ _cache.Remove(key);
+ }
+
+ public void Clear()
+ {
+ foreach (var item in _cache)
+ {
+ Remove(item.Key);
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void Set(string key, object value, CacheItemPolicy policy)
+ {
+ _cache.Set(key, value, policy);
+ }
+
+ #endregion
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/NullCache.cs b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/NullCache.cs
new file mode 100644
index 0000000..1b670c8
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CacheStores/NullCache.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Aop.Caching.CacheStores
+{
+ ///
+ /// implementation which does nothing
+ ///
+ ///
+ /// Used when real caches are unavailable or disabled
+ ///
+ public class NullCache : ICache
+ {
+ public void InitialiseInternal()
+ {
+ }
+
+ public void Set(string key, object value, DateTime expiresAt)
+ {
+ }
+
+ public void Set(string key, object value, TimeSpan validFor)
+ {
+ }
+
+ public object Get(string key, Type type)
+ {
+ return null;
+ }
+
+ public void Remove(string key)
+ {
+ }
+
+ public bool IsSet(string key)
+ {
+ return false;
+ }
+
+ public void Clear()
+ {
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/CachedObject.cs b/2014.02.February/AOP/Demo/Aop/Caching/CachedObject.cs
new file mode 100644
index 0000000..3074e8f
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/CachedObject.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Aop.Caching
+{
+ public class CachedObject
+ {
+ public string Key { get; set; }
+ public object Value { get; set; }
+ public DateTime CachedDate { get; set; }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/ICache.cs b/2014.02.February/AOP/Demo/Aop/Caching/ICache.cs
new file mode 100644
index 0000000..13f6f33
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/ICache.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace Aop.Caching
+{
+ public interface ICache
+ {
+ ///
+ /// Gets the value associated with the specified key.
+ ///
+ /// The key of the value to get.
+ /// Type of returned value.
+ /// The value associated with the specified key.
+ object Get(string key, Type type);
+
+ ///
+ /// Adds the specified key and object to the cache.
+ ///
+ /// key
+ /// Data
+ /// Cache time
+ void Set(string key, object data, TimeSpan lifespan);
+
+ ///
+ /// Adds the specified key and object to the cache.
+ ///
+ /// key
+ /// Data
+ /// Cache expiry date and time
+ void Set(string key, object data, DateTime expiresAt);
+
+ ///
+ /// Removes the value with the specified key from the cache
+ ///
+ /// /key
+ void Remove(string key);
+
+ ///
+ /// Clear all cache data
+ ///
+ void Clear();
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Caching/_Enumerations.cs b/2014.02.February/AOP/Demo/Aop/Caching/_Enumerations.cs
new file mode 100644
index 0000000..b65bd14
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Caching/_Enumerations.cs
@@ -0,0 +1,9 @@
+namespace Aop.Caching
+{
+ public enum CacheStore
+ {
+ Memcached = 0, // Default Cache
+ Memory = 1,
+ Null = 2
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/DynamicProxyTests/DynamicProxyLoggingAspectTests.cs b/2014.02.February/AOP/Demo/Aop/DynamicProxyTests/DynamicProxyLoggingAspectTests.cs
new file mode 100644
index 0000000..133d75b
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/DynamicProxyTests/DynamicProxyLoggingAspectTests.cs
@@ -0,0 +1,71 @@
+using System;
+using Castle.DynamicProxy;
+using Moq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace Aop.DynamicProxyTests
+{
+ #region Logging Service
+
+ public interface ILoggingService
+ {
+ void Write(string message);
+ }
+
+ public class LoggingService : ILoggingService
+ {
+ public void Write(string message)
+ {
+ Console.WriteLine("Logging: " + message);
+ }
+ }
+
+ #endregion Logging Service
+
+ #region Logging Aspect
+
+ public class LoggingAspect : IInterceptor
+ {
+ readonly ILoggingService _loggingService;
+
+ public LoggingAspect(ILoggingService loggingService)
+ {
+ _loggingService = loggingService;
+ }
+
+ public void Intercept(IInvocation invocation)
+ {
+ _loggingService.Write("Log start");
+ invocation.Proceed();
+ var returnValue = (int)invocation.ReturnValue;
+ _loggingService.Write(string.Format("Log {0} end", returnValue));
+ }
+ }
+
+ #endregion Logging Aspect
+
+ #region Unit Test
+
+ [TestClass]
+ public class LoggingAspectTests
+ {
+ [TestMethod]
+ public void LoggingAspectTest()
+ {
+ // Arrange
+ var mockLoggingService = new Mock();
+ var loggingAspect = new LoggingAspect(mockLoggingService.Object);
+ var mockInvocation = new Mock();
+ mockInvocation.Setup(x => x.ReturnValue).Returns(3);
+
+ // Act
+ loggingAspect.Intercept(mockInvocation.Object);
+
+ // Assert
+ mockLoggingService.Verify(x => x.Write("Log start"));
+ mockLoggingService.Verify(x => x.Write(string.Format("Log 3 end")));
+ }
+ }
+
+ #endregion Unit Test
+}
diff --git a/2014.02.February/AOP/Demo/Aop/PostSharpTestsNoIoC/PostSharpLoggingAspectTestsNoIoC.cs b/2014.02.February/AOP/Demo/Aop/PostSharpTestsNoIoC/PostSharpLoggingAspectTestsNoIoC.cs
new file mode 100644
index 0000000..86c9034
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/PostSharpTestsNoIoC/PostSharpLoggingAspectTestsNoIoC.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection.Emit;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using PostSharp.Aspects;
+
+namespace Aop.PostSharpTestsNoIoC
+{
+ public static class LoggingService
+ {
+ public static List _messages = new List();
+
+ public static List Messages
+ {
+ get { return _messages; }
+ }
+
+ public static void Write(string message)
+ {
+ _messages.Add(message);
+ }
+ }
+
+ [Serializable]
+ public class LoggingAspect : OnMethodBoundaryAspect
+ {
+ public override void OnEntry(MethodExecutionArgs args)
+ {
+ LoggingService.Write("Before: " + args.Method.Name);
+ }
+ public override void OnSuccess(MethodExecutionArgs args)
+ {
+ LoggingService.Write("After: " + args.Method.Name);
+ }
+ }
+
+ [TestClass]
+ public class LoggingAspectTests
+ {
+ [TestMethod]
+ public void LoggingAspectTest()
+ {
+ // Arrange
+ var args = new MethodExecutionArgs(null, Arguments.Empty)
+ {
+ Method = new DynamicMethod("AddSubscription", null, null)
+ };
+
+ var aspect = new LoggingAspect();
+
+ // Act
+ aspect.OnEntry(args);
+ aspect.OnSuccess(args);
+
+ // Assert
+ Assert.IsTrue(LoggingService.Messages.Contains("Before: " + args.Method.Name));
+ Assert.IsTrue(LoggingService.Messages.Contains("After: " + args.Method.Name));
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/PostSharpTestsWithIoC/PostSharpLoggingAspectTestsWithIoC.cs b/2014.02.February/AOP/Demo/Aop/PostSharpTestsWithIoC/PostSharpLoggingAspectTestsWithIoC.cs
new file mode 100644
index 0000000..b003718
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/PostSharpTestsWithIoC/PostSharpLoggingAspectTestsWithIoC.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Autofac;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using PostSharp.Aspects;
+
+namespace Aop.PostSharpTestsWithIoC
+{
+ public class StringHelpers
+ {
+ [LoggingAspect]
+ public string Reverse(string str)
+ {
+ return new string(str.Reverse().ToArray());
+ }
+ }
+
+ [Serializable]
+ public class LoggingAspect : OnMethodBoundaryAspect
+ {
+ ILoggingService _loggingService;
+
+ public static Func GetScope { get; set; }
+
+ public override void RuntimeInitialize(MethodBase method)
+ {
+ if (!AspectSettings.On) return;
+ _loggingService = GetScope().Resolve();
+ }
+
+ public override void OnEntry(MethodExecutionArgs args)
+ {
+ if (!AspectSettings.On) return;
+ _loggingService.Log("before");
+ }
+
+ public override void OnSuccess(MethodExecutionArgs args)
+ {
+ if (!AspectSettings.On) return;
+ _loggingService.Log("after");
+ }
+ }
+
+ public interface ILoggingService
+ {
+ void Log(string logMessage);
+ }
+
+ public static class AspectSettings
+ {
+ public static bool On = true;
+ }
+
+ [TestClass]
+ public class MyNormalCodeTest
+ {
+ public void SetupIoC(ILoggingService loggingService)
+ {
+ var builder = new ContainerBuilder();
+ builder.RegisterInstance(loggingService).As();
+ var container = builder.Build();
+ LoggingAspect.GetScope = container.Resolve;
+ }
+
+ [TestMethod]
+ public void ReverseTest()
+ {
+ // Arrange
+ var loggingService = new Mock();
+ SetupIoC(loggingService.Object);
+ var stringHelpers = new StringHelpers();
+
+ // Act
+ var result = stringHelpers.Reverse("hello");
+
+ // Assert
+ Assert.AreEqual("olleh", result);
+ loggingService.Verify(x => x.Log("before"));
+ loggingService.Verify(x => x.Log("after"));
+ }
+
+ [TestMethod]
+ public void ReverseTestAlternative()
+ {
+ // Arrange
+ AspectSettings.On = false;
+ var myCode = new StringHelpers();
+
+ // Act
+ var result = myCode.Reverse("hello");
+
+ // Assert
+ Assert.AreEqual("olleh", result);
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Program.cs b/2014.02.February/AOP/Demo/Aop/Program.cs
new file mode 100644
index 0000000..7e537ff
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Program.cs
@@ -0,0 +1,115 @@
+using Aop.Advantage;
+using Aop.Business.Domain;
+using Aop.Business.Services;
+using Aop.Business.ServicesDynamicProxy;
+using Aop.Business.ServicesDynamicProxy.Aspects;
+using Aop.Business.ServicesPostSharp;
+using Aop.Caching.CacheStores;
+using Autofac;
+using Autofac.Extras.DynamicProxy2;
+using Enyim.Caching;
+using Aop.Caching;
+
+namespace Aop
+{
+ class Program
+ {
+ private static IContainer Container { get; set; }
+
+ static void Main()
+ {
+ SetupIoC();
+
+ var subscription = new Subscription
+ {
+ CustomerId = 1,
+ PubCode = "ABC"
+ };
+
+ using (var scope = Container.BeginLifetimeScope())
+ {
+ //#region Add Subscription No AOP
+
+ //var advantageService = scope.Resolve();
+
+ //advantageService.AddSubscriptionV5(subscription);
+
+ //#endregion Add Subscription No AOP
+
+ #region Add Subscription PostSharp AOP
+
+ var advantageServicePostSharp = scope.Resolve();
+
+ //advantageServicePostSharp.AddSubscription(subscription);
+
+ #endregion Add Subscription PostSharp AOP
+
+ //#region Add Subscription DynamicProxy AOP
+
+ //var advantageServiceDynamicProxy = scope.Resolve();
+
+ //advantageServiceDynamicProxy.AddSubscription(subscription);
+
+ //#endregion
+
+ #region Get Subscriptions PostSharp AOP
+
+ CacheContainer.GetScope = () => scope;
+
+ advantageServicePostSharp.GetSubscriptions(1);
+
+ advantageServicePostSharp.GetSubscriptions(1);
+
+ #endregion Get Subscriptions PostSharp AOP
+
+ //#region Get Subscriptions DynamicProxy AOP
+
+ //advantageServiceDynamicProxy.GetSubscriptions(1);
+
+ //#endregion
+ }
+ }
+
+ private static void SetupIoC()
+ {
+ var builder = new ContainerBuilder();
+
+ builder.RegisterType().As();
+ builder.RegisterType().As();
+
+ #region PostSharp
+
+ builder.RegisterType().As();
+
+ #endregion PostSharp
+
+ #region Dynamic Proxy
+
+ builder.Register(c => new DefensiveProgramming());
+ builder.Register(c => new Logging());
+ builder.Register(c => new TransactionManagement());
+ builder.Register(c => new ExceptionHandling());
+
+ builder.RegisterType()
+ .As()
+ .EnableInterfaceInterceptors()
+ .InterceptedBy(typeof (Logging))
+ .InterceptedBy(typeof (DefensiveProgramming))
+ .InterceptedBy(typeof (ExceptionHandling))
+ .InterceptedBy(typeof (TransactionManagement));
+
+ #endregion Dynamic Proxy
+
+ #region Caching
+
+ builder.RegisterType().As().SingleInstance();
+ builder.RegisterType().SingleInstance();
+ builder.RegisterType().SingleInstance();
+ builder.RegisterType().SingleInstance();
+
+ #endregion Caching
+
+ Container = builder.Build();
+ }
+ }
+}
diff --git a/2014.02.February/AOP/Demo/Aop/Properties/AssemblyInfo.cs b/2014.02.February/AOP/Demo/Aop/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7db95eb
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("PostSharpAop")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("PostSharpAop")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f397875b-29a8-43a5-bbbb-eb8b7e824ee8")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/2014.02.February/AOP/Demo/Aop/packages.config b/2014.02.February/AOP/Demo/Aop/packages.config
new file mode 100644
index 0000000..61a0a62
--- /dev/null
+++ b/2014.02.February/AOP/Demo/Aop/packages.config
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2014.02.February/AOP/Demo/packages/repositories.config b/2014.02.February/AOP/Demo/packages/repositories.config
new file mode 100644
index 0000000..9e9dcff
--- /dev/null
+++ b/2014.02.February/AOP/Demo/packages/repositories.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/2014.02.February/AOP/Presentation/AOP.pptx b/2014.02.February/AOP/Presentation/AOP.pptx
new file mode 100644
index 0000000..a00e87c
Binary files /dev/null and b/2014.02.February/AOP/Presentation/AOP.pptx differ