直接参考真的有必要吗?

时间:2015-10-20 10:40:42

标签: .net reference

假设我们的visual studio解决方案中有3个项目。项目A,B和C.

项目代码:

public class A
{
  public void someMethodA()
  {
    B b = new B();
    b.someMethodB(new C());
  }
}

项目B代码:

public class B
{
  public void someMethodB(C c)
  {
    c.foo();  // we do something with C, call C's method
  }
}

项目C代码:

public class C
{
  public void foo()
  {
    return; // just for testing
  }
}

项目B根据需要引用项目C(someMethodB中需要C类)。项目A引用项目B,因为它创建新对象B并调用B的方法 - someMethodB()。

此时我们的解决方案将无法编译,因为项目A需要引用项目C - 它调用需要项目C的b.someMethodB(new C())。项目A是否真的需要引用项目C?不能从项目B获得它,它也引用它。我知道每个项目都会生成自己的dll文件,在bin目录中有3个文件,但它仍然可以从项目B中获得所需的文件。

项目C不是B域,但我们可以参考C到B。

4 个答案:

答案 0 :(得分:1)

如果A只是在B上调用方法而不必传入C,即使该方法本身使用C,也不需要直接引用。但是,由于A需要构造C,因此需要直接引用C才能获得所需的元数据 - 此元数据包含在C中,不会复制到B。

如果从链接的所有引用库中复制了所有元数据,那么您只需要直接引用您正在使用的dll,即使从未使用过该函数,dll的大小也会膨胀 - 它需要在那里“以防万一”。

答案 1 :(得分:0)

为什么不在项目B中创建一个返回new C()的方法?然后你可以避免在A中使用C.

答案 2 :(得分:0)

是的,A需要直接引用,因为它需要知道它正在处理什么类型的C 例如,可能有一个System.Whatever.C和一个MyProject.C - 现在,如果你没有指定它,它应该在new C()调用什么构造函数?

如果你想避免在A中引用,你可以在someMethodB中创建C的实例,而不是将其作为参数传递。

答案 3 :(得分:0)

如果您的C程序集实现了某个接口(例如IC),而程序集A引用了定义接口的程序集,那么{{只要A方法的返回类型不是具体的C,而是接口B,就不必了解C的任何内容。

示意图,它应该是这样的:

If you have a common assembly where the interface is defined, you don't need to reference C explicitly

这很可能是你应该如何组织你的应用程序。我注意到你提到传递某个IC,其中包含数据库连接所需的信息,但你当然不希望从UI层访问数据库凭据,甚至不能创建实际的ConnectionInfo个实例。

例如,您可以实现一种存储库模式,或者像这样的简单ORM:

DbConnection

您的// IC assembly (common assembly containing entities and repo interfaces) public interface ISession : IDisposable { // It can even be an empty, marker interface for the // outside world. Only `C` will know its internals anyway. } public interface IRepoFactory { ISession OpenSession(); IRepo<T> GetRepo<T>(ISession session); } 程序集可以将具体的B实例返回到Session

A

但是你的// B assembly // RepoFactory should also be internal to B assembly, // the only thing that A needs is a method which will // provide the implementation of IRepoFactory internal RepoFactory : IRepoFactory { public ISession OpenSession() { // this creates a concrete instance, // but callers will only get the `ISession` interface return C.CreateActualSession(); } // other methods should also accept the session // object through its interface public IRepo<T> GetRepo<T>(ISession session) { return C.GetRepo(session); } } 程序集可以使用A而不知道它是如何在幕后实现的:

ISession