昨天編程遇到一個問題兩個類字段都是二十多個,其中有十多個是相同的,需要將一個類的字段賦值給另外一個類,開始的自己想手動的一個個去賦值,后來想來一下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);
|