Warum muss ich expandoobjekt manuell erstellen, um das dynamische Keyword richtig zu verwenden?

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

  •  07-03-2022
  •  | 
  •  

Frage

Ich habe die Frage angesehen Verwenden Sie 'Dynamic' werfen Sie eine Laufzeitbinderexception. Ich bin ein ähnliches Problem mitmachen:

Grundsätzlich möchte ich einen "HTML-Helfer" in ASP.NET MVC erstellen, der dynamische Argumente verwendet, die dem Parameter HTMlarguments für viele der vorhandenen Helfer (mehr Code unten) verwendet wird:

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

Sicht:

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

In der naiven Annäherung bekomme ich jedoch RuntimeBinderException auf mich geworfen und das erklären 'object' does not contain a definition for 'Position', obwohl beim Debuggen und Schweben der _ARGS-Variablen deutlich tut eine Positionseigenschaft haben.

Der Anrufer und die Callee befinden sich in separaten Baugruppen. Warum passiert dieses Problem?

(Die Lösung dafür wurde in derselben Frage gezeigt: Erstellen Sie manuell ein expandoobjekt die Args halten.)

Implementierung:

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

Bearbeitet, um klarer zu gestalten, dass mein Problem auftritt, wenn "offensichtlich" die Positionseigenschaft eingestellt ist. Ich bin mir bewusst, dass, wenn das Eigentum nie an erster Stelle definiert wurde, eine Ausnahme angehoben werden muss.

War es hilfreich?

Lösung

Dieser Code ist tödlich fehlerhaft.

Es tut Arbeit, solange Sie diese Eigenschaft angeben:

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

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

Das wird ausgegeben 0, wird es nicht werfen RuntimeBinderException.

Der Zweck eines solchen Codes ist jedoch die Möglichkeit, dass der Anrufer nur die erforderlichen Eigenschaften angeben und den Rest auslassen.
Sie versuchen, diese Auslassung über zu überprüfen if(args.Position != null). Das funktioniert aber nicht, es erfordert bereits Position existieren.

Wenn Sie einen Blick auf die Routing-API von ASP.NET haben, die auch diese anonymen Konfigurationsobjekte unterstützt, werden Sie feststellen, dass der Typ des Parameters ist object und nicht dynamic.
Verwendet object anstatt dynamic Aktiviert es Ihrer API, über Montagegrenzen verwendet zu werden.

Wie funktioniert es?

Wie in der verknüpften Antwort müssen Sie ein Wörterbuch der Eigenschaften manuell erstellen. Ob Sie ein einfaches altes verwenden Dictionary<string, object> oder an ExpandoObject ist eine Frage der Vorlieben.
Verwendet ExpandoObject Funktioniert Ihren Code ein bisschen einfacher, um zu lesen und zu schreiben, aber es ist nicht erforderlich.


Über die tatsächliche Ausnahme, die Sie erhalten:
Bitte beachten Sie, dass es Ihnen sagt, dass es nicht das finden kann Position Eigentum an object. Wenn es ein anonymer Typ wäre, der das fehlte Position Eigenschaft Die Ausnahmenachricht bezieht sich nicht auf object aber zu einem anonymen Typ. Etwas wie das:

'<>f__AnonymousType0' enthält keine Definition für 'Position'

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top