- Analyze the implementation performance
- Authorize using
- Log access
With use cases implemented by business class methods, it is a interesting way intercept the calls of these methods and apply these strategies.
How to intercept methods:
The instance of business should be created through a DynamicProxy.
The interceptable methods must be virtual, so that the proxy can override it.
Installs Castle.Core the project, obtained via NuGet, which provides a great API to intercept methods.
This recipe is for properties as well.
Below there is a simple application which implements the idea.
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace InterceptingApp { using Castle.DynamicProxy; using System.Reflection; class Program { static void Main(string[] args) { var user = new User { Login = "It's me" }; var allowedMethods = new List<MemberInfo> { typeof(MyBusiness).GetMethod("GetProducts") }; var performanceInterceptor = new PerformanceInterceptor(); var authorizeInterceptor = new AuthorizeInterceptor(allowedMethods); var logInterceptor = new LogInterceptor(user); var generator = new ProxyGenerator(new PersistentProxyBuilder()); var business = generator.CreateClassProxy<MyBusiness>(performanceInterceptor, authorizeInterceptor, logInterceptor); try { // This call was allowed, so it should works just fine Console.WriteLine("Products:"); foreach (var product in business.GetProducts()) { Console.WriteLine("Product name: {0} price: {1:c}", product.Name, product.Price); } // This call was not allowed, so it should throw an exception Console.WriteLine("BestSellers:"); foreach (var product in business.GetBestSellers()) { Console.WriteLine("Product name: {0} price: {1:c}", product.Name, product.Price); } } catch (Exception ex) { Console.WriteLine(ex); } } } public class MyBusiness { public virtual IEnumerable<Product> GetProducts() { System.Threading.Thread.Sleep(100); return new List<Product> { new Product { Name = "Beer", Price = 1.80M }, new Product { Name = "Soda", Price = 1.50M }, new Product { Name = "Juice", Price = 2.15M } }; } public virtual IEnumerable<Product> GetBestSellers() { System.Threading.Thread.Sleep(100); return new List<Product> { new Product { Name = "Juice", Price = 2.15M } }; } } public class User { public string Login { get; set; } } public class Product { public string Name { get; set; } public decimal Price { get; set; } } class PerformanceInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { var start = DateTime.Now; try { invocation.Proceed(); } catch { throw; } finally { var end = DateTime.Now; Console.WriteLine("[Performance]: Method {0}.{1} takes {2}", invocation.Method.DeclaringType.Name, invocation.Method.Name, end - start); } } } class AuthorizeInterceptor : IInterceptor { IEnumerable<MemberInfo> _allowedMethods; public AuthorizeInterceptor(IEnumerable<MemberInfo> allowedMethods) { _allowedMethods = allowedMethods; } public void Intercept(IInvocation invocation) { if (_allowedMethods.Contains(invocation.Method)) { Console.WriteLine("[Authorize]: Granted! You are allowed to access this method"); invocation.Proceed(); } else { throw new Exception("[Authorize]: Denied! You are not allowed to access this method."); } } } class LogInterceptor : IInterceptor { User _user; public LogInterceptor(User user) { _user = user; } public void Intercept(IInvocation invocation) { Console.WriteLine("[Log]: Method {0}.{1} was called by '{2}' at {3}", invocation.Method.DeclaringType.Name, invocation.Method.Name, _user.Login, DateTime.Now); invocation.Proceed(); } } }
Nenhum comentário:
Postar um comentário
Feel free to comment on the immoderately.