昨天编程遇到一个问题两个类字段都是二十多个,其中有十多个是相同的,需要将一个类的字段赋值给另外一个类,开始的自己想手动的一个个去赋值,后来想来一下C#基础知识,用PropertyInfo就可以解决类似的问题,博客园写博客需要内容详实,我还是慢慢的C#属性从头写起,先看下属性的定义吧:
属性定义:它提供灵活的机制来读取、编写或计算某个私有字段的值。 可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。 这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。属性通常可以分为常规属性和自动属性。两者之间还是有一点区别的,最开始编程对着两个全无概念。
常规属性
常规属性以前做Winform的时候经常使用,现在开始使用EF,基本上都是使用自动属性,看下常规属性的完成构成:
1.私有字段,一般设置为私有,通过属性来赋值保证起安全性:
1
|
private
string
_age;
|
2.get访问器,负责读取数据,其中可以进行自己的逻辑判断和数据验证,以return或者throw结束:
1
2
3
4
5
|
get
{
//年龄返回值判断
return
_age> 0 ? _age: 0;
}
|
3.set访问器,负责给属性赋值,类似于一个返回类型为void的方法,可以包含逻辑处理,例如可以根据默认的值通过计算后返回结果。
自动属性
上面简单的说了一下常规属性,当属性访问器中不需要其他逻辑时,可以使用自动属性,不过需要注意一点的就是声明自动属性时,编译器将创建一个私有的匿名后备字段,该字段只能通过属性的 get 和 set 访问器进行访问。
1
|
public
int
Id {
get
;
set
; }
|
自动属性没有太多可以可以说的东西,简单的对比一下常规属性和自动属性之间的区别吧:
1.自动实现的属性必须同时声明 get 和 set 访问器。创建 readonly 自动实现属性时,需要将set 访问器设置为private 。
2自动实现的属性上可以使用特性,不能用在支持后备字段上。 如果属性的后备字段上使用特性,则应该只创建常规属性。
3.自动实现属性get,和set中不能包含特殊的逻辑处理。与字段类似,但不同于字段。与字段不同,属性不作为变量来分类,不能将属性作为 ref参数或 out参数传递。
属性PropertyInfo的使用
上面大概简单的说了一下属性和自动属性之间的区别,现在可以回归到文中最开始的时候的那个问题:
1.案例1,如果两个类中有大部分的字段相同,需要将其中一个类的字段赋值给另外一个类:
定义Person类:
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Person {
public
Person(
int
id,
string
name,
string
address)
{
this
.Id = id;
this
.Name = name;
this
.Address = address;
}
public
int
Id {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
string
Address {
get
;
set
; }
}
|
定义User类
1
2
3
4
5
|
public
class
User {
public
int
Id {
get
;
set
; }
public
string
Name {
get
;
set
; }
public
string
Group {
get
;
set
; }
}
|
转换方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public
static
User ConvertObject(User user,Person person)
{
PropertyInfo[] userPro = user.GetType().GetProperties();
PropertyInfo[] personPro = person.GetType().GetProperties();
if
(userPro.Length>0&&personPro.Length>0)
{
for
(
int
i = 0; i < userPro.Length; i++)
{
for
(
int
j = 0; j < personPro.Length; j++)
{<br>
//判断User的属性是不是的Person中
if
(userPro[i].Name == personPro[j].Name && userPro[i].PropertyType == personPro[j].PropertyType)
{
Object value=personPro[j].GetValue(person,
null
);
//将Person中属性的值赋值给User<br> userPro[i].SetValue(user,value , null);
}
}
}
}
return
user;
}
|
方法的调用:
1
2
3
4
5
6
7
8
9
10
|
static
void
Main(
string
[] args)
{
Person person =
new
Person(1,
"FlyElephant"
,
"北京"
);
User user =
new
User();
user.Id = 20;
user = ConvertObject(user, person);
Console.WriteLine(
"Id:"
+ user.Id +
"Name:"
+ user.Name +
"角色:"
+ user.Group);
System.Console.Read();
}
|
2.之前在做Winform的时候就经常回使用到SqlHelper,现在也有很多公司是这么使用的,当时很多东西感觉就是重复性的操作,一度以为编程只是复制粘贴,下面这段代码大家应该很常见:
1
2
3
4
5
6
7
8
9
10
|
List<Person> list =
new
List<Person>();
SqlDataReader sdr =
new
SqlDataReader();
while
(sdr.Read())
{
Person person =
new
Person();
person.Name = sdr.GetString(0);
//....下面类似
list.Add(person);
}
|
开始写的时候觉得是锻炼了,写的多了就觉得无聊了,其实完全可以换一种方式来实现上面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
static
List<T> ConvertData<T>(SqlDataReader sdr)
{
List<T> list =
new
List<T>();
Type type =
typeof
(T);
PropertyInfo[] properties = type.GetProperties();
while
(sdr.Read())
{
T model = Activator.CreateInstance<T>();
for
(
int
i = 0; i < properties.Length; i++)
{
for
(
int
j = 0; j < sdr.FieldCount; j++)
{
//判断属性的名称和字段的名称是否相同
if
(properties[i].Name == sdr.GetName(j))
{
Object value =sdr[j];
//将字段的值赋值给User中的属性
properties[i].SetValue(model, value,
null
);
}
}
}
list.Add(model);
}
return
list;
}
|
1
2
3
|
List<User> list =
new
List<User>();
SqlDataReader sdr = cmd.ExecuteReader();
list = ConvertData<User>(sdr);
|
3.案例三,ajax页面传递值可以使用get方式,或者post方式的传递JSON格式数据转换
简单的转换一个get传递的字符串Name=xx&Age=xx,后台直接用一个字典去模拟了:
1
2
3
4
|
Dictionary<
string
,
object
> dic =
new
Dictionary<
string
,
object
>();
dic.Add(
"Id"
,100);
dic.Add(
"Name"
,
"keso"
);
dic.Add(
"Group"
,
"程序员"
);
|
转换字典方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
static
T ConvertDic<T>(Dictionary<
string
,
object
> dic)
{
T model = Activator.CreateInstance<T>();
PropertyInfo[] modelPro = model.GetType().GetProperties();
if
(modelPro.Length > 0 && dic.Count() > 0)
{
for
(
int
i = 0; i < modelPro.Length; i++)
{
if
(dic.ContainsKey(modelPro[i].Name))
{
modelPro[i].SetValue(model, dic[modelPro[i].Name],
null
);
}
}
}
return
model;
}
|
最后的调用:
1
|
User user = ConvertDic<User>(dic);
|