不确定我是否正确命名它(即嵌套接口实现)。但是我不明白使用动态代理而不是嵌套接口实现的好处。动态代理比执行下面的示例代码更好吗?以下示例代码在某种程度上是否比 DynamicProxy 中使用的拦截器模式更具限制性?
更新 我了解什么是横切关注点以及 DynamicProxy 如何使维护这些情况更容易。诸如记录异常之类的事情与正在执行的实际代码正在做什么无关。这个例子在本质上并不像日志例子那样通用。吃饼干就是你吃饼干的方式。它不应该关心你什么时候应该吃它。一个不太人为的例子是一个查询服务,它确定它是否应该调用一个使用本地存储的实现,或者调用一个为特定查询进行网络调用的实现。基于它是否在总线上收到一条消息,用于本地存储中包含的项目更新。在这种情况下使用 DynamicProxy 拦截器如何有利于代码维护?
using System;
using Castle.Windsor;
using Castle.MicroKernel.Registration;
namespace ConsoleApplication19 {
public enum SmellsLike { Poo, YummyCookie }
public class Cookie {
public SmellsLike SmellsLike { get; set; }
public int Size { get; set; }
}
public interface IHaveCookies {
Cookie Eat(Cookie c);
void OtherOperation(Cookie c);
}
// this would be the interceptor if implemented using DynamicProxy
// e.g. interceptor or decorator pattern
public class SmellService : IHaveCookies {
IHaveCookies _;
public SmellService(IHaveCookies implementation) {
_ = implementation;
}
public Cookie Eat(Cookie c) {
Console.WriteLine("Smelling cookie");
// intercept call to Eat and don't call it if it smells like poo
return c.SmellsLike == SmellsLike.Poo
? c
: _.Eat(c);
}
// shows that i'm not intercepting this call
void OtherOperation(Cookie c) {
// do nothing
_.OtherOperation(c);
}
}
//This is the actual service implementation
public class EatService : IHaveCookies {
public Cookie Eat(Cookie c) {
Console.WriteLine("Eating cookie");
var whatsLeft = NomNomNom(c);
return whatsLeft;
}
Cookie NomNomNom(Cookie c) {
c.Size--;
return c;
}
public void OtherOperation(Cookie c) {
// do something else
}
}
// shor program that uses windsor to wire up the interfaces
class Program {
static void Main(string[] args) {
var container = new WindsorContainer();
container.Register(
// interface implementation that is actually given when
// container.Resolve is called
Component.For<IHaveCookies>().ImplementedBy<SmellService>().Named("Smell"),
// wiring up actual service implementation
Component.For<IHaveCookies>().ImplementedBy<EatService>().Named("Eat"),
// this injects the interceptor into the actual service implementation
Component.For<SmellService>().ServiceOverrides(ServiceOverride.ForKey("implementation").Eq("Eat")));
// example usage
var yummy = new Cookie { Size = 2, SmellsLike = SmellsLike.YummyCookie };
var poo = new Cookie { Size = 2, SmellsLike = SmellsLike.Poo };
var svc = container.Resolve<IHaveCookies>();
Console.WriteLine("eating yummy");
// EatService.Eat gets called, as expected
svc.Eat(yummy);
Console.WriteLine("eating poo");
// EatService.Eat does not get called, as expected
svc.Eat(poo);
Console.WriteLine("DONE");
Console.ReadLine();
}
}
}