IDynamicMetaObjectProvider 设置 属性 使用文字名称
IDynamicMetaObjectProvider set property using literal name
我需要使用字符串 属性Name 设置 DynamicObject 属性。我找到了使用此 answer 获取 属性 值的方法,但是当涉及到 setValue 时,我不太确定如何重写代码以设置 属性。我收到运行时错误并且不太确定表达式逻辑。我想知道您是否可以提出任何关于如何实施 void SetProperty(object o, string member,object value)
方法的想法。
在某些情况下,例如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 不需要它。
我需要使用字符串 属性Name 设置 DynamicObject 属性。我找到了使用此 answer 获取 属性 值的方法,但是当涉及到 setValue 时,我不太确定如何重写代码以设置 属性。我收到运行时错误并且不太确定表达式逻辑。我想知道您是否可以提出任何关于如何实施 void SetProperty(object o, string member,object value)
方法的想法。
在某些情况下,例如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 不需要它。