本来想写这个帖子已经很久了,但是公司事情多,做着做着就忘记了。公司因为需要做接口,而且用的还是asp.net的老框架,使用Handler来做,没得办法,自己照着MVC写了一个通过的接口操作模板。

上送json数据,返回的也是json数据。可以像MVC一样自动绑定并可以进行DataAnnotations验证。尽量达到在业务逻辑处理区域不用对上送参数做过多的获取和判断,能一次搞定就一次搞定。

话不多说,上代码!!!

BaseClass:用作接口参数的基类。接口参数类型可以继承该类,也可以不继承,或自己定义其他基类。

public abstract class BaseClass { }

EmptyClass:一个空类。当做一个参数类型传入到接口中,占用地方而已。

public class EmptyClass : BaseClass { }

ModelError:错误消息载体类型。

    [Serializable]
public class ModelError {
public ModelError(Exception exception) : this(exception, null) { } public ModelError(string errorMessage) {
this.ErrorMessage = errorMessage ?? string.Empty;
} public ModelError(Exception exception, string errorMessage) : this(errorMessage) {
if (exception == null)
throw new ArgumentNullException("exception");
this.Exception = exception;
} public Exception Exception { get; private set; }
public string ErrorMessage { get; private set; }
}

ModelErrorCollection:错误消息载体集合。

    [Serializable]
public class ModelErrorCollection : Collection<ModelError> {
public void Add(string errorMessage) {
base.Add(new ModelError(errorMessage));
} public void Add(Exception exception) {
base.Add(new ModelError(exception));
}
}

ModelState:模型绑定状态。

    /// <summary>
/// 模型绑定状态
/// </summary>
[Serializable]
public class ModelState {
private ModelErrorCollection _errors = new ModelErrorCollection();
public bool IsValid {
get {
return _errors.Count == ;
}
}
public ModelErrorCollection Errors {
get {
return _errors;
}
}
}

ModelBinder:模型绑定抽象类,需要继承此抽象类。用来绑定上送参数并验证的基类。

    /// <summary>
/// 模型绑定抽象类,需要继承此抽象类。
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class ModelBinder<T> where T : class {
protected ModelState _modelState; /// <summary>
/// 模型绑定状态
/// </summary>
public ModelState ModelState {
get {
if (_modelState == null)
_modelState = new ModelState();
return _modelState;
}
} /// <summary>
/// 绑定操作
/// </summary>
/// <returns></returns>
public abstract T Binder(); /// <summary>
/// 验证实体数据合法性。如果有错误,请在ModelState参数中获取。
/// </summary>
/// <param name="entity"></param>
protected void Valide(object entity) {
if (entity == null)
return;
//获取T类型的所有公共属性
Type type = entity.GetType();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); if (properties != null && properties.Count() > ) {
//针对每一个公共属性,获取其特性
foreach (var property in properties) {
//如果当前属性为一个自定义类型
if (property.PropertyType != typeof(object) && Type.GetTypeCode(property.PropertyType) == TypeCode.Object) {
this.Valide(property.GetValue(entity, null));
}
else
ValideProperty(entity, property); if (!_modelState.IsValid)
break;
}
}
} /// <summary>
/// 验证属性的每一个特性约束
/// </summary>
/// <param name="entity"></param>
/// <param name="property"></param>
private void ValideProperty(object entity, PropertyInfo property) {
if (entity != null && property != null) {
var attributes = property.GetCustomAttributes(typeof(ValidationAttribute), false);
foreach (ValidationAttribute attribute in attributes)
ValidatePropertyAttribute(entity, property, attribute);
}
} /// <summary>
/// 使用特性对属性进行验证
/// </summary>
/// <param name="entity"></param>
/// <param name="property"></param>
/// <param name="attribute"></param>
private void ValidatePropertyAttribute(object entity, PropertyInfo property, ValidationAttribute attribute) {
if (entity != null && property != null && attribute != null) {
//找到该属性
//注明:每一个函数都应当具有独立性.
PropertyInfo currentProperty = entity.GetType().GetProperties().Where(p => p.Name == property.Name).FirstOrDefault(); //判断当前特性是否有IsRequiredInstance字段,这是自定义的特性,用于验证同一个实例中两个不同共有属性的值
PropertyInfo[] pros = attribute.GetType().GetProperties();
if (pros.Where(it => it.Name == "IsRequiredInstance" && it.PropertyType == typeof(bool)).FirstOrDefault() != null)
attribute.GetType().GetProperty("Instance").SetValue(attribute, entity, null); if (currentProperty != null) {
var value = currentProperty.GetValue(entity, null);
if (!attribute.IsValid(value))
_modelState.Errors.Add(attribute.ErrorMessage);
}
}
} }

BaseHandler:一般处理逻辑的基类。

    /// <summary>
/// 一般处理逻辑的基类。
/// </summary>
/// <typeparam name="T">请求参数模型</typeparam>
/// <typeparam name="R">返回参数模型</typeparam>
public abstract class BaseHandler<T, R> : ModelBinder<T> where T : class where R : class {
protected readonly ILog log;
public BaseHandler() {
log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
public BaseHandler(string typeName) {
if ((typeName ?? "").Trim() != "")
log = LogManager.GetLogger(typeName);
else
log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
} /// <summary>
/// 处理接口API消息
/// </summary>
/// <returns></returns>
public abstract R Process(); /// <summary>
/// 真正需要处理的接口逻辑
/// </summary>
/// <param name="param">客户端传过来的请求参数</param>
/// <returns></returns>
protected abstract R DoWork(T param);
}

IndexHandler:一般业务接口的模板方法处理器。该接口是基础性接口,如果有其他业务需求,请自行另外自定义或继承该接口。

    /// <summary>
/// 一般业务接口的模板方法处理器。
/// 该接口是基础性接口,如果有其他业务需求,请自行另外自定义或继承该接口。
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class IndexHandler<T> : BaseHandler<T, BaseResponseResult> where T : class {
public IndexHandler() : base() { }
public IndexHandler(string typeName) : base(typeName) { } /// <summary>
/// 对实体模型进行绑定和参数的特性验证
/// </summary>
/// <returns></returns>
public override T Binder() {
//初始化模型
T rc = default(T); try {
//初始化ModelState
if (_modelState == null)
_modelState = new ModelState();
else
_modelState.Errors.Clear(); //获取数据
Stream stream = HttpContext.Current.Request.InputStream;
stream.Seek(, SeekOrigin.Begin);
byte[] buffer = new byte[stream.Length];
int count = stream.Read(buffer, , buffer.Length);
if (count > ) {
string requestParam = Encoding.UTF8.GetString(buffer);
//绑定数据
rc = new JavaScriptSerializer().Deserialize<T>(requestParam);
if (rc != null) {
//验证数据合法性
base.Valide(rc);
}
else
_modelState.Errors.Add("绑定数据失败!");
}
else
_modelState.Errors.Add("请求参数为空!");
}
catch (Exception ex) {
_modelState.Errors.Add("绑定数据出现错误!");
} return rc;
} /// <summary>
/// 处理接口API消息
/// </summary>
/// <returns></returns>
public override BaseResponseResult Process() {
BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError); try {
//绑定请求参数
T requestParam = Binder();
//开启逻辑操作
if (_modelState.IsValid)
rc = DoWork(requestParam);
else {
StringBuilder sbuilder = new StringBuilder();
foreach (var error in _modelState.Errors)
sbuilder.Append(error.ErrorMessage); rc.SetResult(ErrorCode.InvalideParameter, sbuilder.ToString());
}
}
catch (Exception ex) {
rc.SetResult(ErrorCode.SystemError);
rc.returnData = null;
log.Error("Process", ex);
} return rc;
}
}

BaseResponseResult:返回结果。

    /// <summary>
/// 返回结果
/// </summary>
public class BaseResponseResult {
public BaseResponseResult() { } public BaseResponseResult(int returnValue, string returnMsg) {
_code = returnValue;
_message = returnMsg;
} public BaseResponseResult(ErrorCode code, string returnMsg="") {
SetResult(code, returnMsg);
} private int _code = ;
private string _message = "";
private string _contentType = "application/json";
/// <summary>
/// 错误码,0表示成功,其他表示失败
/// </summary>
public virtual int returnValue { get { return _code; } }
/// <summary>
/// 错误码,0表示成功,其他表示失败
/// </summary>
public virtual string returnMsg { get { return _message; } }
/// <summary>
/// 返回的数据,json格式
/// </summary>
public virtual object returnData { get; set; } /// <summary>
/// 设置返回状态码
/// </summary>
/// <param name="code"></param>
public virtual void SetCode(int code) {
_code = code;
} /// <summary>
/// 设置返回状态码
/// </summary>
/// <param name="code"></param>
public virtual void SetCode(ErrorCode code) {
SetResult(code);
} /// <summary>
/// 设置返回消息
/// </summary>
/// <param name="message"></param>
public virtual void SetMessage(string message) {
_message = message;
}
/// <summary>
/// 设置返回状态码和消息
/// </summary>
/// <param name="returnValue"></param>
/// <param name="returnMsg"></param>
public virtual void SetResult(int returnValue, string returnMsg) {
_code = returnValue;
_message = returnMsg;
} /// <summary>
///
/// </summary>
/// <param name="code">ErrorCode代码</param>
/// <param name="returnMsg">返回消息。如果此项不输入值,则自动设置默认值!</param>
public virtual void SetResult(ErrorCode code, string returnMsg="") {
this._code = (int)code;
this._message = (returnMsg??"").Trim()!=""?returnMsg:ErrorMsg.ErrorMessage[code];
}
/// <summary>
/// 设置返回消息体
/// </summary>
/// <param name="obj"></param>
public virtual void SetReturnData(params object[] obj) {
if (obj != null && obj.Length > ) {
this.returnData = obj.ToList();
}
} public virtual void SetReturnData(object obj) {
this.returnData = obj;
} public virtual void SetContentType(string contentType) {
this._contentType = contentType;
} /// <summary>
/// 将当前结果转化为JSON字符串
/// </summary>
/// <returns></returns>
public virtual string ToJson() {
return new JavaScriptSerializer().Serialize(this);
} public virtual void Response(bool isEnd = true) {
HttpContext.Current.Response.ContentType = _contentType;
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
HttpContext.Current.Response.Write(this.ToJson());
if (isEnd)
HttpContext.Current.Response.End();
}
}

ErrorCode:返回状态码枚举。

 public enum ErrorCode {
/// <summary>
/// 操作错误
/// </summary>
OperationError = -,
/// <summary>
/// 成功
/// </summary>
Success = ,
/// <summary>
/// 失败
/// </summary>
Failed = ,
/// <summary>
/// 无数据
/// </summary>
NoData=,
/// <summary>
/// 不存在此页面
/// </summary>
NotExistPage=,
/// <summary>
/// 无权限
/// </summary>
NoPermission=,
/// <summary>
/// 未登录
/// </summary>
NoLogin=,
/// <summary>
/// 被禁止
/// </summary>
Forbidden=,
/// <summary>
/// 请求参数格式不符合要求
/// </summary>
InvalideParameter = ,
/// <summary>
/// 无此接口
/// </summary>
NoAction = ,
/// <summary>
/// 系统错误
/// </summary>
SystemError = ,
} public class ErrorMsg {
public static Dictionary<ErrorCode, string> ErrorMessage = new Dictionary<ErrorCode, string> {
{ ErrorCode.OperationError,"服务器响应错误!"},
{ ErrorCode.Success,"成功!"},
{ ErrorCode.Failed, "失败!"},
{ ErrorCode.NoData, "查无数据!"},
{ ErrorCode.NotExistPage,"此页码不存在!"},
{ ErrorCode.InvalideParameter,"请求参数非法!"},
{ ErrorCode.NoAction,"无此接口!"},
{ ErrorCode.SystemError,"系统错误!"},
{ ErrorCode.NoPermission,"无权限操作此功能!" },
{ ErrorCode.NoLogin,"未登录!"},
{ ErrorCode.Forbidden,"操作被禁止!"},
};
}

接下来介绍使用方法:

IndexHandler_Base64:定义一个接收base64字符串参数的接口处理器。代码如下:

    /// <summary>
/// 一般业务接口的模板方法处理器,适用于参数为base64字符串的请求
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class IndexHandler_Base64<T> : IndexHandler<T> where T:class {
//当前接口是否需要登录后才能操作
protected bool _isLoginRequired = false; /// <summary>
/// 实例化一个只接收base64字符串的接口操作
/// </summary>
/// <param name="isLoginRequired">当前接口是否需要登录。true:需要 false:不需要(默认)</param>
public IndexHandler_Base64(bool isLoginRequired = false) : base() { _isLoginRequired = isLoginRequired; }
/// <summary>
/// 实例化一个只接收base64字符串的接口操作
/// </summary>
/// <param name="typeName">发起日志记录的类名</param>
/// <param name="isLoginRequired">当前接口是否需要登录。true:需要 false:不需要(默认)</param>
public IndexHandler_Base64(string typeName,bool isLoginRequired=false) : base(typeName) { _isLoginRequired = isLoginRequired; } /// <summary>
/// 对实体模型进行绑定和参数的特性验证
/// </summary>
/// <returns></returns>
public override T Binder() {
//初始化模型
T rc = default(T); try {
//初始化ModelState
if (_modelState == null)
_modelState = new ModelState();
else
_modelState.Errors.Clear(); //获取数据
Stream stream = HttpContext.Current.Request.InputStream;
stream.Seek(, SeekOrigin.Begin);
byte[] buffer = new byte[stream.Length];
int count = stream.Read(buffer, , buffer.Length);
if (count > ) {
string requestParam = Encoding.UTF8.GetString(buffer);
requestParam = Encoding.UTF8.GetString(Convert.FromBase64String(requestParam));
//绑定数据
rc = new JavaScriptSerializer().Deserialize<T>(requestParam);
if (rc != null) {
//验证数据合法性
base.Valide(rc);
}
else
_modelState.Errors.Add("绑定数据失败!");
}
else
_modelState.Errors.Add("请求参数为空!");
}
catch (Exception ex) {
_modelState.Errors.Add("绑定数据出现错误!");
} return rc;
} public override BaseResponseResult Process() {
//如果该接口需要登录后才能操作,则检查当前用户是否登录
if (_isLoginRequired) {
int userId = ;
try {
userId = Login.GetSession("UserID");
}
catch { }
if (userId <= )
return new BaseResponseResult(ErrorCode.NoLogin);
} return base.Process();
}
}

接下来定义一个Index.ashx文件,开始使用模板接口。

    /// <summary>
/// index 的摘要说明
/// </summary>
public class Index : IHttpHandler {
private readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//当前登录的用户
public static int _thisUserId {
get {
return Login.GetSession("UserID");
}
}
public void ProcessRequest(HttpContext context) {
BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError, "获取数据失败!"); try {
string action = GetAction(); switch (action) {
//获取 xxx列表
case "":
rc = new ListHandler().Process();
break;
//获取 xxx信息
case "":
rc = new ItemHandler().Process();
break; default:
rc.SetResult(ErrorCode.NoAction);
break;
} }
catch (Exception ex) {
log.Error("ProcessRequest", ex);
rc.SetResult(ErrorCode.SystemError);
} rc.Response();
} public bool IsReusable {
get {
return false;
}
} /// <summary>
/// 获取Action接口名称
/// </summary>
/// <returns></returns>
private string GetAction() {
string rc = ""; try {
rc = HttpContext.Current.Request["action"] ?? "";
if ((rc ?? "").Trim() == "") {
Stream stream = HttpContext.Current.Request.InputStream;
if (stream != null) {
byte[] buffer = new byte[stream.Length];
int count = stream.Read(buffer, , buffer.Length);
if (count > ) {
try {
string requestParam = Encoding.UTF8.GetString(buffer);
requestParam = Encoding.UTF8.GetString(Convert.FromBase64String(requestParam));
JsonData jd = JsonMapper.ToObject(requestParam);
if (jd != null && jd.Keys.Contains("action"))
rc = jd["action"].ToString();
}
catch { }
}
}
}
}
catch (Exception ex) {
log.Error("GetAction", ex);
} return rc;
} } #region 接口处理区 #region 1001 获取 xxx列表
public class ListReqModel { [Required(ErrorMessage = "请上送需要类型!")]
[Range(0,5, ErrorMessage = "type参数值有误!")]
public int type { get; set; }
/// <summary>
/// 页码索引,从0开始
/// </summary>
[Required(ErrorMessage = "请上送页码索引!")]
[Min(, ErrorMessage = "pageIndex参数值有误!")]
public int pageIndex { get; set; } /// <summary>
/// 每页个数
/// </summary>
[Required(ErrorMessage = "请上送每页的个数!")]
[Min(, ErrorMessage = "pageSize参数值有误!")]
public int pageSize { get; set; } }
public class ListHandler : IndexHandler_Base64<ListReqModel> { public ListHandler() : base("ListHandler") { }
protected override BaseResponseResult DoWork(ListReqModel param) {
BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError);
int totalCount = ;
ProjectBLL biz = new ProjectBLL();
DataTable table = biz.GetList(param.type ,Index._thisUserId, out totalCount, param.pageIndex, param.pageSize); if (table != null && table.Rows.Count > ) {
rc.SetReturnData(new
{
//总个数
totalCount = totalCount,
list = table.AsEnumerable().Select(it => new
{
id = it["ID"].ToInt64(),
title = it["Title"].ToNormalString(),
frontCover = it["FrontCover"].ToNormalString()
}).ToList()
});
rc.SetResult(ErrorCode.Success, "成功!");
}
else if (totalCount > )
rc.SetResult(ErrorCode.NotExistPage, "当前页码不存在!");
else
rc.SetResult(ErrorCode.NoData, "没有数据哟!"); return rc;
}
}
#endregion #region 1002 获取xxx信息 public class ItemReqModel {
[Required(ErrorMessage = "请上送项目标识!")]
[Min(, ErrorMessage = "id参数值有误!")]
public long id { get; set; }
} public class ItemHandler : IndexHandler_Base64<ItemReqModel> {
public ItemHandler() : base("ItemHandler") { } protected override BaseResponseResult DoWork(ItemReqModel param) {
BaseResponseResult rc = new BaseResponseResult(ErrorCode.OperationError);return rc;
}
} #endregion#endregion

ajax的使用方式:

//接入说明:
//1、请使用POST方式上传;
//2、请将参数组装为Json字符串,如:{'action':'xxx','xx':'xx'};
//3、Json字符串组装好以后,将其变为Base64字符串后上传。 //上送数据案例如下所示:
$.ajax({
type: "POST",
dataType: "json",
url: GetHost() + 'Index.ashx',
data: Base.encode('{"action":"1001","type":"' + type + '","pgIndex":' + pageIndex + ',"pgSize":' + pageSize + '}'),
contentType:"application/json",
success: function (data) {
//获取数据
if (data) {
//成功获取数据
if (data.returnValue == ) {
//处理数据
}
}
}
});

至此,完毕!以上的通用接口处理器采用了模板方法设计模式,尽量减少重复工作量。

说明:本篇文章为作者原创,如需转载,请说明来源及出处!

asp.net 自定义的模板方法接口通用类型的更多相关文章

  1. asp.net core参数保护之自定义要保护的参数类型

    asp.net core参数保护之自定义要保护的参数类型 Intro 为了实现 asp.net core 下的参数保护,扩展了asp.net core 中 DataProtection,可以自动化的保 ...

  2. ASP.NET交互Rest服务接口(Jquery的Get与Post方式)

    ASP.NET交互Rest服务接口(Jquery的Get与Post方式) 本文将通过一个简单的实例,介绍如何创建一个Rest服务接口,以及通过JQUERY去对它进行调用;主要采取两种方式分别为Get跟 ...

  3. 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式

    连表查询都用Left Join吧   最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...

  4. 《连载 | 物联网框架ServerSuperIO教程》- 13.自定义视图显示接口开发,满足不同的显示需求

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  5. ABAP基本数据类型、通用类型

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. Android 代码库(自定义一套 Dialog通用提示框 )

          做Android开发五年了,期间做做停停(去做后台开发,服务器管理),当回来做Android的时候,发现很生疏,好些控件以前写得很顺手,现在好像忘记些什么了,总要打开这个项目,打开那个项目 ...

  7. ASP.NET中共有哪几种类型的控件?其中,HTML控件、HTML服务器控件和WEB服务器控件之间有什么区别

    ASP.NET的控件包括WEB服务器控件.WEB用户控件.WEB自定义控件.HTML服务器控件和HTML控件.HTML控件.HTML服务器控件和WEB服务器控件之间的区别如下所示.q      HTM ...

  8. ASP.NET WebAPI构建API接口服务实战演练

    一.课程介绍 一.王小二和他领导的第一次故事 有一天王小二和往常一下去上早班,刚吃完早餐刚一打开电脑没一会儿.王小二的领导宋大宝走到他的面前,我们现在的系统需要提供服务给其他内部业务系统,我看你平时喜 ...

  9. 使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证

    使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证   目前WEB 前后端分离的开发模式比较流行,之前做过的几个小项目也都是前后分离的模式,后端使用asp.net weba ...

随机推荐

  1. H5页面解决IOS进入不自动播放问题(微信内)

    废话少说,直接上代码. 主要还是调用微信的jdk做兼容处理.,安卓可自动播放. ($(function(){ $(function(){ /* ** 复选框*/ $('.ul-radio').on(' ...

  2. MySQL之最基本命令

    前言:以下是数据库最基础最常用的命令,特别适用初学者练习,希望通过不断练习这些命令来熟练操作.巩固基础,因为只有不断地练习才能将知识真正变成自己的东西. 快速查看以下内容: 操作 命令 创建数据库 C ...

  3. Crossin-8-1;8-2课程记录

    打开文件:    open,注意打开文件的路径    读取结束需使用close读取文件:    read    readlines    readline    for in 重置光标位置:   se ...

  4. centos 7.1系统更改Mariadb数据存储位置步骤分享

    一.首先确保你要更改Mariadb数据存储的位置的空间够大 现在已将Mariadb存储位置更改到/opt/目录下 1.然后将Mariadb服务stop:systemctl stop mariadb 2 ...

  5. JavaScript实现常见算法面试题

    算法题目部分参照了<进军硅谷>这本书. github:https://github.com/qcer/Algo-Practice (如果你觉得有帮助,记得给个star,THS) 一.排序 ...

  6. 吐槽CSDN--想钱想疯了--阅读全文需要关闭广告屏蔽

    吐槽CSDN 想钱想疯了–阅读全文需要关闭广告屏蔽 近来csdn开始主推博客皮肤升级,说白了就是有一套新的盈利模式,具体怎么操作呢: 1. 采用信息流方式,博客内容变成类似朋友圈.微博.知乎那样的信息 ...

  7. 张高兴的 Windows 10 IoT 开发笔记:使用 MAX7219 驱动 8×8 点阵

    GitHub:https://github.com/ZhangGaoxing/windows-iot-demo/tree/master/MAX7219

  8. shell编程/字库裁剪(3)——验证

    版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/7712496.html 作者:窗户 Q ...

  9. JavaBean编辑器的简单介绍

    引言 Sun所指定的JavaBean规范很大程度上是为IDE准备的--它让IDE能够以可视化的方式设置JavaBean的属性.如果在IDE中开发一个可视化的应用程序,则需要通过属性设置的方式对组成应用 ...

  10. C GOTO使用示例

    GOTO虽然会破坏程序的结构,使用代码可读性变差,但是GOTO依然还是有可用的地方 #include <stdio.h>#include <stdbool.h> int mai ...