繁体   English   中英

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

[英]Can I get the default value for a null value removal expression in C#?

给定dynamic object ,如果有一种方法可以在删除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";

我的问题是在Dynamic class定义的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" obj.DemoProp ?? "Default value is assigned" ,它是左侧操作数是隐式调用的评价Dynamico.TryGetMember ,并且在答案中讨论到这个问题 ,C#甚至不评估空合并运算符的右侧操作数( ?? )除非并且直到它确定左侧操作数为空。 因此, "Default value is assigned" - 或者您放置的任何表达式 - 都不能用于评估obj.DemoProp调用的方法,因为它的值尚未确定。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM