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.
Keine Kommentare:
Kommentar veröffentlichen