【发布时间】:2010-07-28 00:42:08
【问题描述】:
我编写了一个类,它允许派生指定哪些属性可以延迟加载。代码是:
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 时会发生什么? “不起作用”不是很有帮助。
-
更新帖子更具体
标签: c# .net dynamic duck-typing