本篇目的:封装一些抽象类

1::封装日志相关类

2:封装一个Service操作类

3:封装缓存操作类

4:封装其他一些常用Helper

1.1在Framework项目里面建立好相关操作类文件夹,以便于区分

在项目中我们抽象出来的东西一般不直接对应具体的实现,而是要有一种面向接口的编程思维,这里我们封装的操作对象在具体应用时还是通过配置文件的形式配置具体应用哪一个。

本项目中我使用的是log4net记录程序日志信息。log4net是一个功能著名的开源日志记录组件.但是我们要抽象出一个日志接口ILogHelper

namespace zjl.Framework.Log
{
interface ILogHelper
{
void WriteLog(Type t, string info, LogType type, string fromIP); } public enum LogType
{
Info = ,
Error =
} public enum LogTypeEnum
{
/// <summary>
/// 文本日志
/// </summary>
Log4Net = ,
/// <summary>
/// MongoDB数据库日志
/// </summary>
MongoDB =
}
}

这里我们定义的接口只有一个写日志的方法,参数包含日志类型LogType和LogType的枚举如果有其他日志类型还可以继续扩展。

继续我们添加一个日志实现类LogHelper并实现ILogerHelper接口

这里我们要安装一下Log4net,使用Nuget命令安装

安装好了之后实现相关代码,这是一个log4的实现代码

using log4net;
using log4net.Appender;
using log4net.Config;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace zjl.Framework.Log
{
public class LogHelper : ILogHelper
{
public LogHelper()
{
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
var logCfg = new FileInfo(baseDir + @"Configs\Log4net.config");
XmlConfigurator.ConfigureAndWatch(logCfg);
} /// <summary>
/// 配置文件路径
/// </summary>
/// <param name="path"></param>
private void ConfigFilePath(string path)
{
var repository = LogManager.GetRepository();
var appenders = repository.GetAppenders();
foreach (RollingFileAppender roolingfileappender in appenders)
{
roolingfileappender.File = path;
roolingfileappender.ActivateOptions();
}
} /// <summary>
/// 写日志
/// </summary>
/// <param name="t"></param>
/// <param name="ex"></param>
public void WriteLog(Type t, string info, LogType type, string fromIP)
{
var mLog = LogManager.GetLogger(t);
info = string.Format("FromIP:{0}\r\n{1}", fromIP, info);
switch (type)
{
case LogType.Info:
mLog.Info(info);
break;
case LogType.Error:
mLog.Error(info);
break;
default:
mLog.Info(info);
break;
} }
}
}

接下来再提供一个日志的单例LogProvider来具体的提供写日志服务

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using zjl.Framework.Helper; namespace zjl.Framework.Log
{
public class LogProvider
{
//存放SQL数据库的接口实例
private Dictionary<Type, ILogHelper> Log = new Dictionary<Type, ILogHelper>();
// 依然是静态自动hold实例
private static volatile LogProvider instance = null;
// Lock对象,线程安全所用
private static object syncRoot = new Object(); private LogProvider()
{
//将来业务扩展可以在此为所有服务做配置化接口注册
Log.Add(typeof(LogHelper), new LogHelper());
} public static LogProvider Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new LogProvider();
}
}
return instance;
}
} /// <summary>
/// 获取Service实例
/// </summary>
/// <typeparam name="T">需要获取的接口类型</typeparam>
/// <returns>DA实例,如果不存在则返回null</returns>
public ILogHelper GetLogHelper()
{
switch ((LogTypeEnum)Convert.ToInt32(ConfigHelper.Instance.getSystemConfig().LogSet))
{
case LogTypeEnum.Log4Net:
return Log[typeof(LogHelper)];
}
return null;
} /// <summary>
/// 异步调用日志记录
/// </summary>
/// <param name="logInfo"></param>
public void WriteLogAsyn(LogRequest logInfo)
{
Thread t = new Thread(new ParameterizedThreadStart(WriteLog));
t.Start(logInfo);
} private void WriteLog(object o)
{
LogRequest log = o as LogRequest;
this.GetLogHelper().WriteLog(log.declaringType, log.logInfo, log.logType, log.ipAddress);
}
} public class LogRequest
{
public Type declaringType { get; set; }
public string logInfo { get; set; } public LogType logType { get; set; }
public string ipAddress { get; set; }
}
}

上述Helper类中有用到 ConfigHelper,因为我们指定使用的数据库类型或者日之类型的时候只希望是以自定义配置的方式完成.所以封装了一个配置文件操作类

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using zjl.Framework.Cache; namespace zjl.Framework.Helper
{
public class ConfigHelper
{
private static volatile ConfigHelper instance = null;
// Lock对象,线程安全所用
private static object syncRoot = new Object();
private ConfigHelper()
{ } public static ConfigHelper Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new ConfigHelper();
string serverPath = ConfigurationManager.AppSettings["ConfigPath"].ToString();
//判断是否是绝对路径
if (!Path.IsPathRooted(serverPath))
{
serverPath = System.Web.HttpRuntime.AppDomainAppPath + serverPath;
}
ConfigWatcher.SetupWacher(serverPath);
} }
} return instance;
}
} public SystemConfig getSystemConfig()
{
SystemConfig config = CacheManager.Get<SystemConfig>("App.SystemConfig");
if (config != null)
{
return config;
}
string serverPath = ConfigurationManager.AppSettings["SystemConfig"].ToString();
//判断是否是绝对路径
if (!Path.IsPathRooted(serverPath))
{
serverPath = System.Web.HttpRuntime.AppDomainAppPath + serverPath;
}
CacheManager.Insert("App.SystemConfig", XmlHelper.DeSerialize<SystemConfig>(serverPath));
return CacheManager.Get<SystemConfig>("App.SystemConfig");
}
} #region 自定义系统配置类
[XmlType(TypeName = "config")]
public class SystemConfig
{
/// <summary>
/// 日志设置(0:关闭日志,1:文本日志,2:nosql数据库日志,3:sql数据库日志)
/// </summary>
[XmlElement("LogSet")]
public int LogSet { get; set; } /// <summary>
/// 数据库设置(0:两个数据库都访问,优先访问nosql数据库,1:sql数据库,2:nosql数据库)
/// </summary>
[XmlElement("DBSet")]
public int DBSet { get; set; } /// <summary>
/// Redis缓存设置(0:不设Redis缓存,优先访问数据库,1:设置Redis缓存,优先访问redis缓存,不存在则访问数据库) author:liwx(2016/11/09)
/// </summary>
[XmlElement("RedisSet")]
public int RedisSet { get; set; }
}
#endregion
}

还有一个自定义的缓存配置类

接下来 再封装一个services操作类,其实这个类就是封装服务列表和http请求的过程 ,应为我们后面会分布式部署各个独立的模块,而各个独立的模块又相当于一个子服务,所以需要在配置文件中配置服务路径

所有的服务请求,我们在程序中都会使用代理的类去向各个服务发送请求。所以直接上封装好的Server代码吧

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization; namespace zjl.Framework.Server
{
[XmlType(TypeName = "Config")]
public class Services
{
[XmlArray("Services")]
public List<Service> List { get; set; }
} [XmlType(TypeName = "Service")]
public class Service
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Url { get; set; }
[XmlAttribute]
public string Server { get; set; }
[XmlAttribute]
public string Method { get; set; }
[XmlAttribute]
public bool IsRelative { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization; namespace zjl.Framework.Server
{
[XmlType(TypeName = "Config")]
public class Servers
{
[XmlArray("Servers")]
public List<Server> List { get; set; }
} [XmlType(TypeName = "Server")]
public class Server
{
[XmlAttribute]
public string Name { get; set; }
[XmlAttribute]
public string Url { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using zjl.Framework.Helper; namespace zjl.Framework.Server
{
public class ServiceCommon
{
public static Dictionary<string, Service> InitServiceList()
{
Dictionary<string, Server> servers = new Dictionary<string, Server>();
Dictionary<string, Service> services = new Dictionary<string, Service>(); string serverPath = ConfigurationManager.AppSettings["ServerConfig"].ToString();
string servicePath = ConfigurationManager.AppSettings["ServiceConfig"].ToString();
//判断是否是绝对路径
if (!Path.IsPathRooted(serverPath))
{
serverPath = System.Web.HttpRuntime.AppDomainAppPath + serverPath; }
//获取服务器列表
Servers serverList = XmlHelper.DeSerialize<Servers>(serverPath);
foreach (var server in serverList.List)
{
servers.Add(server.Name, server);
} //判断是否是绝对路径
if (!Path.IsPathRooted(servicePath))
{
servicePath = System.Web.HttpRuntime.AppDomainAppPath + servicePath;
}
//获取服务列表
Services serviceList =
XmlHelper.DeSerialize<Services>(servicePath);
foreach (var service in serviceList.List)
{
if (service.IsRelative && servers.Keys.Contains(service.Server))
{
service.Url = servers[service.Server].Url + service.Url;
}
services.Add(service.Name, service);
}
return services;
} /// <summary>
/// 获取服务器列表
/// </summary>
/// <returns></returns>
public static Dictionary<string, Server> InitServerList()
{
Dictionary<string, Server> servers = new Dictionary<string, Server>();
Servers serverList =
XmlHelper.DeSerialize<Servers>(ConfigurationManager.AppSettings["ServerConfig"].ToString());
foreach (var server in serverList.List)
{
servers.Add(server.Name, server);
}
return servers;
} }
}

最后还是使用一个单例来提供实例化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json; namespace zjl.Framework.Server
{
public class ServiceHandler
{
// 依然是静态自动hold实例
private static volatile ServiceHandler instance = null; private static volatile Dictionary<string, Service> serviceList = null; // Lock对象,线程安全所用
private static object syncRoot = new Object();
private ServiceHandler()
{
serviceList = ServiceCommon.InitServiceList();
} public static ServiceHandler Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new ServiceHandler();
}
}
return instance;
}
} /// <summary>
/// 返回字符串对象
/// </summary>
/// <param name="serviceName">服务名称</param>
/// <param name="param">请求的参数,GET请求传字符串,Post请求直接传对象</param>
/// <returns></returns>
public string Request2Str(string serviceName, object param)
{
Service service = null;
string resultStr = "";
//判断是否存在该服务的配置
if (!serviceList.Keys.Contains(serviceName))
{
throw new Exception("调用服务未找到!");
return null;
}
service = serviceList[serviceName];
switch (service.Method.ToUpper())
{
case "GET":
resultStr = Get(service.Url, param as string);
break;
case "POST":
resultStr = Post(service.Url, param);
break;
default:
break;
}
return resultStr;
} /// <summary>
/// 向服务器发起请求
/// </summary>
/// <typeparam name="T">返回的对象类型</typeparam>
/// <param name="serviceName">服务名称</param>
/// <param name="param">请求的参数,GET请求传字符串,Post请求直接传对象</param>
/// <returns></returns>
public T Request<T>(string serviceName, object param) where T : class,new()
{
return JsonConvert.DeserializeObject<T>(Request2Str(serviceName, param));
} //public void reflashServiceList()
//{
// serviceList = ServiceCommon.InitServiceList();
//} public Dictionary<string, Service> getServiceList()
{
return ServiceCommon.InitServiceList();
} private string Get(string url, string param)
{
string result = WebRequestHelper.GetData(param, url);
return result;
} private string Post(string url, object param)
{
string paramString = JsonConvert.SerializeObject(param);
string result = WebRequestHelper.PostData(paramString, url);
return result;
}
}
}

http请求类

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks; namespace zjl.Framework.Helper
{
public class WebRequestHelper
{ /// <summary>
/// 以POST 形式请求数据
/// </summary>
/// <param name="RequestPara"></param>
/// <param name="Url"></param>
/// <returns></returns>
public static string PostData(string RequestPara, string Url)
{
return PostData(RequestPara, Url, "application/json");
} /// <summary>
/// 以POST 形式请求数据
/// </summary>
/// <param name="RequestPara"></param>
/// <param name="Url"></param>
/// <returns></returns>
public static string PostData(string RequestPara, string Url, string ContentType)
{
WebRequest hr = HttpWebRequest.Create(Url);
string ReturnVal = null;
byte[] buf = Encoding.GetEncoding("utf-8").GetBytes(RequestPara);
hr.ContentType = ContentType;
hr.ContentLength = buf.Length;
hr.Method = "POST";
using (Stream RequestStream = hr.GetRequestStream())
{
RequestStream.Write(buf, , buf.Length);
RequestStream.Close();
}
using (WebResponse response = hr.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
ReturnVal = reader.ReadToEnd();
}
} return ReturnVal;
} /// <summary>
/// 以GET 形式获取数据
/// </summary>
/// <param name="RequestPara"></param>
/// <param name="Url"></param>
/// <returns></returns>
public static string GetData(string RequestPara, string Url)
{
string ReturnVal = null;
RequestPara = RequestPara.IndexOf('?') > - ? (RequestPara) : ("?" + RequestPara);
WebRequest hr = HttpWebRequest.Create(Url + RequestPara); byte[] buf = Encoding.GetEncoding("utf-8").GetBytes(RequestPara);
hr.Method = "GET";
using (WebResponse response = hr.GetResponse())
{
using(StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")))
{
ReturnVal = reader.ReadToEnd();
}
}
return ReturnVal;
}
}
}

好了 这样几个通用的抽象工具类就封装的差不多了 没有看懂的小伙伴们不要着急 ,我会附上源码,可能要等到我全部介绍完了才会有人看懂我想表达什么。博主在全部介绍完会上一个完整的案例。

附件下载

亲手搭建一个基于Asp.Net WebApi的项目基础框架2的更多相关文章

  1. 亲手搭建一个基于Asp.Net WebApi的项目基础框架1

    目标:教大家搭建一个简易的前后端分离的项目框架. 目录: 1:关于项目架构的概念 2:前后端分离的开发模式 3:搭建框架的各个部分 这段时间比较闲,所以想把之前项目里用到的一些技术写到博客里来,分享给 ...

  2. 亲手搭建一个基于Asp.Net WebApi的项目基础框架4

    实现目的:配置website端与服务端对接 1:配置好各项配置文件 2:server端编写接口客户端调用 1.1首先配置文件有log4的配置文件,有config的配置文件,还有服务列表的配置文件 首先 ...

  3. 亲手搭建一个基于Asp.Net WebApi的项目基础框架3

    1:使用Framework工具类封装http请求 接上第二篇的步骤,现在在站点中使用封装好的组件,将framework编译好之后把dll提取出来,然后放到lib当中 在website中引用dll 接下 ...

  4. 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(1)

    最近使用vscode比较多. 学习了一下如何在mac上使用vscode开发asp.netcore项目. 这里是我写的关于vscode的一篇文章: https://www.cnblogs.com/cgz ...

  5. 使用EF Code First搭建一个简易ASP.NET MVC网站,允许数据库迁移

    本篇使用EF Code First搭建一个简易ASP.NET MVC 4网站,并允许数据库迁移. 创建一个ASP.NET MVC 4 网站. 在Models文件夹内创建Person类. public ...

  6. Uber如何搭建一个基于Kafka的跨数据中心复制平台 原创: 徐宏亮 AI前线 今天

    Uber如何搭建一个基于Kafka的跨数据中心复制平台 原创: 徐宏亮 AI前线 今天

  7. 快速搭建一个基于react的项目

    最近在学习react,快速搭建一个基于react的项目 1.创建一个放项目文件夹,用编辑器打开 2.打开集成终端输入命令: npm install -g create-react-app 3. cre ...

  8. 使用gulp搭建一个传统的多页面前端项目的开发环境

    1.简介 使用gulp搭建一个传统的多页面前端项目的开发环境 支持pug scss es6编译支持 支持开发环境和打包生成sourceMap 支持文件变动自动刷新浏览器,css是热更新(css改动无需 ...

  9. 基于RxJava2+Retrofit2精心打造的Android基础框架

    代码地址如下:http://www.demodashi.com/demo/12132.html XSnow 基于RxJava2+Retrofit2精心打造的Android基础框架,包含网络.上传.下载 ...

随机推荐

  1. ssh代理登录内网服务器

    服务器 192.168.48.81 # client 192.168.48.82 # bastion 192.168.48.83 # private password方式 192.168.48.81 ...

  2. c#Winform程序调用app.config文件配置数据库连接字符串

    你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings name="  " connectionString= ...

  3. vos忙时闲时费率不一样怎么设置

    问题: 现有一客户要求上午闲时由原来的9:00追加到9:30 即: 9:30——12:00为忙时 14:00——18:00为忙时 其他为闲时 忙时费率为0.04元即4分 闲时费率为0.025元即2分5 ...

  4. querystring处理参数小利器

    相信上一章的讲解,相信大家对url地址有一个更直观的认识,在url解析的时候可以用querystring这样一个module替换,然后对这个query集成一个对象,这里不管是前端开发还是后端开发,都常 ...

  5. 2017.11.12 web中JDBC 方式访问数据库的技术

    JavaWeb------ 第四章 JDBC数据库访问技术 在JavaWeb应用程序中数据库访问是通过Java数据库连接(JavaDateBase Connectivity简称JDBC)数据库的链接一 ...

  6. python同时遍历数组的索引和元素

    1.一般要同时遍历数组的索引和元素需要先确定数组的长度length(元素个数),然后使用range函数来生成数组的索引,最后使用该索引来访问数组的元素. 具体做法如下: l = [2,7,11,15] ...

  7. cuda数组的拷贝

    原文链接 简单描述一下自己要做的事情:(1)CPU三维的vector--->(2)CPU三维数组--->(3)转换到GPU中的三维数组--->(4)转换到CPU中的三维数组,而其中问 ...

  8. 改Chrome的User Agent,移动版网络

    理论上访问手机版或者iPad等平板电脑版的网络,应该可以剩些流量的,毕竟移动网络是经过优化压缩的,但是PC电脑如果访问移动版的网站呢?我主要使用的浏览器是Chrome,这几天也找了下Chrome下的修 ...

  9. 动态生成的DOM做点击事件无效

    有时候我们的标签都是从后台获取的数据,然后利用JS添加到页面上,当我们写生成的标签的点击事件(click)时没有效果. 例如: <section> 测试动态生成的DOM点击事件 <b ...

  10. 前端jQuery之事件流

    1.事件流概念 描述的是从页面中接收事件的顺序 包含事件捕获阶段,处于目标阶段,事件冒泡阶段 2.绑定事件 语法 bind(type,data,fn) 示例:每个标签被点击的时候,弹出其文本 $(&q ...