西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)其它知識(shí) → 為對(duì)象添加擴(kuò)展屬性動(dòng)態(tài)獲取數(shù)據(jù)

為對(duì)象添加擴(kuò)展屬性動(dòng)態(tài)獲取數(shù)據(jù)

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來源:本站整理時(shí)間:2010/12/20 7:26:20字體大。A-A+

作者:佚名點(diǎn)擊:148次評(píng)論:0次標(biāo)簽: 對(duì)象 RegisterProperty 擴(kuò)展屬性

  • 類型:瀏覽輔助大小:2KB語言:中文 評(píng)分:7.2
  • 標(biāo)簽:
立即下載
由于項(xiàng)目需要常常會(huì)遇到為某一個(gè)對(duì)象動(dòng)態(tài)添加屬性的情況,而以前我的實(shí)現(xiàn)方式是創(chuàng)建一個(gè)字典用于存放對(duì)象實(shí)例和它的值,但是往往光這么做是不夠的,例如想在對(duì)象的某個(gè)屬性值改變的時(shí)候做點(diǎn)什么都要寫很多的代碼,所以想是不是能夠?qū)⑦@一類功能進(jìn)行一下封裝。后來因?yàn)閷W(xué)習(xí)WPF的緣故,想到依賴屬性的思想和我需要的功能相近,但是又不能叫我把每一個(gè)想要添加擴(kuò)展的對(duì)象類都去繼承DependencyObject吧,而且有些類是封閉的不能夠繼承,所以依賴屬性不能滿足我的需求。不過說到底依賴屬性還是個(gè)不錯(cuò)的東西,接下來我們將實(shí)現(xiàn)一個(gè)類似的東西 - 擴(kuò)展屬性。

在實(shí)現(xiàn)擴(kuò)展屬性時(shí)我也參考了依賴屬性的源碼,它的設(shè)計(jì)思想的確很“先進(jìn)”。

1.先來看看擴(kuò)展屬性的使用方式:

1: private static ExtendProperty InfoProperty = 2: ExtendProperty.RegisterProperty("Info", typeof(string), typeof(UserInfo),"you win"); 3: var user = new UserInfo() { Age=21, Name="maxzhang" }; 4: 5: user.SetValue(InfoProperty, "hello"); 6: string rrr = (string)user.GetValue(InfoProperty);
是不是看著特別像依賴屬性呢,往下面看:

1: dynamic userDynamic = user.AsDynamic(); 2: rrr= userDynamic.Info; 3: userDynamic.Info = "1"; 4: userDynamic.Age = 50; 5: rrr = userDynamic.Info;
我為擴(kuò)展屬性添加了動(dòng)態(tài)性使對(duì)象屬性的創(chuàng)建和訪問更加方便,這里如果Info屬性在前面沒有用RegisterProperty方法定義過它會(huì)自動(dòng)生成一個(gè)擴(kuò)展屬性且添加屬性值.如果訪問了它的普通屬性屬性也是正常使用的。以上兩個(gè)例子中

UserInfo類的定義是 public class UserInfo : ExtendObject { public string Name { set; get; } public int Age { set; get; }},你可能會(huì)問這不是和依賴屬性一樣嗎?只是把繼承DependencyObject換成了繼承你自己寫的ExtendObject 了。是的這樣看是差不多的,不過以上的情況還是有一個(gè)好處的就是我可以在任何項(xiàng)目里引用它。

如果遇到了不能繼承的情況呢,其實(shí)這種情況有很多。接…

public class UserInfo1 { public string Name{set;get;} } 這個(gè)類不繼承任何類。

解決它這里引入了新的擴(kuò)展類型AttachObject :

1: AttachObject user1Aobj = new AttachObject(user1); 2: var dyuser = user1Aobj.ToDynamicAttachObject(); 3: //var dyuser = user1.ToDynamicAttachObject(); 4: dyuser.Memo = "haha my name i's maxzhang......"; 5: rrr = dyuser.Memo;
其實(shí)AttachObject 類型也是一個(gè)ExtendObject 可以把它看成是一個(gè)ExtendObject 的裝飾。

2.下面我們來看看這些都是怎么實(shí)現(xiàn)的

(1).ExtendProperty

與依賴屬性類似,在ExtendProperty類中用了一個(gè)Dictionary<int,ExtendProperty>來存儲(chǔ)系統(tǒng)中要用到的擴(kuò)展屬性,這樣實(shí)現(xiàn)也達(dá)到了節(jié)省內(nèi)存資源的目地。且這個(gè)類的構(gòu)造器是一個(gè)private的,這樣也就實(shí)現(xiàn)了一個(gè)單例模式,只有在RegisterProperty方法才能創(chuàng)造出一個(gè)ExtendProperty來.

RegisterPropertypublic static ExtendProperty RegisterProperty(string propertyName, Type propertyType, Type ownerType,object defaultValue)
{
var property = new ExtendProperty(propertyName, propertyType,ownerType);
property.OverrideDefaultValue(ownerType, defaultValue);
ExtendPropertysProvider.Set(property.GetHashCode(), property);

return property;
}
用GetHashCode來標(biāo)示我們這個(gè)屬性的唯一性,這里我重寫了這個(gè)函數(shù)它的值是this.ownerType.GetHashCode()^this.propertyName.GetHashCode(),也就是說用注冊(cè)這個(gè)屬性的類型和屬性的名稱確定了這個(gè)擴(kuò)展屬性。我們看到OverrideDefaultValue這個(gè)方法它是用來重寫屬性的默認(rèn)值的,在這個(gè)系統(tǒng)中如果某個(gè)對(duì)象的擴(kuò)展屬性沒有賦過值或說沒有改變過,那么它應(yīng)該在訪問這個(gè)屬性的時(shí)候取得一個(gè)默認(rèn)值而且這個(gè)默認(rèn)值應(yīng)該是所有相同注冊(cè)類型的對(duì)象共有的,而在用普通屬性存儲(chǔ)的對(duì)象中我們實(shí)例化對(duì)象后會(huì)在每一個(gè)對(duì)象中保存相應(yīng)的默認(rèn)值,這樣無疑是浪費(fèi)了內(nèi)存。而且OverrideDefaultValue與AddOwner方法一起使用可以達(dá)到屬性繼承的目的。我們來看看AddOwner方法的實(shí)現(xiàn):AddOwnerpublic ExtendProperty AddOwner(Type ownerType,object defaultValue)
{
int newOwnerHash = ownerType.GetHashCode() ^ this.PropertyName.GetHashCode();
if(defaultValue!=null)
this.OverrideDefaultValue(ownerType, defaultValue);
ExtendPropertysProvider.Set(newOwnerHash, this);
return this;
}
使用AddOwner方法我們就在原有的擴(kuò)展屬性上添加了一個(gè)指向它的引用從而達(dá)到繼承的目地,怎么重寫屬性默認(rèn)值呢?其實(shí)很簡單默認(rèn)值在擴(kuò)展屬性中保存在一個(gè)<type,object>的字典中通過不同的類型我們就可以訪問不同類型的相同屬性的默認(rèn)值了。 (2).ExtendObject

這里ExtendObject就沒什么好說的了,原理就是其內(nèi)部有一個(gè)Dictionary<int, object> propertyValues 存儲(chǔ)著不同對(duì)象的值,用自身的GetHashCode ^ 擴(kuò)展屬性的HashCode 確定值的唯一性。

ExtendObject的源碼,呵呵 public class ExtendObject
{
protected Dictionary<int, object> propertyValues = new Dictionary<int, object>();
private Type OwnerType = null;

public ExtendObject()
{
OwnerType = this.GetType();
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public virtual object GetOwner()
{
return this;
}

protected void AttachOwner(Type ownerType)
{
this.OwnerType = ownerType;
}

public bool IsExtendProperty(string propertyName)
{
return !OwnerType.GetProperties().Any(p => p.Name == propertyName); ;
}

protected ExtendProperty GetProperty(string name)
{
int propertyKey = OwnerType.GetHashCode() ^ name.GetHashCode();
var property = ExtendPropertysProvider.Get(propertyKey);
return property;
}

public object GetValue(ExtendProperty property)
{

int propertyHash = property.GetHashCode();
int key = this.GetHashCode() ^ propertyHash;

object result = null;
if (!propertyValues.TryGetValue(key, out result))
{
result = property.GetDefaultValue(this.OwnerType);
}
return result;
}

public bool ClearValue(ExtendProperty property)
{
bool result = false;
int propertyHash = property.GetHashCode();
int key = this.GetHashCode() ^ propertyHash;

if (propertyValues.Keys.Any(k => k == key))
{
propertyValues.Remove(key);
result = true;
}
return result;
}

public void SetValue(ExtendProperty property, object value)
{
var changedItemArgs = new ExtendPropertyValueChangedArgs();
int propertyHash = property.GetHashCode();
int key = this.GetHashCode() ^ propertyHash;

if (propertyValues.Keys.Any(k => k == key))
{
changedItemArgs.OldValue = propertyValues[key];
propertyValues[key] = value;
}
else
{
changedItemArgs.OldValue = null;
propertyValues.Add(key, value);
}

changedItemArgs.Item = GetOwner();
changedItemArgs.PropertyType = property.PropertyType;
changedItemArgs.PropertyName = property.PropertyName;
changedItemArgs.NewValue = value;

property.OnValueChanged(changedItemArgs);
}

public bool ClearValue(string propertyName)
{
var property = this.GetProperty(propertyName);
if (property != null)
return this.ClearValue(property);

return false;
}

public object GetValue(string propertyName)
{
var property = this.GetProperty(propertyName);
if (property != null)
return this.GetValue(property);

return null;
}

public void SetValue(string propertyName, object value)
{
var property = this.GetProperty(propertyName);

if (property != null)
{
this.SetValue(property, value);
}
else
{
var newProperty = ExtendProperty.RegisterProperty(propertyName, typeof(object), OwnerType);
this.SetValue(newProperty, value);
}
}

public ExtendDynamicObject AsDynamic()
{
return new ExtendDynamicObject(this);
}

}
不過這里還是有一個(gè)小小的技巧的就是OwnerType這個(gè)屬性和AttachOwner方法,默認(rèn)的OwnerType屬性的值是擴(kuò)展對(duì)象本身的Type,但是通過 AttachOwner方法我們可以改變這個(gè)屬性從而達(dá)到將不繼承自ExtendObject類型的對(duì)象裝飾成ExtendObject

對(duì)象的目地。

(3).也就是AttachObject

AttachObject類通過調(diào)用AttachOwner方法使用了這個(gè)技巧,同時(shí)把同樣為ExtendObject的對(duì)象的屬性統(tǒng)統(tǒng)都Copy過來.

AttachObjectpublic class AttachObject : ExtendObject
{
private object owner;

public AttachObject(object obj)
: base()
{
owner = obj;
if (owner is ExtendObject)
{
Type ownerType = typeof(ExtendObject);
FieldInfo fInfo = ownerType.GetField("propertyValues", BindingFlags.Default | BindingFlags.NonPublic | BindingFlags.Instance);
var ownerValues = fInfo.GetValue(owner) as Dictionary<int, object>;

foreach (var v in ownerValues)
this.propertyValues.Add(v.Key, v.Value);

}
this.AttachOwner(owner.GetType());
}

public override object GetOwner()
{
return owner;
}

public override int GetHashCode()
{
return owner.GetHashCode();
}
}
今天到這里

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)