创建一个小型依赖注入框架





0/5 (0投票)
各位朋友,依赖注入是 ASP.NET 世界中的热门词汇。如今市面上有许多框架,如 Spring.Net、Unity Framework。
各位朋友:
依赖注入是 ASP.NET 世界中的热门词汇。如今市面上有许多框架,如 Spring.Net、Unity Framework、Pico、Avalon 等等。一个典型的 DI 框架包含几个组件。
1. 容器 (Container) : 这是一个映射对象,用于依赖解析。容器是一个容器,在其内部容纳某种抽象。通常,对象管理由正在使用的任何容器负责。
2. 映射指定器 (Mapping Specifier) : 这是一种可配置资源,用于依赖解析。
3. 对象工厂 (Object Factory) : 这通常是一个工厂方法,它使用映射指定器填充容器,并最终将所需的the desired object交付给客户端。
优点 (Benefits) : DI 框架提供了许多优点,以下列出其中一些。
1. 代码量少 (Less code) : 当您使用 DI 框架时,可以节省大量样板代码的编写,其不同组件可用于提供许多常用信息。
2. 单元测试 (Unit Testing) : DI 框架促进了高度的组件解耦,这有助于单元测试。
开发自定义 DI 框架 (Developing a custom DI framework) : 开发这样的框架并不难,一旦完成,它将为我们的应用程序带来一个很棒的设计。因此,在本文中,我们将探讨如何开发这样一个框架。
我们将考虑我们方法论的以下方面。
抽象 (Abstraction) : 抽象是 OOP 的一个重要概念,通常指的是将通用关注点与整体逻辑分离。
无论您处理的是 MVC 应用程序还是 MVP、MVVP、MVVM 应用程序,您都会始终处理称为实体/模型等的对象,它们描述了应用程序中的参与者。
因此,我们的框架将抽象地定义实体的概念。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Abstraction
{
public abstract class EntityBase
{
public abstract bool ValidateEntity();
}
}
这个基类将以一种通用方式定义实体。
操作抽象 (Abstraction of Operations) : 这指的是实体可以参与的离散操作。在典型的服务应用程序中,我们可以将其泛化为 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<EntityBase> GetAll();
EntityBase Delete(EntityBase e);
}
}
整合各部分 (Putting the pieces together) : 定义了上述基本骨架后,我们就可以开始实际使用了。让我们从定义一个实体(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<EntityBase> 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;
}
}
}
}
工厂方法实现 (The factory method Implementation) : 现在我们已经定义了映射,是时候创建一个工厂类了,它在运行时解析我们的依赖关系以生成所需的the desired object。该方法借助我们的属性在实体/模型及其相应的 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>(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 类及其关联的实体。此方法也可用于填充 Dictionary 等容器,以存储实体和 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<Person>(p);
p.Name=”jackie”;
p = per.Update(p) as Person;
}
}
}
解释与优点
- 我们的控制台应用程序(客户端)不了解哪个对象负责处理 Person 实体,它只知道 *IEntityOperations*,并期望 CRUD 操作已定义,这正是创建“*IEntityOperations*”的原因。
- 由于客户端和服务器之间没有链接,两者可以同时开发。
3. 即使在实际实现提供之前也可以进行测试。