开源可扩展的企业 N 层应用程序框架(多层架构)






4.67/5 (2投票s)
Xenta 架构概述
引言
Xenta 是一个具有多层架构的可扩展 N 层应用程序。 Xenta 是一个开源项目,可以免费使用。它使用 .NET/C# 编程语言开发,最初面向基于 Web 的解决方案。 它在修改后的 MIT 许可下获得许可。
本文的目的是向您介绍 Xenta 的架构。
要使用源代码,您需要 Microsoft Visual Studio 2010。
架构概述

Xenta 有 4 层
- 数据访问层 (DAL)
- 业务逻辑层 (BLL)
- 服务层
- 表示层
每一层都包含自己的实体。 这些实体在各层之间进行映射(例如,DAL 实体映射到 BLL 实体)。
数据访问层
DAL 由数据抽象和每个具体数据源的抽象实现组成。 数据抽象描述数据实体和数据提供程序接口。 数据实体的基类是 DataEntityBase
。 对于数据提供程序接口,存在基本接口 IDataProvider
。 提供程序的实例化基于配置文件。 默认情况下,数据源是 Microsoft SQL Server(2005 或更高版本),但是请相信我,更改数据源非常容易。
IDataProvider - 数据提供程序接口的基类
public interface IDataProvider
{
#region Methods
void Initialize(string name, NameValueCollection properties);
#endregion
}
IUserDataProvider - 用户数据提供程序的接口
public interface IUserDataProvider : IDataProvider
{
#region Methods
#region C
bool InsertUser(Guid guid, string username, string firstName,
string lastName, Gender gender, DateTime? birthDate, string email,
string comment, string passwordHash, string passwordSalt,
int languageID, int currencyID, int timeZoneID, int countryID,
bool isActive, DateTime createdOn, DateTime updatedOn, out int userID);
#endregion
#region R
UserData GetUser(int userID);
UserData GetUserByEmail(string email);
UserData GetUserByUsername(string username);
UserData GetUserByGuid(Guid guid);
UserDataCollection GetAllUsers(string searchTerm, int? roleID,
int? countryID, int? languageID, int? currencyID, int? timeZoneID,
DateTime? createdOnStart, DateTime? createdOnEnd, bool showHidden,
int startIndex, int count, out int totalCount);
#endregion
#region U
bool UpdateUser(int userID, Guid guid, string username, string firstName,
string lastName, Gender gender, DateTime? birthDate, string email,
string comment, string passwordHash, string passwordSalt, int languageID,
int currencyID, int timeZoneID, int countryID, bool isActive,
DateTime createdOn, DateTime updatedOn);
#endregion
#region D
bool DeleteUser(int userID);
#endregion
#endregion
}
DAL 配置示例
<xentaDAL>
<providers>
...
<add name="UserDataProvider" type="SiberTek.Xenta.Data.Providers.UserDataProvider,
SiberTek.Xenta.Data.MsSqlServer.Core" connection="MsSqlServerConnection" />
...
</providers>
</xentaDAL>
业务逻辑层
BLL 描述业务规则和管理逻辑。 它包含业务实体、管理器、任务等。
实体继承自 BusinessEntityBase
。
每个管理器都实现 IManager
接口。 通常,管理器是单例。 管理器可以包含事件,这些事件可以由其他管理器或任务或其他内容处理。 例如,定义了 EntityEventArgs
类和 EntityEventHandler
委托,用于与实体操作相关的事件,例如 Create
/Update
/Delete
。
UserManager - 用户管理器类示例
public class UserManager : IManager
{
#region Constants
private const string GuestUsername = "guest";
#endregion
#region Fields
private static UserManager _instance = null;
private bool _initialized;
private IUserDataProvider _userDataProvider;
private IUserAttributeDataProvider _attributeDataProvider;
private IUserSessionDataProvider _sessionDataProvider;
#endregion
#region Constructors
private UserManager()
{
_initialized = false;
_userDataProvider = null;
_attributeDataProvider = null;
_sessionDataProvider = null;
}
#endregion
#region Events
public event EntityEventHandler UserCreated;
public event EntityEventHandler UserUpdated;
public event EntityEventHandler UserDeleted;
#endregion
#region Properties
public static UserManager Instance
{
get
{
if(_instance == null)
{
_instance = new UserManager();
}
return _instance;
}
}
...
任务实现 ITask
接口。 每个任务都有 Period
属性,此属性包含一个 TimeSpan
值,该值定义任务执行周期。
任务由 TaskScheduler
类调度。 此类启动一个线程,该线程每秒从文本文件中读取执行计划,运行所需的任务并重新安排列表中每个任务的下一个执行时间。
ITask - 任务接口
public interface ITask
{
#region Properties
TimeSpan Period
{
get;
}
#endregion
#region Methods
void Initialize(NameValueCollection properties);
void TaskProc();
#endregion
}
任务配置示例
<tasks>
...
<add name="MessageDispatcher" type="SiberTek.Xenta.Tasks.MessageDispatcher,
SiberTek.Xenta.Core" />
...
</tasks>
服务层
这个“薄”层基于 WCF 技术。 它允许在不同的物理服务器、一台服务器甚至一个应用程序中部署 Xenta 层。 服务托管在 Xenta.Services.Host
应用程序中。
ICoreService - 核心服务合同
[ServiceContract]
public interface ICoreService
{
#region Methods
#region Users
[OperationContract]
[FaultContract(typeof(XentaFault))]
User CreateUser(string username, string firstName, string lastName,
Gender gender, DateTime? birthDate, string email, string comment,
string password, int languageID, int currencyID, int timeZoneID, int countryID);
[OperationContract]
User GetUser(int userID);
[OperationContract]
User GetGuestUser();
[OperationContract]
User GetUserByUsername(string username);
[OperationContract]
User GetUserByEmail(string email);
[OperationContract]
User GetUserByGuid(Guid guid);
[OperationContract]
UserCollection GetAllUsers(string searchTerm, int? roleID, int?
countryID, int? languageID, int? currencyID, int? timeZoneID, DateTime?
createdOnStart, DateTime? createdOnEnd, bool showHidden, int startIndex, int count);
[OperationContract]
bool IsUsernameBusy(string username);
[OperationContract]
bool IsEmailBusy(string email);
[OperationContract]
bool IsUserPasswordValid(int userID, string password);
[OperationContract]
[FaultContract(typeof(XentaFault))]
bool UpdateUserPassword(int userID, string password);
[OperationContract]
[FaultContract(typeof(XentaFault))]
bool ActivateUser(int userID);
[OperationContract]
bool IsUserActive(int userID);
...
表示层
该层实现了 MVP 模式。 UI 基于 ASP.NET 技术,并分为多个 Web 应用程序,例如: Xenta.Web.Admin
、Xenta.Web.Home
、Xenta.Web.FileStorage
、Xenta.Web.Forum
。 您可以决定要部署哪个应用程序。
在 MVP 模式的上下文中,有:
- 模型 - 可以通过服务访问的业务逻辑
- 视图 - Web 应用程序
- 演示者 - 演示者和辅助类,它们通过服务访问模型
UserPresenter - 用户演示者类示例
public class UserPresenter : PresenterBase
{
#region Methods
public void Update()
{
ViewDataContainer item = View.DataContainer["User"] as ViewDataContainer;
int userID = (int)item["UserID"];
string username = (string)item["Username"];
string email = (string)item["Email"];
string firstName = (string)item["FirstName"];
string lastName = (string)item["LastName"];
bool isActive = (bool)item["IsActive"];
Gender gender = (Gender)item["Gender"];
DateTime? birthDate = (DateTime?)item["BirthDate"];
string comment = (string)item["Comment"];
int languageID = (int)item["LanguageIDv];
int countryID = (int)item["CountryID"];
int timeZoneID = (int)item["TimeZoneID"];
int currencyID = (int)item["CurrencyID"];
if(birthDate.HasValue)
{
birthDate = UserContext.Current.DateTimeConvertToUtc(birthDate.Value);
}
using(CoreServiceClient svc = new CoreServiceClient())
{
svc.UpdateUser(userID, username, firstName, lastName,
gender, birthDate, email, comment, languageID, currencyID,
timeZoneID, countryID, isActive);
}
}
...
UserForm - ASP.NET 控件
public partial class UserForm : ViewBase<UserPresenter>, IForm, ICommandHandler
{
#region Properties
[Browsable(false)]
public int? UserID
{
get
{
return StringHelper.Parse<Int32?>(txtUserID.Text);
}
set
{
txtUserID.Text = value.HasValue ? value.ToString() : String.Empty;
}
}
public string ValidationGroup
{
set
{
vldUsername.ValidationGroup = value;
vldEmail.ValidationGroup = value;
vldEmail2.ValidationGroup = value;
vldPassword.ValidationGroup = value;
vldPassword2.ValidationGroup = value;
vldFileQuota.ValidationGroup = value;
}
}
...
结论
Xenta 具有清晰的架构,并实现了最佳模式和实践。 它很容易扩展。 它使您可以自由地进行打包和部署。 您可以删除所有不必要的东西并构建自己的包。 欢迎您加入我们的社区,您可以在这里获得任何问题的有用答案。