通过IoC影响具有属性的AOP; 代码味或优雅?

Mar*_*ell 8 .net c# structuremap aop inversion-of-control

我目前正在使用StructureMap,通常使用基于约定的(Scan())自动配置,我希望将基于装饰器的缓存添加到管道中.

如果我手动配置它很好,但是当你获得大量依赖时Scan()它就是这么方便 ...我正在注意接口上的缓存建议,例如:

public interface IFoo {
    [CacheDuration(20)] // cache for 20 minutes
    string[] DoSomethingReusable();

    SomeType DoSomethingNonReusable(int key); // not cached
}
Run Code Online (Sandbox Code Playgroud)

通过在StructureMap扫描中添加自定义"约定" (非常简单),它可以发现一个或多个方法被装饰用于缓存,并自动将生成的缓存装饰器注入到该类型的管道中(生成缓存)来自接口/方法名称和参数值的键).

从好的方面来说,它增加了缓存非常无痛 - 只需稍微装饰一下界面; 但是代码味道是什么?和/或我是否重复了已经解决的问题?

Krz*_*mic 7

如果您了解两个主要因素,那么属性就可以了:

  • 本质上是分散的结构,而不是在一个地方,你的元数据洒在它接触的每个组件上

  • 刚性编译器常量结构.如果您突然确定缓存持续时间应为10而不是20,则必须重新编译所有代码.你可以将属性路由到配置之类的东西,但是这会解决属性问题,此时你应该重新考虑使用它们是否是最好的想法.

只要你意识到这些问题,并且对它们没问题,那就继续吧.

  • 它可能不是,重要的部分是 - 它们是编译时间常数,具有所有限制. (3认同)
  • +1这个答案提出了一些我没有想到的观点.更多弹药对抗属性:) (2认同)

Mar*_*ann 5

据我所知,您主要考虑添加属性以使容器注册更容易.您仍在使用Decorator设计模式实现缓存,这是IMO实现缓存的正确方法.

我们在Safewhere中也这样做,但我们使用基于约定的注册.我们也使用Castle Windsor,所以我不知道这是否可以使用StructureMap,但我们只需在命名之后扫描相应的程序集,Caching*Repository并将它们注册为真实存储库的装饰器.我们还有一个基于约定的单元测试,用于验证是否存在所有必需的高速缓存存储库.

添加自定义属性是否是代码异味取决于代码所需的可重用程度.我的经验法则是,我希望能够穷人的DI连接一切.我仍然使用DI容器,但是这个规则为我提供了一个健全性检查.

一般来说,我不喜欢将我的代码耦合到特定的容器,但我无法弄清楚你是否在这里这样做.这取决于您是否需要引用StructureMap来定义自定义属性.如果你必须参考结构图,我会认为它是一种气味.