是否可以在 C# 中获取空值删除表达式的默认值?



给定dynamicobject,如果有办法在null值删除的表达式中获取默认值? 代码片段可能如下所示:

[Serializable]
public class Dynamico : DynamicObject, IDictionary<string, object>, ICloneable, INotifyPropertyChanged, IXmlSerializable
{
private readonly IDictionary<string, object> _values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
public object this[string key]
{
get { return GetProperty(key); }
set
{
_values[key] = value;
OnPropertyChanged(key);
}
}
public object GetProperty(string propertyName)
{
if (_values.ContainsKey(propertyName) == true)
{
return _values[propertyName];
}
return RequestProperty(propertyName);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = GetProperty(binder.Name);
**//To do: to get the default value of null value removal expression**
return true;
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
return base.TryInvoke(binder, args, out result);
}
......
}

我可以使用以下代码来利用class

dynamic obj = new Dynamico();
.......
var t = obj.DemoProp ?? "Default value is assigned";

我的问题是在Dynamicclass定义的TryGetMember方法中,如何获取默认值,即。"已分配默认值"?解决方案可以使用表达式,任何伙伴都可以建议吗?

感谢每个人,为什么我需要实现这一目标是因为我正在开发一个由 MVC 提供支持的多模板支持的 CMS 引擎,我想保持模板对开发人员友好,等等......(请原谅我跳过长篇大论...

在这里,我提出了一个解决方案,只需粘贴下面尚未优化的代码即可。

System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace();
var frames = st.GetFrames();
System.Diagnostics.StackFrame expfm = null;
for (int i = 0; i < frames.Length; i++)
{
string fn = frames[i].GetMethod().Name;
if (fn == "get_Item" || fn == "UpdateAndExecute1") // to find the caller
{
expfm = frames[i + 1];
break;
}
else if (fn == "Execute")
{
expfm = frames[i];
break;
}
}
if (expfm != null)
{
var mb = expfm.GetMethod().GetMethodBody();
byte[] il = mb.GetILAsByteArray();
int offset = expfm.GetILOffset();
bool found = false;
for (int i = offset; i < il.Length && i <= offset + 100; i++)
{
if (il[i] == OpCodes.Brtrue_S.Value && il[i + 2] == OpCodes.Pop.Value && il[i + 3] == OpCodes.Ldstr.Value)
{
offset = i + 4;
found = true;
break;
}
}
if (found)
{
int mt = ReadInt32(il, ref offset);
var defs = expfm.GetMethod().Module.ResolveString(mt);
}
}
private static int ReadInt32(byte[] il, ref int position)
{
return (((il[position++] | (il[position++] << 8)) | (il[position++] << 0x10)) | (il[position++] << 0x18));
}

变量"defs"包含我需要的默认值。

你可以试试TryConvert

public override bool TryConvert(ConvertBinder binder, out object result)
{
if (binder.Type == typeof(String))
{
result = node.Value;
return true;
}
else
{
result = null;
return false;
}
}

更多阅读: https://blogs.msdn.microsoft.com/csharpfaq/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject/

这是不可能的,至少在你现在使用的语法中是不可能的。在表达式obj.DemoProp ?? "Default value is assigned"中,隐式调用Dynamico.TryGetMember的是左操作数的求值,正如在回答这个问题中所讨论的,C#甚至不计算空合并运算符(??(的右操作数,除非它确定左操作数为空。因此,"Default value is assigned"的值——或者你放在它的位置上的任何表达式——不能用于obj.DemoProp求值调用的方法,因为它的值甚至还没有确定。

如果希望确定动态类中可能存在或不存在的属性值的同一逻辑也可以访问默认值,则必须提供专门用于此目的的方法,并依赖类的用户来调用该方法,而不是使用 null 合并运算符。例如,您可以编写obj.GetValueOrDefault("DemoProp", "Default value is assigned")而不是obj.DemoProp ?? "Default value is assigned",然后向Dynamico添加一个GetValueOrDefault方法,该方法可以执行您要执行的操作。 祝你好运。

最新更新