GOOGLE ADS

Dienstag, 19. April 2022

Warum kann ich in anonymen C#-Typen keine Eigenschaften festlegen oder Attribute verwenden?

Anonyme C#-Typen scheinen wirklich nützlich zu sein, aber ich bin ziemlich schnell auf eine Anwendung gestoßen, in der ich die Eigenschaft eines anonymen Typs festlegen möchte, und ich möchte auch Attribute verwenden können.

My application is a general purpose stored procedure and SQL executor, which can automatically map C# properties to SQL input and output paramaters with appropriate SqlDbType (e.g. string maps to NVARCHAR(MAX), etc.).

z.B

 int PersonID = 1234;
var output = new { GivenName = (string)null, FamilyName = (string)null };
sqlExecutor.ExecSQL("SELECT @GivenName = GivenName, @FamilyName = FamilyName FROM People WHERE PersonID = @PersonID", new { PersonID }, output);
string GivenName = output.GivenName;
string FamilyName = output.FamilyName;

Der Ansatz funktioniert (auch für gespeicherte Prozeduren habe ich oben nur rohes SQL verwendet, um klarer zu machen, was ich versuche zu tun). Aber ich kann es nur in genau der obigen Form zum Laufen bringen, indem ich die „schlechte Idee" verwende, die Sicherungsfelder im anonymen Ausgabeobjekt festzulegen (unter Verwendung des Codes in der Antwort von Benutzer Alex auf How to set value for property of an anonymous Objekt? ).

Ich kann mir keine andere Möglichkeit vorstellen, eine so einfach zu bedienende, leichte Oberfläche für diese Art von Problem zu erstellen. Es ist ziemlich leicht zu sehen, dass Attribute auch hier nützlich sein könnten, zB um die Parameterzuordnung zu modifizieren.

Warum sind also anonyme Typen auf keine Einstellung und keine Attribute beschränkt? Diese scheinen beide in vernünftigen Anwendungsfällen nützlich zu sein, und als ob sie einfach zu integrierende Funktionen wären, da das grundlegende Merkmal des anonymen Typs bereits in der Sprache vorhanden ist.


Lösung des Problems

Wahrscheinlich könnten Sie sich hier in eine andere Lösung hacken, z. B. den generierten Code der anonymen Klasse / Instanz durch Umschreiben von Reflexionen ändern oder dynamische Dinge wie ExpandoObject und / oder Dictionary verwenden. Aber hier ist ein saubererer und einfacherer Weg – der „mit Ausdruck" – der eine „nicht-destruktive Mutation" bietet. Es behält den 'Typ' bei und erlaubt Ihnen trotzdem, das anonyme Objekt zu mutieren (eigentlich kopiert es alles in ein neues Objekt (wenn einige Ihrer anonymen Typstützen Referenztypen sind, wird eine Referenz kopiert).

Der with-Ausdruck wird nur für – insbesondere anonyme Typen – in C# 10 unterstützt, was.NET 6-Framework bedeutet. Die Lösung hier ist also nur für den neueren Lösungstyp verfügbar. Viele von uns stecken in.NET Framework 4.8 und so weiter in realen Lösungen bei der Arbeit mit Legacy-Code fest. Wenn Sie C# 10 und.NET 6 bei der Arbeit verwenden können, können Sie sich glücklich schätzen, da Sie einen mächtigeren Werkzeuggürtel zur Hand haben mit C#!

Ab C# 10 können Sie den with-Ausdruck für anonyme Typen (und Strukturen und ab C# 9 für Datensätze) verwenden.

Beispiel:

In Linqpad 7 einfügen: Dieser Code in einem C#-Programm und.NET auf Auto eingestellt

void Main()
{
var someInstanceOfAnonymousType = new {
Knight = "Sir Galahad",
FavoriteColor = "Blue. No RED!",
Shout = "Aaaargh!"
};

var mutatedInstanceOfAnonymousType = someInstanceOfAnonymousType with
{ Knight = "Sir Lancelot", Shout = "I did not vote for you!" };

mutatedInstanceOfAnonymousType.Dump();
}

Beachten Sie, dass der with-Operator Ihren anonymen Typ beibehält und es Ihnen dennoch ermöglicht, auf einfache Weise eine beliebige Anzahl von Unterstützungsfeldern zu ändern, die als schreibgeschützte Eigenschaften im anonymen Typ verfügbar gemacht werden. Geben Sie auf der rechten Seite einfach die Instanz ein, gefolgt von einem „with", gefolgt von den geschweiften Klammern und den Eigenschaften mit den Werten, die Sie festlegen möchten.

Mutating anonymous typed instance with with expression

Keine Kommentare:

Kommentar veröffentlichen

Warum werden SCHED_FIFO-Threads derselben physischen CPU zugewiesen, obwohl CPUs im Leerlauf verfügbar sind?

Lösung des Problems Wenn ich das richtig verstehe, versuchen Sie, SCHED_FIFO mit aktiviertem Hyperthreading ("HT") zu verwenden, ...