将 DI 与跨应用程序的共享库结合使用
本文关键字:结合 共享 DI 应用程序 | 更新日期: 2023-09-27 17:55:52
我面临着一个设计挑战,我似乎无法以令人满意的方式解决。 我有一个类库程序集,其中包含我所有共享的ORM对象(使用EntitySpaces框架)。 这些对象用于 2 个或多个不同的应用程序,这就是它们位于自己的程序集中的原因。 这个设置对我来说已经工作了4 +年。
我还在Microsoft模式与实践组(P&P)的复合应用程序块(CAB)上构建了几个应用程序。 是的,我知道这真的很旧,但我是一名兼职开发人员,一个人的商店,负担不起更新到当前框架的费用。
这就是我的问题所在:我一直在锻炼我的OO设计技能,每当进行实质性的重构时,我都会尝试从程序方法转向更多的OO方法。 当然,OO设计的一个主要方面是将操作放置在它们使用的数据附近,这意味着我的ORM对象需要在适当的时候添加功能。 当我考虑到我在CAB中使用P&P的Object Builder DI容器并且我将移动到ORM对象中的许多功能将需要访问我的应用程序公开的服务时,这证明是一个真正的头疼问题。
换句话说,假设我有一个名为"Person"的共享业务对象(我知道是原始的),并且我有两个应用程序对一个人做完全不同的事情。 应用程序 A 提供了一组服务,Person 对象需要对这些服务进行 DI 处理,以便采用当前遍布我的服务层的一些方法。 应用程序 B 还具有一组不同的服务,IT 需要将这些服务DI到人员对象中。
考虑到P&P对象生成器如何使用属性修饰和类型反射来解决依赖关系,我不明白如何做到这一点。 简而言之,我有一个共享对象,当在各种应用程序中使用时,我需要注入依赖项,以便它可以执行特定于该应用程序的某些操作。
我能想到的唯一方法是从 Person 对象继承应用程序 A 和 B 中的新类型。 然后,我将我的非共享功能和 DI 代码添加到此特定于应用程序的专用 Person 对象中。 现在我写了,这似乎很明显,但它仍然是我能想出的唯一解决方案,我想在这里问一下是否有其他人有不同的解决方案,他们想提出
?我的解决方案会遇到的一个问题是,我可以看到自己陷入了命名继承类型的困境 - 我的意思是......这是一个人,那你还会怎么称呼它? 无论如何,希望你能对我有一些想法。
此外,我对当前的技术并不时髦,老实说,我只是勉强掌握了我目前正在使用的技术。 因此,如果我说了一些矛盾或令人困惑的话,我希望你能从帖子的其余部分理解到足以理解我所问的内容。
听起来你违反了单一责任原则。
Person
对象应该只保存人员记录的数据。然后,服务将接收Person
对象并对其进行操作,而不是在执行该操作的Person
对象上使用方法。
一个典型的示例是填充 Person
对象。假设应用 A 从 Web 服务中获取数据,应用 B 从数据库中获取数据。在这些情况下,我会调用某种Storage
服务来获取Person
对象。然后,该存储的实现可以特定于每个应用程序,并由应用放入 IOC 中,而不是尝试在共享程序集中使用通用接口。
我同意卡梅隆·麦克法兰的观点:你正在破坏SRP。
当然是OO设计的一个主要方面 正在将操作放置在靠近 他们使用的数据,这意味着 我的 ORM 对象需要有 添加到其中的功能 适当
从 A 放置数据和功能,从 B 放置 AND 功能是两个太多的责任。与SRP相邻几乎总是会导致将数据和功能分离到单独的类(数据结构和对象)中。因此,使用Cameron MacFarlandssugestion可能是最好的方法。
我可以想到几种方法来解决这个问题。
- 分别分离出特定于每个人/应用程序的行为。在应用程序本身中使用 setter 执行依赖项注入。
附录1
public interface IPerson
{
IPersonApp1 Person1 {get; set;}
IPersonApp2 person2 {get; set;}
}
class Person : IPerson
{
IPerson1 Person1 {get; set;}
IPerson2 Person2 {get; set;}
}
public interface IPerson1
{
// App1 specific behavior here
void App1SpecificMethod1();
}
class Person1: IPerson1
{
void App1SpecificMethod1()
{
// implementation
}
}
class App1
{
IPerson objPerson;
// Dependency injection using framework
App1(IPerson objPerson)
{
this.objPerson = objPerson;
// Dependency injection using setter
this.objPerson.Person1 = new Person1();
}
}
- 分别分离出特定于每个人/应用程序的行为。在 Person 构造函数中执行依赖项注入。
Apporach2
class Person : IPerson
{
IPerson1 Person1 {get; private set;}
IPerson2 Person2 {get; private set;}
// DI through constructor. If the type IPerson1 or IPerson2 are not registered, it will be set to null.
Person(IPerson1 objPerson1, IPerson2 objPerson2)
{
this.Person1 = objPerson1;
this.Person2 = objPerson2;
}
}
人员接口项目需要引用 IPerson1 和 IPerson2,或者您可以在人员接口项目本身中声明 IPerson1 和 IPerson2。