C# 城堡项目是如何进行的';当问题不是横切时,DynamicProxy使代码更易于维护?

C# 城堡项目是如何进行的';当问题不是横切时,DynamicProxy使代码更易于维护?,c#,castle-windsor,aop,dynamic-proxy,C#,Castle Windsor,Aop,Dynamic Proxy,不确定是否正确命名(即嵌套接口实现)。但是,我不理解使用动态代理优于嵌套接口实现的好处动态代理如何比下面的示例代码更好?以下示例代码在某种程度上是否比DynamicProxy中使用的拦截器模式更具限制性 更新 我了解什么是交叉关注点,以及DynamicProxy如何使维护这些情况变得更容易。日志异常之类的事情与实际执行的代码的行为无关。这个示例在本质上不像日志记录示例那样通用。吃是你吃饼干的方式。它不应该关心你什么时候应该吃它。一个不那么人为的例子是查询服务,它决定是调用使用本地存储的实现,还是

不确定是否正确命名(即嵌套接口实现)。但是,我不理解使用动态代理优于嵌套接口实现的好处动态代理如何比下面的示例代码更好?以下示例代码在某种程度上是否比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();
    }
}
}
使用系统;
使用温莎城堡;
使用Castle.MicroKernel.Registration;
命名空间控制台应用程序19{
公共枚举闻起来像{Poo,YummyCookie}
公共类Cookie{
公共气味类似气味类似{get;set;}
公共整数大小{get;set;}
}
公共接口IHaveCookies{
饼干吃(饼干c);
无效操作(cookiec);
}
//如果使用DynamicProxy实现,这将是拦截器
//例如,拦截器或装饰器模式
公共类服务:IHaveCookies{
我喜欢饼干;;
公共服务(IHaveCookies实施){
_=实施;
}
公共饼干吃(饼干c){
控制台。WriteLine(“臭饼干”);
//拦截呼叫吃东西,如果闻起来像便便就不要呼叫
返回c.soutslike==soutslike.Poo
C
:吃(c);
}
//表明我没有拦截这个电话
作废其他操作(Cookie c){
//无所事事
_.其他操作(c);
}
}
//这是实际的服务实现
公共类服务:IHaveCookies{
公共饼干吃(饼干c){
控制台。WriteLine(“吃饼干”);
var Whatsleet=nom(c);
归还剩余的东西;
}
Cookie名称(Cookie c){
c、 大小--;
返回c;
}
公共操作(Cookie c){
//做点别的
}
}
//使用windsor连接接口的shor程序
班级计划{
静态void Main(字符串[]参数){
var container=新的WindsorContainer();
集装箱。登记(
//接口实现,当
//container.Resolve被调用
Component.For().ImplementedBy().Named(“嗅觉”),
//连接实际的服务实现
Component.For().ImplementedBy().Named(“Eat”),
//这将拦截器注入到实际的服务实现中
Component.For().ServiceOverrides(ServiceOverride.ForKey(“实现”).Eq(“Eat”));
//示例用法
var yummy=newcookie{Size=2,studeslike=studeslike.YummyCookie};
var poo=newcookie{Size=2,stoonslike=stoonslike.poo};
var svc=container.Resolve();
Console.WriteLine(“吃美味”);
//EatService.Eat按预期被调用
吃(好吃);
控制台。WriteLine(“吃屎”);
//EatService.Eat未按预期调用
吃东西(便便);
控制台。写入线(“完成”);
Console.ReadLine();
}
}
}

动态代理可用于实现适用于整个系统或子系统的行为方面。如果您有15个服务,每个服务有20个方法,需要对它们应用相同的行为(安全检查、远程处理、日志记录……或嗅探,如您的示例中所示),那么可以使用动态代理一次性实现该行为。使用委托,您可以获得相同的结果,但需要更多的样板代码(使用我的数字,需要300倍)

重复的样板代码增加了进行更改所涉及的维护工作量,并使某些类型的结构更改变得更加昂贵(并且不太可能发生)


动态代理也有一些缺点-代码比(单一使用)委托更复杂。性能特性也可能存在差异,这意味着在性能开销很大的少数情况下,需要在性能和可维护性之间进行权衡

动态代理可用于实现适用于整个系统或子系统的行为方面。如果您有15个服务,每个服务有20个方法,需要对它们应用相同的行为(安全检查、远程处理、日志记录……或嗅探,如您的示例中所示),那么可以使用动态代理一次性实现该行为。使用委托,您可以获得相同的结果,但需要更多的样板代码(使用我的数字,需要300倍)

重复的样板代码增加了进行更改所涉及的维护工作量,并使某些类型的结构更改变得更加昂贵(并且不太可能发生)


动态代理也有一些缺点-代码比(单一使用)委托更复杂。性能特性也可能存在差异,这意味着在性能开销很大的少数情况下,需要在性能和可维护性之间进行权衡

我认为使用动态代理的想法是,它确实有利于跨领域关注点。事情
public class LoggingInterceptor : IInterceptor  
{
    public void Intercept(IInvocation invocation)
    {
        // log method call and parameters
        try                                           
        {                                             
            invocation.Proceed();   
        }                                             
        catch (Exception e)              
        {                                             
            // log exception
            throw; // or sth else                
        }
    }                                             
}
public class ServiceSelectingWhatCallToMake : IHaveCookies
{
  public ServiceSelectingWhatCallToMake(IHaveCookies localCalls, IHaveCookies networkCalls)
  {
    // save in member variables
  }
  public SomeMethod()
  {
    if (somethingDescribingIShouldMakeLocalCall)
       this.localCalls.SomeMethod();
    else
       this.networkCalls.SomeMethod();
  }
}
public class ServiceThatDoesntKnowWhatCallItMakes
{
  public ServiceSelectingWhatCallToMake(IHaveCookiesFactory factory)
  {
    // save in member variables
  }
  public SomeMethod()
  {
    var localOrNetwork = this.factory.Create(somethingDescribingWhatCallToMake)
    localCalOrNetwork.SomeMethod();
  }
}