我已经阅读了许多解释IoC和DI之间差异的线程,虽然许多解释相互矛盾,但我认为它们仍然帮助我理解了它们之间的区别.
所以在这里我想问一下我的理解是否正确,并且发布了有助于我的摘录(虽然其中一些相互矛盾).
我知道在这个问题上已经有很多线程,但我希望这个线程不会被关闭,因为我不认为提到的线程中的任何OP也显示所有相关的帖子(来自各种线程)他们终于明白了.
无论如何,这是我理解的方式(如果可能,请单独解答/回答每个问题):
a)当我们在框架层面应用DIP原则时,我们使用术语IoC?在框架层面实施DIP的机制之一是DI?
b)当我们在较低级别/非框架级别实施DIP(使用DI)时,术语IoC不适用,在这种情况下,我们简称为DI?
c)DI通过将实际创建和选择依赖关系的控制权传递给第三方来帮助我们实现DIP,第三方对所涉及的其他2个中立方是中立的?
d)当在框架级(IoC)应用DIP(使用DI)时,三种类型的控制被反转:
界面的控制.现在,高级模块正在控制低级模块需要遵循的接口,而不是相反
控制流量.- >现在框架代码(而不是用户/业务代码)控制程序的流程(换句话说 - 它们(即框架)调用你(即业务代码) )
依赖创建的控制.这种反转将实际创建和选择依赖关系的控制权传递给第三方,该第三方对所涉及的其他2个中立方是中立的.
e)当在非框架级别应用DIP(使用DI)时,两种类型的控制被反转:
界面的控制.现在,高级模块正在控制低级模块需要遵循的接口,而不是相反
依赖创建的控制.这种反转将实际创建和选择依赖关系的控制权传递给第三方,该第三方对所涉及的其他2个中立方是中立的.
?
以下摘录有助于:
控制反转是通用术语.依赖注入是一种特定类型的IoC
...
控制反转是指框架/基础架构调用应用程序代码,而不是相反
...
可以在不做IoC的情况下进行DI.如果你将一个ConcesoleStringWriter注入到HelloWorld中,我并不认为这是IoC,因为没有"框架"或"基础架构".
如果您接受Fowler的定义,那么控制反转是一个比DI更广泛的术语,涵盖了插入框架的所有框架使用,但框架仍处于控制之中.依赖注入是IoC的一个专门化,它专门用于管理依赖关系.
这是我对这两个术语的定义,但我不确定它是否是一个完整的术语:
甲持久对象是在领域模型中的一类,它表示从数据库中提取的某些信息的一个实例.甲 瞬时对象是在领域模型中的一类,其在存储器中创建的一个实例
a)我假设术语持久性和瞬态仅用于域模型中的对象,但不适用于业务层中居住在域模型之外的对象?
b)我们是否也将这两个术语用于数据传输对象?
c)这两个术语是否也用于价值对象?
谢谢
我已经阅读了很多关于存储库是什么的话题,但仍有一些事情困扰着我.
据我所知,Repository和传统数据访问层之间的唯一区别是Repository的查询构造功能(即查询对象模式).但是当阅读以下存储库模式的定义时,即使我们没有实现查询对象模式,我们仍然可以拥有存储库:
a) 来自:
存储库是我们切换和获取对象的唯一点.它也是与存储通信开始和结束的边界.
我认为上面的引用表明Repository是DAL的入口点.换句话说,根据引用,DAL使用者(比如服务层)通过存储库与DAL通信.但是,数据上下文不应该代表DAL的入口点(因此Repository应该驻留在数据上下文中)?
b) 来自:
将存储库与传统数据访问层区分开来的主要原因在于,所有意图和目的都是集合语义 - 就像.Net中的IList一样
大多数传统的DAL是否也有返回集合的方法(例如List<Customer> GetAllCustomers())?那么,Repository的集合式语义究竟与传统DAL 的集合式语义有什么不同呢?
c) 来自:
简而言之,Repository模式意味着抽象持久层,将其作为集合进行屏蔽.这样,应用程序不关心数据库和其他持久性细节,它只处理抽象(通常编码为接口).
据我所知,上述定义与传统DAL的定义没有任何不同.因此,如果Repository实现只执行了两个函数 - 具有类似集合的语义并将域对象与数据库访问代码的细节隔离 - 它与传统DAL有什么不同?换句话说,它/它应该仍然被称为存储库吗?
d)是什么使以下接口成为Repository接口而不仅仅是常规DAL接口?
public interface IPostsRepository
{
void Save(Post mypost);
Post Get(int id);
PaginatedResult<Post> List(int skip,int …Run Code Online (Sandbox Code Playgroud) public delegate T GenDel<T>();
class Program
{
public static void genMet<T>(GenDel<T> d) { }
static void Main(string[] args)
{
genMet(new GenDel<string>(() => "Works"));
genMet(() => "Works");
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,泛型方法接收lambda表达式作为参数(genMet(() => "Works");),并且从此lambda表达式方法能够推断出参数类型.
为什么方法也不能在下一个示例中推断出参数类型,而不是lambda表达式,我们将委托实例作为参数传递:
genMet(new GenDel(() => "Doesn't work")); // Error: Using the generic type 'GenDel<T>'
// requires 1 type arguments
Run Code Online (Sandbox Code Playgroud) 1)LSP是否也适用于接口,这意味着我们应该能够使用实现特定接口的类并仍能获得预期的行为?
2)如果确实如此,那么为什么编程接口被认为是好事(顺便说一句 - 我知道对接口的编程会增加松散耦合),如果反对使用继承的主要原因之一是由于不存在风险遵守LSP?也许是因为:
a)松散耦合的好处超重了不遵守LSP的风险
b)与继承相比,类(实现接口)不会附加到LSP的可能性要小得多
谢谢
假设公司和个人都有相同的邮件地址.哪些陈述确实有效?
1."如果我修改Company.Address,我希望Person.Address自动获取这些更改"
2."如果我修改Company.Address,它不得影响Person.Address"
如果1为真,则Address应为实体
如果2为真,则Address应为值对象.
不应该在上面的模型中邮件Address是一个Value Object,因为即使Company并且Person有相同的邮件,这个邮件仍然没有概念身份?
换句话说,如果最初Company和Person分享initial.address@gmail.com,然后获得新邮件new.address@gmail.com,那么我们可以争辩说邮件地址 initial.address@gmail.com本身没有改变,而是Company并Person用new.address@gmail.com替换它?
因此,根据我的理解,一个Address共享的事实应该不足以赋予它个性(即身份)?!
谢谢
agile ×1
c# ×1
cohesion ×1
entity ×1
generics ×1
liskov-substitution-principle ×1
oop ×1
persistence ×1
soa ×1
transient ×1