0

Use 'dynamic' throw a RuntimeBinderExceptionという質問を見ていました。私は同様の問題に直面しています:

基本的に、動的引数を使用する ASP.NET MVC で "HTML ヘルパー" を作成したいと考えています。これは、多くの既存のヘルパーの htmlArguments パラメーターに似ています (詳細は以下のコード)。

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

意見:

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

ただし、素朴なアプローチでは、_args変数をデバッグしてホバリングすると、明らかにPositionプロパティがあるにもかかわらRuntimeBinderException、それを宣言して投げ出されます。'object' does not contain a definition for 'Position'

呼び出し元と呼び出し先は別のアセンブリにあります。なぜその問題が起こっているのですか?

(その解決策は、同じ質問に示されています:手動で ExpandoObject を作成して引数を保持します。)

実装:

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());
    }
}

[「明らかに」Positionプロパティが設定されているときに問題が発生することを明確にするために編集。プロパティが最初から定義されていない場合は、例外を発生させる必要があることを認識しています。]

4

1 に答える 1

3

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

そのプロパティを指定する限り、機能します

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

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

それは を出力します0が、 をスローしませんRuntimeBinderException

ただし、このようなコードの目的は、呼び出し元が必要なプロパティのみを指定し、残りを省略できるようにすることです。
経由でこの省略を確認しようとしていif(args.Position != null)ます。しかし、それは機能しません。すでにPosition存在する必要があります。

これらの匿名構成オブジェクトもサポートする ASP.NET のルーティング API を見ると、パラメーターの型が であり、 ではobjectないことがわかりますdynamic。の代わりに
使用すると、アセンブリの境界を越えて API を使用できるようになります。objectdynamic

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

リンクされた回答と同様に、プロパティの辞書を手動で作成する必要があります。普通の古いものを使用するか、古いものを使用するかDictionary<string, object>ExpandoObject好みの問題です。
を使用ExpandoObjectすると、コードの読み書きが少し簡単になりますが、必須ではありません。


取得している実際の例外について:でプロパティが
見つからないことを示していることに注意してください。プロパティが欠落している匿名型である場合、例外メッセージは参照せず、匿名型を参照します。このようなもの:PositionobjectPositionobject

'<>f__AnonymousType0'「位置」の定義が含まれていません

于 2013-02-06T11:26:07.487 に答える