我寫了一個類,允許派生指定哪些屬性可以延遲加載。該代碼是:Duck Typing DynamicObject衍生
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
而一個衍生類:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address",() => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
這工作完全正常獲取和設置屬性值,但我得到一個既可以當我隱式轉換一個RuntimeBinderException或與一個InvalidCastException明確地將SelfHydratingEntity轉換回T.
我知道你可以覆蓋DynamicObject.TryConvert方法,但是我想知道究竟是什麼這個方法。我今天讀了很多關於鴨子打字的文章,並嘗試了幾個圖書館,但沒有一個適用於這種特殊情況。我今天嘗試過的所有庫都使用Reflection.Emit生成一個包裝類,它調用「get_」和「set_」方法,並自然使用反射在包裝實例上查找這些方法。 SelfHydratingEntity當然沒有定義「get_」和「set_」方法。
所以,我想知道這種事情是否可能。有什麼辦法將SelfHydratingEntity的實例投射到T?我正在尋找這樣的事情:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
當您嘗試投射到IPerson時會發生什麼? 「不起作用」不是很有幫助。 – 2010-07-28 01:06:05
更新後的文章更具體 – 2010-07-28 02:37:39