2

ExpandoObjectクラスを使用してオブジェクトを作成し、そのオブジェクトに対してspring.net式を実行したいのですが、次のエラーが発生しました。

「名前」ノードは、指定されたコンテキスト[System.Dynamic.ExpandoObject]に対して解決できません。

コードは次のようになります:

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

スプリング式は動的オブジェクトでは機能しないと思いますが、なぜそれが起こったのか、そして回避策があります(IDictionaryリストでExpandoObjectを変換してからスプリング式を実行しようとしましたが、これはweelとして機能しません)?

4

1 に答える 1

4

Spring.Netソースコードをダウンロードしました。最初に気付いたのは、現在のバージョン(1.3.2)のspring.netがSystemで動作できないため、spring.netコアライブラリが.NetFramework2.0で作成されていることです。 Dynamic.ExpandoObject(.net Framework 4.0に追加)。
System.Dynamic.ExpandoObjectは、実行時にメンバーを動的に追加および削除できるオブジェクトであるため、追加されたプロパティとメソッドはディクショナリリストに保持されます。そのため、Spring.netコアのソースコードを変更してSystem.Dynamic.ExpandoObjectをサポートし、すべてが完全に機能するようになりました。


私は何を変えましたか?
1.Spring.Netライブラリを.NETFramework4.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 に答える