2

我使用 ExpandoObject 类创建对象,我想对该对象执行 spring.net 表达式,但随后出现以下错误:

无法为指定的上下文 [System.Dynamic.ExpandoObject] 解析“名称”节点。

代码如下:

  dynamic expandObject = new ExpandoObject();
  expandObject.Name = "Los";
  var value = (string)ExpressionEvaluator.GetValue(expandObject, "Name");

我认为 spring 表达式不适用于动态对象,但也许你现在为什么会发生这种情况以及任何解决方法(我尝试在 IDictionary 列表上转换 ExpandoObject,然后执行 spring 表达式,但这不起作用)?

4

1 回答 1

4

我下载了 Spring.Net 源代码,我注意到的第一件事是 spring.net 核心库是在 .Net 框架 2.0 中制作的,因为当前版本(1.3.2)的 spring.net 不能与系统一起使用。 Dynamic.ExpandoObject(在 .net framework 4.0 中添加)。
正如我们现在的 System.Dynamic.ExpandoObject 是一个对象,其成员可以在运行时动态添加和删除,添加的属性和方法保存在 Dictionary 列表中。因此,我修改了 spring.net 核心的源代码以支持 System.Dynamic.ExpandoObject,现在一切正常。


我改变了什么?
1. 我将 Spring.Net 库升级到 .NET framework 4.0
2. 我修改了 Spring.Expressions.PropertyOrFieldNode 类中的 InitializeNode() 方法:

private void InitializeNode(object context)
    {
        Type contextType = (context == null || context is Type ? context as Type : context.GetType());

        if (accessor == null || accessor.RequiresRefresh(contextType))
        {
            memberName = this.getText();

            // clear cached member info if context type has changed (for example, when ASP.NET page is recompiled)
            if (accessor != null && accessor.RequiresRefresh(contextType))
            {
                accessor = null;
            }

            // initialize this node if necessary
            if (contextType != null && accessor == null)
            {//below is new IF;)
                if (contextType == typeof(System.Dynamic.ExpandoObject))
                {
                    accessor = new ExpandoObjectValueAccessor(memberName);
                }
                // try to initialize node as enum value first
                else if (contextType.IsEnum)
                {
                    try
                    {
                        accessor = new EnumValueAccessor(Enum.Parse(contextType, memberName, true));
                    }
                    catch (ArgumentException)
                    {
                        // ArgumentException will be thrown if specified member name is not a valid
                        // enum value for the context type. We should just ignore it and continue processing,
                        // because the specified member could be a property of a Type class (i.e. EnumType.FullName)
                    }
                }

                // then try to initialize node as property or field value
                if (accessor == null)
                {
                    // check the context type first
                    accessor = GetPropertyOrFieldAccessor(contextType, memberName, BINDING_FLAGS);

                    // if not found, probe the Type type
                    if (accessor == null && context is Type)
                    {
                        accessor = GetPropertyOrFieldAccessor(typeof(Type), memberName, BINDING_FLAGS);
                    }
                }
            }

            // if there is still no match, try to initialize node as type accessor
            if (accessor == null)
            {
                try
                {
                    accessor = new TypeValueAccessor(TypeResolutionUtils.ResolveType(memberName));
                }
                catch (TypeLoadException)
                {
                    if (context == null)
                    {
                        throw new NullValueInNestedPathException("Cannot initialize property or field node '" +
                                                                 memberName +
                                                                 "' because the specified context is null.");
                    }
                    else
                    {
                        throw new InvalidPropertyException(contextType, memberName,
                                                           "'" + memberName +
                                                           "' node cannot be resolved for the specified context [" +
                                                           context + "].");
                    }
                }
            }
        }
    }


2. 我添加了我的自定义 ExpandoObjectValueAccessor

private class ExpandoObjectValueAccessor : BaseValueAccessor
    {
        private string memberName;

        public ExpandoObjectValueAccessor(string memberName)
        {
            this.memberName = memberName;
        }

        public override object Get(object context)
        {
            var dictionary = context as IDictionary<string, object>;

            object value;
            if (dictionary.TryGetValue(memberName, out value))
            {
                return value;
            }
            throw new InvalidPropertyException(typeof(System.Dynamic.ExpandoObject), memberName,
                                               "'" + memberName +
                                               "' node cannot be resolved for the specified context [" +
                                               context + "].");
        }

        public override void Set(object context, object value)
        {
            throw new NotSupportedException("Cannot set the value of an expando object.");
        }
    }

编辑:当然,您不必将 spring.net 核心库升级到 .net framework 4.0 - 我这样做是因为我不喜欢通过魔术字符串来组合对象类型,我更喜欢使用 typeof()

于 2012-05-01T19:51:09.740 回答