跨程序集的依赖注入命名空间 [英] Dependency Injection across assemblies & namespaces

查看:164
本文介绍了跨程序集的依赖注入命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个DI问题,我认为我理解原因,但是我需要一些建议来解决。

I am working on a DI problem that I think I understand the cause of, but I need some suggestions to work around.

我已经建立了一个独立的组件与Sql(称为程序集a)和另一个包含业务逻辑的程序集(称为程序集b)对话。我在b程序集中为db类创建了一个接口。由于该接口不是db程序集的一部分,因此我不需要对db项目的任何引用,并且如果我想在运行时运行单元测试并且两个程序集都不运行,则可以加载对db程序集或存根的引用。需要了解其他。

I have built a stand alone assembly that talks to Sql (call this assembly a), and another assembly that contains business logic (call this assembly b). I created an interface for the db class in the b assembly. Since the interface isn't part of the db assembly, I don't need any references to the db project, and I can load a reference to the db assembly or a stub if I want to run unit tests at run time and neither assembly needs to know about the other.

我可以在业务逻辑库中编写如下代码:(假设a和b是它们各自程序集中的名称空间)

I can write code in the business logic library that compiles that looks like this: (pretend that a and b are namespaces in their respective assemblies)

 a.IDatabaseClass db_class = (a.IDatabase)new b.Database();

但是,当我尝试运行此命令时,出现无效的强制转换异常。我认为它可以编译是因为该接口与该类完全匹配,但是在运行时失败,因为对象签名在Database类的继承链中看不到IDatabase。

When I try to run this however, I get an invalid cast exception. I think it compiles because the interface matches the class perfectly, but fails at run time because object signature doesn't see IDatabase in the inheritance chain of the Database class.

使用c ++可以随意转换任何内容,但是c#在转换对象指针方面要严格一些。即使该类具有所有正确的函数签名,它也会由于对象不匹配而被炸毁。

In c++ you can get away with casting anything however you want, but c# is a little bit stricter about casting object pointers. Even though the class has all the correct function signatures, it is blowing up because the objects don't match.

现在,我可以将db对象接口放在程序集中db对象,但是业务逻辑需要对db程序集的引用。同样,这只会在以后产生复杂性,因为如果我在单元测试中编写存根db对象,则仅在我要在测试存根对象中使用的接口时,我需要对db程序集的引用。通过执行此操作,这似乎并没有解开耦合。

Now I could put the db object interface in the assembly with the db object, but then the business logic needs a reference to the db assembly. Also, this just creates complications down the road, because if I write a stub db object in a unit test, I need a reference to the db assembly just for the interface that I am going to use in my test stub object. This doesn't seem to be disentangling couplings by doing this...

我可以将所有接口放在作为db程序集父级的第三个程序集中。业务逻辑和单元测试。这是解决循环依赖问题的方法。但是,这会将db程序集与父程序集联系起来,从而使其模块化程度大大降低,无法与其他项目一起使用。

I could put all the interfaces in a third assembly that is a parent to the db assembly, the business logic, and the unit tests. This is how you can solve circular dependency issues. However, this ties the db assembly to the parent assembly, and makes it a lot less modular to be used with other projects.

我愿意接受有关如何处理的建议设置每个组件,使它们独立运行并可以用于DI。我想我可以将测试存根对象与真实代码放在同一程序集中,但这似乎很奇怪。

I am open to suggestions about how I can set up each assembly so that they function independently and can be used for DI. I suppose I could keep the test stub objects in the same assembly as the real code, but that seems weird.

解决方案:以下答复之一做出了这样的评论:我拍摄的基本上是接口的鸭子式输入。 C#当前不支持鸭子类型,但是我认为这是可能的,因为接口实现的行为与您可以称为部分类指针(或更准确地说,是函数指针的集合)的行为类似。

Solution: One of the replies below makes the comment that what I was shooting for is basically duck-typing for interfaces. C# doesn't support duck typing currently, but I was thinking it might be possible since interface implementation acts in similar way to what you might call a partial class pointer (or probably more accurately, a collection of function pointers). My experiment was showing me otherwise, and that is why.

因此,在Redmond将更多野鸭放入c#之前,似乎我们无法达到最终的优雅解耦程序集水平

so until Redmond puts 'more mallard' into c#, looks like we cannot reach that final elegant level of decoupling assemblies entirely.

推荐答案

创建一个包含公共接口的参考库。这样,您将拥有所有与实现无关的逻辑的通用资源。

Create a reference library containing your common interfaces. This way you'll have a common source with all of your implementation agnostic logic.

我没有经验使这成为一个明确的声明,但我强烈怀疑这种耦合当您谈论引用特定接口的单个​​类型及其行为时,这主要是一个问题。程序集的特殊性不会使耦合成为问题。

I don't have the experience to feel confident making this a categorical statement, but I strongly suspect that coupling is primarily an issue when you're talking about individual types referencing specific interfaces and how they behave. Assemblies don't have the same sort of specificity that would make coupling a problem.

让我修改和扩展。一个程序集必须引用另一个程序集,或者两者都必须引用一个公共程序集。

Let me amend and extend. One assembly must reference the other, or both must reference a common assembly. C# doesn't have duck-interfacing, if that's a thing.

现在,我认为最佳实践是将业务逻辑与外部接口隔离开,所以如果您要执行任何操作,您应该将业务逻辑与数据库实现隔离开来。因此,DB /应用程序程序集引用业务逻辑,而不是其他方式。

Now I think the best practice is to isolate the business logic from external interfaces, so if you're going to do anything you should keep your business logic isolated from your DB implementation. So DB/Application assembly references business logic, but not the other way around.

这里有更多关于依赖方向的信息

这篇关于跨程序集的依赖注入命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆