動的キーワードを正しく使用するには、PlaindoObjectを手動で作成する必要がありますか?

StackOverflow https://stackoverflow.com/questions/14727807

  •  07-03-2022
  •  | 
  •  

質問

私は質問を見ていました RuntimeBinderExceptionを「動的」スローを使用してください. 。私は同様の問題に直面しています:

基本的に、既存のヘルパーの多くのHTMLargumentsパラメータにakinさんの動的引数を使用しているASP.NET MVCで "HTMLヘルパー"を作成します(以下のより多くのコード)。

public BootstrapCell(Action<string> emitContentAction, dynamic args)

意見:

@using (grid.Cell(ViewContext.Writer.Write, new {Position = 4}))
{
     <p>zomg!</p>
}

しかしながら、ナイーブアプローチでは、降ります RuntimeBinderException 私を投げ、それを宣言します 'object' does not contain a definition for 'Position', 、_args変数をデバッグしてホバリングするときは、それをはっきりしています does 位置特性を持っています。

発信者と着信者は別々のアセンブリにあります。なぜその問題が起こっているのですか?

(同じ質問に示されているという解決策が示されています。 ExpendoObjectを手動で作成します argsを保持するために)

実装:

public class Cell
{
    private readonly string _tagName;
    private dynamic _args;
    private Action<string> EmitContentAction;

    public BootstrapCell(Action<string> emitContentAction, dynamic args) : DisposableBaseClass
    {
        _args = args;
        EmitContentAction = emitContentAction;
        OnContextEnter();
    }

    protected void OnContextEnter()
    {
        var sb = new StringBuilder("<");
        sb.Append(_tagName);

        if (_args.Position > 0)
        {
            sb.Append(" class=\"offset");
            sb.Append(args.Position);
            sb.Append("\"");
        }

        sb.Append(">");

        EmitContentAction(sb.ToString());
    }
}

「明らかに」位置プロパティが設定されているときに問題が発生することを明確にするために編集されました。私は、財産が最初の場所で定義されたことがない場合、例外が発生する必要があります。

役に立ちましたか?

解決

そのコードは致命的に欠陥があります。

これ does そのプロパティを指定している限り、作業してください。

void Bar()
{
    Foo(new {Position = 0});
}

void Foo(dynamic args)
{
    Console.WriteLine(args.Position);
}

それは出力されます 0, 、Aを投げません RuntimeBinderException.

しかし、そのようなコードの目的は、呼び出し側が必要なプロパティだけを指定し、残りを省略する可能性です。
あなたはこの省略を介してチェックしようとしています if(args.Position != null). 。しかし、それはうまくいかない、それはすでに必要です Position 存在する。

パラメータの種類があることに気付くであろう匿名設定オブジェクトをサポートするASP.NETのルーティングAPIを参照している場合 object そして違います dynamic.
using object それ以外の dynamic APIをアセンブリ境界にわたって使用することができます。

それで、それはどのように機能しますか?

リンクされた答えのように、あなたは手動でプロパティの辞書を作成する必要があります。あなたが平野の古いものを使うかどうか Dictionary<string, object> またはAN ExpandoObject 好みの問題です。
using ExpandoObject あなたのコードを少し簡単に読み書きするのが簡単になりますが、必要ありません。


実際の例外についてあなたが取得しています:
見つけることができないことを伝えてください Position 財産 object. 。それが欠けていた匿名型になる場合 Position プロパティ例外メッセージは参照しません object しかし匿名のタイプに。このようなもの:

'<>f__AnonymousType0' 'Position'の定義を含まない

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top