在某些情况下,例如ExpandoObject,您可以改用IDictionary<string,object> API:
ExpandoObject obj = ...
var dict = (IDictionary<string, object>)obj;
object oldVal = dict[memberName];
dict[memberName] = newVal;
在更一般的IDynamicMetaObjectProvider 情况下:您可以从FastMember 借用CallSiteCache:
internal static class CallSiteCache
{
private static readonly Hashtable getters = new Hashtable(), setters = new Hashtable();
internal static object GetValue(string name, object target)
{
CallSite<Func<CallSite, object, object>> callSite = (CallSite<Func<CallSite, object, object>>)getters[name];
if (callSite == null)
{
lock (getters)
{
callSite = (CallSite<Func<CallSite, object, object>>)getters[name];
if (callSite == null)
{
CallSite<Func<CallSite, object, object>> newSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, name, typeof(CallSiteCache), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
getters[name] = callSite = newSite;
}
}
}
return callSite.Target(callSite, target);
}
internal static void SetValue(string name, object target, object value)
{
CallSite<Func<CallSite, object, object, object>> callSite = (CallSite<Func<CallSite, object, object, object>>)setters[name];
if (callSite == null)
{
lock (setters)
{
callSite = (CallSite<Func<CallSite, object, object, object>>)setters[name];
if (callSite == null)
{
CallSite<Func<CallSite, object, object, object>> newSite = CallSite<Func<CallSite, object, object, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, name, typeof(CallSiteCache), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
setters[name] = callSite = newSite;
}
}
}
callSite.Target(callSite, target, value);
}
}
请注意,我们可以将target 输入为IDynamicMetaObjectProvider,但我们实际上并不需要它 - CallSite API 不需要它。