依赖注入(DI)是一种设计模式,它可以帮助开发者减少代码的耦合度,提高代码的可测试性和可维护性。在现代软件开发中,DI框架已经成为构建大型应用程序不可或缺的一部分。本文将探讨如何设计和实现一个简单的DI框架,以及它所带来的好处。
一个典型的DI框架包含以下几个核心组件:
容器是一个映射对象,它帮助解决依赖关系。容器是一个存储抽象的容器,通常负责管理对象的生命周期。
映射规范是一种可配置的资源,它帮助解决依赖关系。
对象工厂通常是一个工厂方法,它使用映射规范来填充容器,并最终将所需的对象提供给客户端。
使用DI框架可以带来许多好处,以下是其中的一些:
使用DI框架可以节省编写大量样板代码的时间,其不同的组件可以提供许多常用的信息。
DI框架促进了组件的高度解耦,这有助于进行单元测试。
开发一个自定义的DI框架并不困难,一旦完成,它将为应用程序提供一个良好的设计。在本文中,将看到如何开发这样一个框架。
抽象是面向对象编程(OOP)的一个重要概念,通常指的是将共同关注点从整体逻辑中分离出来。无论是在MVC、MVP、MVVM等应用程序中工作,总是要处理被称为实体/模型的对象,它们描述了应用程序中的角色。因此,框架将抽象地定义实体的概念。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Abstraction
{
public abstract class EntityBase
{
public abstract bool ValidateEntity();
}
}
这指的是实体可以参与的离散操作。在典型的服务应用程序中,可以将它们概括为CRUD操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Interfaces
{
public interface IEntityOperations
{
EntityBase Create(EntityBase e);
EntityBase Update(EntityBase e);
IEnumerable GetAll();
EntityBase Delete(EntityBase e);
}
}
定义了上述基本骨架后,就可以将其用于实际应用了。让从定义一个实体(Person)开始。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interfaces;
namespace Entities
{
public class Person : EntityBase
{
public string Name { get; set; }
public override bool ValidateEntity()
{
throw new NotImplementedException();
}
}
}
现在,让也定义一个应用程序的业务层。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FrameWork;
using Entities;
using Interfaces;
namespace BusinessLogic
{
[AssociatedEntity(typeof(Person))]
public class PersonBl : IEntityOperations
{
#region IEntityOperations Members
public EntityBase Create(EntityBase e)
{
return new Person { Name = "Jackie" };
}
public EntityBase Update(EntityBase e)
{
return new Person { Name = "Jackie" };
}
public IEnumerable GetAll()
{
throw new NotImplementedException();
}
public EntityBase Delete(EntityBase e)
{
throw new NotImplementedException();
}
#endregion
}
}
这里需要注意的重要一点是属性“AssociatedEntity”,它有助于定义实体与其工作类之间的映射。下面是这个属性的实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interfaces;
namespace FrameWork
{
[AttributeUsage(AttributeTargets.Class)]
public class AssociatedEntity : Attribute
{
Type _t;
public AssociatedEntity(Type t)
{
_t = t;
}
public Type AssociatedType
{
get
{
return _t;
}
}
}
}
现在已经定义了映射,是时候创建一个工厂类来在运行时解析依赖关系,以产生所需的对象。这个方法利用属性来建立实体/模型与其相应的BLL类之间的关系。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Interfaces;
using System.Reflection;
using System.IO;
using System.Configuration;
namespace FrameWork
{
public static class ServiceContext
{
public static IEntityOperations CreateService(T desiredType) where T : EntityBase
{
Assembly asm = Assembly.LoadFile(ConfigurationManager.AppSettings["BLLAssembly"]);
foreach (Type typ in asm.GetTypes())
{
foreach (AssociatedEntity attrib in typ.GetCustomAttributes(typeof(AssociatedEntity), false))
{
if (attrib.AssociatedType == typeof(T))
return Activator.CreateInstance(typ) as IEntityOperations;
}
}
return null;
}
}
}
在这个方法中,基本上是在查找业务逻辑DLL,以查找BLL类及其关联的实体。这个方法也可以用来填充一个容器,比如一个字典,以存储实体和BLL类的映射。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Entities;
using FrameWork;
using Interfaces;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Person p = new Person { Name = "bruce" };
IEntityOperations per = ServiceContext.CreateService(p);
p.Name = "jackie";
p = per.Update(p) as Person;
}
}
}