我应该如何将行为注入实体

时间:2013-02-17 19:09:36

标签: c# .net entity-framework design-patterns dependency-injection

我正在探索实体框架数据库的使用首先,我试图了解我是否应该将行为注入实体,如果是,那么这样做的最佳技术是什么。我通常在过去做过这个以避免贫血域对象。一些用例是我将规范注入实体(规范模式/定义可组合业务规则)的地方,或者我可能将ninject实现的工厂注入到根实体中,其中实现的绑定由策略/工厂方法决定使用点)例如下面,我将使用IOC注入ISomethingSpec实现。

 class Foo
 {
    void DoSomething()
    { 
        if(somethingSpec.SatisfiedBy(this)
        {
        }
    }
}

请问,我是否应该考虑将行为与实体关联的不同模式?或者如果它是合理的,使用部分类/属性和方法注入是我首先使用EF5和数据库的最佳选择吗?

这是我的第一篇文章,所以我希望它的格式不是太远了。我发布的内容是因为我已经查看过类似的其他问题,但我无法就将行为与域对象/ EF实体关联的最佳实践达成共识。

2 个答案:

答案 0 :(得分:3)

我使用specification pattern和Entity Framework来过滤从数据库中检索的数据。我认为您可以使用相同的方法并根据您的需求进行调整。

您可以使用DI容器注入您可能需要的规格和其他物体。第一步是为规范对象定义合同,如下所示:

public interface ISpecification<T> where T : class
{
    Expression<Func<T, bool>> GetExpression();
    bool IsSatisfiedBy(T entity);
}

通用规范对象可以这样定义:

public class Specification<T> : ISpecification<T> where T : class
{
    private Expression<Func<T, bool>> expression;

    public Expression<Func<T, bool>> GetExpression()
    {
        return expression;
    }

    public Specification(Expression<Func<T, bool>> expression)
    {
        this.expression = expression;
    }

    public bool IsSatisfiedBy(T entity)
    {
        var query = (new[] { entity }).AsQueryable();

        return query.Any(this.expression);
    }
}

然后您可以像这样更改您的Foo类,这样您就可以使用DI / IoC容器注入依赖项:

public class Foo()
{
    public ISpecification<Foo> Specification 
    {
        get;
        private set;
    }

    public Foo(ISpecification<Foo> specification)
    {
        this.Specification = specification;
    }

    public void DoSomething()
    { 
        if(Specification.SatisfiedBy(this))
        {
            //...
        }
    }
}

创建和使用规范:

// example - create one specification
Expression<Func<Foo, bool>> expression =  ....;  
ISpecification<Foo> fooSpecification = new Specification<Foo>(expression);


// using the specification with linq
var entities = dbContext.Foos.Where(fooSpecification.GetExpression());


// performing validation
var foo = new Foo{
    // ....
};

if(fooSpecification.IsSatisfiedBy(foo))
{
    // do something....
}

此处有更多详情:

http://ruijarimba.wordpress.com/2011/06/05/entity-framework-and-t4-generate-specification-objects-for-your-entities/

答案 1 :(得分:1)

回答这个问题,经过Rui的有益评论之后的一些调查,我得出的结论是,我向一个实体注入服务的意图是有缺陷的。因此,我原来的问题的答案是使用域事件来减少耦合,或者使用“双调度”,如下面的链接。我目前正在将nServiceBus视为实现域事件的技术(以及作为nServiceBus本身的介绍)

以下文章帮助我清楚了解服务类型以及如何使用域模型:

Domain Events Salvation