循环引用在Visual Studio中是编译不通过的。出现循环引用很可能是设计上抽象不够导致的,根据设计模式的依赖倒置-高层模块不应该依赖于低层模块。二者都应该依赖于抽象,抽象不应该依赖于细节,细节应该依赖于抽象这一原则,可以来解决循环引用。
在一些项目中,使用一些依赖注入的框架如SPRING.net,CASTLE可以在一定程度上避免循环引用。 Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定。
但有时候,项目中一些小的功能点如果使用这些框架会显得“过重”,并且解决功能点之间的循环引用也不太复杂,简言之就是抽象出接口。下面就演示一下如何解决项目间的循环引用。
为了演示,首先新建Product 和Order两个类库,Product类库中内容如下:
///
/// Product实体类
///
public class Product
{
public int ProductId { get; set; }
public int OrderId { get; set; }
public string ProductName { get; set; }
public override string ToString()
{
return String.Format("the product of [{0}] infomations as followings: \r\n OrderId: {1} \r\n ProductName: {2}",
OrderId, ProductId, ProductName);
}
}
public class ProductService
{
///
/// 根据OrderID获取Product
///
///
///
public Product GetProductsByOrderId(int orderId)
{
Product product = new Product()
{
ProductId = 1,
OrderId = orderId,
ProductName = "test product"
};
return product;
}
}
里面有一个Product实体类,然后一个ProductService类用来提供服务,其中有一个名为GetProductsByOrderId的方法可以通过OrderId查询产品信息。
Order类库类似,提供了一个Order实体类和OrderService类来提供服务,其中有一个名为GetOrdersByProductId的方法可以通过ProductId查询订单信息。
///
/// Order实体类
///
public class Order
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public string OrderName { get; set; }
public override string ToString()
{
return String.Format("the order of [{0}] information are as followings: \r\n ProductId: {1} \r\n OrderName: {2}",
OrderId, ProductId, OrderName);
}
}
public class OrderService
{
public Order GetOrdersByProductId(int productId)
{
Order order = new Order()
{
OrderId = 1,
ProductId = productId,
OrderName = "test order"
};
return order;
}
}
现在, 假设我们在Product类中需要调用Order类中的GetOrdersByProductId方法查询订单,那么需要引用Order工程文件,因为实体和方法都在Order类库中,这时Product对Order类库产生了依赖,假设与此同时,Order类中也需要调用Product类中的GetProductsByOrderId方法来查询产品,这样Order类库就对Product产生了依赖。就出现了循环引用的情况。
在这种情况下,我们新建一个Shared类库,将Order和Product中需要对外依赖的部分抽象成接口IOrder和IProduct放到这个第三方库中,并定义一些需要交换数据的实体类OrderModel和ProductModel。
public interface IProduct
{
ProductModel GetProductsByOrderId(int orderId);
}
public interface IOrder
{
OrderModel GetOrdersByProductId(int productId);
}
然后Order和Product项目引用Shared类库,并实现定义好的接口,现在Product类库中的ProductService方法实现IProduct 接口,变为了:
public class ProductService:IProduct
{
///
/// 接口方法,根据OrderId获取产品信息
///
///
///
public ProductModel GetProductsByOrderId(int orderId)
{
ProductModel result;
Product product = GetProduct(orderId);
result= new ProductModel {
OrderId = product.OrderId,