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

我可以在C#中获取空值删除表达式的默认值吗?,c#,expression,C#,Expression,给定动态对象,是否有方法在null值移除表达式中获取默认值?代码段可能如下所示: [Serializable] public class Dynamico : DynamicObject, IDictionary<string, object>, ICloneable, INotifyPropertyChanged, IXmlSerializable { private readonly IDictionary<string, object> _values =

给定
动态
对象
,是否有方法在
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);
    }
    ......
}

我的问题是在
Dynamic
类定义的
TryGetMember
方法中,如何获取默认值,即“分配了默认值”?解决方案可以使用表达式,任何好友都可以建议吗?

您可以尝试
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;
    }
}

这里有更多阅读:

这是不可能的,至少你现在使用的语法是不可能的。在表达式
obj.DemoProp??“默认值已赋值”
,它是对隐式调用
Dynamico.TryGetMember
的左手操作数的求值,并且正如在对的回答中所讨论的,C甚至不求值null合并运算符(
)的右手操作数,除非并直到它确定左手操作数为null。因此,
“默认值已分配”
-或者您放置在其位置的任何表达式的值都无法用于计算
obj.DemoProp
调用的方法,因为其值甚至尚未确定


如果您希望确定动态类上可能存在或可能不存在的属性值的同一逻辑段也可以访问默认值,那么您必须提供一个专门用于此目的的方法,并依靠类的用户调用该方法,而不是使用null合并操作符。例如,而不是
obj.DemoProp??“分配了默认值”
,您可以编写
obj.GetValueOrDefault(“DemoProp”,“分配了默认值”)
,然后向
Dynamico
添加一个
GetValueOrDefault
方法,该方法执行您尝试执行的任何操作。祝你好运。

谢谢大家,我之所以需要实现这一点,是因为我正在开发一个由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));
    }
System.Diagnostics.StackTrace st=新的System.Diagnostics.StackTrace();
var frames=st.GetFrames();
System.Diagnostics.StackFrame expfm=null;
for(int i=0;i对于(int i=offset;ia??b
a&&b
这样的表达式,期望如果
a
的值不需要计算,那么
b
将永远不会被计算。你想要的将使该期望失效N
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));
    }