有个项目需要保存多个配置项,配置项可能随着开发不断增加。偏向使用SQLite数据库配合ORM(对象关系映射)来实现。
因为要求并不复杂,就打算自己简单实现一下,练下手。
这里记录遇到的一些点。
类
- C#中的泛型类,可以看作时针对某种泛型生成了新的类。比如类声明的静态代码块(静态构造函数)
static ClassName(){}
会在使用新的泛型时重新执行。不同泛型,类的静态变量也不互通。 - 类的
readonly
字段只能在声明期间或构造函数赋值(包括静态构造函数,当然这种情况需要变量也是静态的)。
反射
- 反射可通过
System.Type
对象实现,Type
对象可由typeof(ClassName)
或obj.getType()
获得。 - 类内容的获取:
Type
对象有一系列Get()方法
,可以访问类内的属性(即有get()
、set()
的变量)、变量、方法等,返回值都是封装好的对象或是对象集合。 - 实例的创建,
Activator.CreateInstance()
:T t=Activator.CreateInstance<T>();
- 泛型实例属性读写(
SetValue()
/GetValue()
):public void Increase(T t) { var propA = typeof(T).GetProperty("A"); var value = propA.GetValue(t, null); if (propA.PropertyType == typeof(int)) { var result = int.Parse(value.ToString()) + 1; propA.SetValue(t, result, null); } }
特性(注解)
- 通过继承
System.Attribute
类即可。public class NonSQL : Attribute { } class Person { [NonSQL] public string FirstName {get;set;} }
- 想要获取属性的特性,可以通过
PropertyInfo.GetCustomAttributes()
即可获取,其他如字段等也有类似方法。
SQLite
- SQLite对
alter
的支持有限,字段一旦添加,就不能通过alter
语句修改字段的属性(类型、主键等)。 - 查找表是否存在,(0-表名):
select count(*) from sqlite_master where type='table' and name = '{0}';
- 建表,(0-表名;1-以逗号隔开的字段定义):
create table if not exists {0} ({1});
- 添加字段,(0-表名;1-字段定义):
alter table {0} add column {1};
- 插入,(0-表名;1-以逗号隔开的字段;2-以逗号隔开的字段对应值):
insert or replace into {0} ({1}) values ({2});
-
where
子句使用:以and
连接多个条件,除了逻辑运算符外,还可以使用like
做字符匹配,百分号(%)代表零个、一个或多个数字或字符,下划线(_)代表一个单一的数字或字符,符号可被组合使用。 - 执行查询时会返回
SQLiteDataReader
对象,有很多方法,这里说两个常用的。- 通过
Read()
读取一列数据,读取成功返回true。 - 通过
["{PropName}"]
可以直接读取字段的值。
- 通过
- 两种执行语句的方法
// 只是执行一条SQL语句 private void ExecuteNonQuery(string sql) { lock (connection) { EnsureDatabaseConnected(); using (var tr = connection.BeginTransaction()) { using (var command = connection.CreateCommand()) { command.CommandText = sql; command.ExecuteNonQuery(); } tr.Commit(); } } } // 执行一条SQL语句,并执行提供的操作,一般用于查询 private void ExecuteQuery(string sql, Action<SQLiteDataReader> action) { lock (connection) { EnsureDatabaseConnected(); using (var command = connection.CreateCommand()) { command.CommandText = sql; var reader = command.ExecuteReader(); action(reader); } } } //后一种的使用示例 public int GetTableCount(string tableName) { var tableCount = 0; var tableCountSql = string.Format("select count(*) from sqlite_master where type='table' and name = '{0}';", tableName); ExecuteQuery(tableCountSql, reader => { reader.Read(); tableCount = reader.GetInt32(0); }); return tableCount; }
其他
- 尽量使用泛型方法而不是泛型类。
-
String.IsNullOrWhiteSpace()
,除了null
和空字符串(String.IsNullOrEmpty()
判断范围),还扩展了空白字符的判断。 - C#中有一个
System.IO.Path
类,可以很方便的拼接文件路径、提取文件所在文件夹等。并且操作是跨平台的。