【问题标题】:What is the difference between ComponentModel.DataAnnotation and decorator pattern.?ComponentModel.DataAnnotation 和装饰器模式有什么区别?
【发布时间】:2015-02-25 10:10:05
【问题描述】:


我正在我的项目中实现存储库装饰器模式:

[Auditable]
public class Product
{
    public int Id {get; set;}
    public string Name {get; set;}
}

我从以下链接中得到了这个想法。

https://efpatterns.codeplex.com/discussions/282699

但未能成功实施。然后我开始学习装饰器模式和 DataAnnotation,因为 Product 实体上的 Auditable 属性的方式在 DataAnnotation 和装饰器模式中有些相似。所以我的问题是它们是一样的吗?如果它们相同,那么我将如何在我的项目中实现可审核存储库模式(更多链接)。

【问题讨论】:

  • 我的理解是“装饰器”(通常)添加功能,而属性(通常)旨在添加元数据,然后由任意功能解释/使用。明显有例外(比如MVC filterAttribute)
  • 存储库并不是抽象 EF 的绝佳方式。建议看Unit of Work design pattern
  • 但是 DataAnnotation 中的静态类 TypeDescriptor 提供了与装饰器模式类似的功能。

标签: asp.net-mvc entity-framework repository-pattern data-annotations system.componentmodel


【解决方案1】:

这不是四人组最初描述的decorator pattern

装饰器模式是一种向现有类添加功能的继承技术。该模式通过创建一组子类来工作,每个子类在基类之上提供特定类型的功能。

然后通过将现有实例作为内部对象传递给子类实例来组合组合:

public class SecurityToken
public class ExpiringToken : SecurityToken;
public class RpcSecurityToken : SecurityToken;

因此,如果您想要一个远程令牌并在一段时间后过期:

var token = new RpcSecurityToken(new ExpiringToken(new SecurityToken("sds")));

你所做的只是用一个属性来装饰一个类,这不是一回事。

【讨论】:

  • 因此,如果它不是四人组描述的装饰器模式,那么使用实体框架实现存储库装饰器模式的正确方法是什么。
【解决方案2】:

装饰器模式是一种将给定接口的基本实现作为扩展其行为而不修改原始实现的机制。

类似于从基类继承,但是它具有更大的灵活性。例如,装饰器类可以应用于实现相同接口的任何其他类,没有限制只扩展单个基类。它们也可以链接在一起等等......

例如

public interface IThing
{
     void AMethod()
}

public abstract class ThingDecorator : IThing
{
    private IThing inner;
    public ThingDecorator(IThing inner)
    {
        this.inner = inner;
    }

    public virtual void AMethod()
    {
         this.inner.AMethod();
    }
}

从 ThingDecorator 继承并将您自己的扩展应用到虚拟 AMethod 将添加行为(装饰)传入的内部实例。由于内部实例与接口耦合,它可以是该接口的任何实现。

在您的示例中,您可以将 ThingDecorator 继承为 AuditThingDecorator,并在调用 base.AMethod() 之前覆盖 AMethod 并包含审核功能

这与仅将属性应用于类不同。我认为您正在尝试使用属性应用行为。如果存在容器或系统的其他部分可以读取属性并实际应用给定行为,则属性只能将行为应用于类。使用 DataAnnotations,还有其他类可以读取这些属性并应用行为(例如,在 ASP.NET MVC 中,DefaultModelBinder 使用某些属性在绑定模型时提供验证)。

这是一种 AOP(面向apsect 的编程)方法。应用它的一种方法(也是我倾向于使用的一种方法)是使用 Castle.Core 并创建可以自动实现接口方法或扩展虚拟方法并从正在拦截的方法/属性中读取属性的拦截器,然后应用行为:

http://docs.castleproject.org/Tools.DynamicProxy-Introduction.ashx

它们本质上都是给定类型的代理,但是上面的装饰器模式不是动态的,它们是在代码中创建的,AOP 方法可以在运行时应用行为。

【讨论】:

  • 感谢您的友好回答。但我试图实现的内容包含在帖子中提供的链接中。它说,如果我们在像 Product 类这样的任何实体上使用 Auditable 属性,那么我们将首先使用 EF 代码从数据库中的 Auditable 类中获取来自 Product 类的列 Id 和 Name 以及列 CreatedBy、Created、UpdatedBy、Updated。作为表的名称将是产品。但是得到的只是列 ID 和名称。
  • 示例使用 AOP 技术。从您发布的链接中,1)您需要使用 [Auditable] 来装饰类,2)您需要确保使用 AuditableRepository 包装您的存储库(例如)
猜你喜欢
  • 2012-01-09
  • 2011-02-04
  • 1970-01-01
  • 2014-02-20
  • 1970-01-01
  • 2017-04-21
  • 2020-02-21
  • 2023-03-21
  • 2016-09-16
相关资源
最近更新 更多