Laden...

[erledigt] Schleife, die ein bestimmtes Element aus einer Liste liefert, in Linq umsetzen

Erstellt von bigeddie vor 11 Jahren Letzter Beitrag vor 11 Jahren 1.037 Views
B
bigeddie Themenstarter:in
372 Beiträge seit 2007
vor 11 Jahren
[erledigt] Schleife, die ein bestimmtes Element aus einer Liste liefert, in Linq umsetzen

Hallo Gemeinde,

Wie kann ich folgenden Code mit LINQ umsetzen:


Type tmpType = tmpMapper.GetType();
            FieldInfo[] tmpFieldInfo = tmpType.BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);            
            foreach (var i in tmpFieldInfo)
            {
                try
                {
                    if (Attribute.IsDefined(((PropertyInfo)i.GetValue(tmpMapper)), typeof(PrimaryKeyAttribute)))
                    {
                        tmpProp = (PropertyInfo)i.GetValue(tmpMapper);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }

Mein bisheriger Ansatzen hat mich jetzt schon einige Tagen gekostet und lautet


PropertyInfo tmpProp = null;
            PropertyInfo q = (PropertyInfo)(from i in tmpFieldInfo
                    where Attribute.IsDefined(((PropertyInfo)i.GetValue(tmpMapper)), typeof(PrimaryKeyAttribute))
                    select i.GetValue(tmpMapper));

Compilieren läßt sich der Code, zur Laufzeit erhalte ich jedoch folgende Exception> Fehlermeldung:

InvalidCastException:
Das Objekt des Typs "WhereSelectArrayIterator`2[System.Reflection.FieldInfo,System.Object]" kann nicht in Typ "System.Reflection.PropertyInfo" umgewandelt werden.

Ich hoffe der Post ist in seiner Form richtig.

Viele Grüße

Jürgen

Man muß nichts wissen,
man muß nur wissen wer es wissen könnte
oder wo es steht😉

16.806 Beiträge seit 2008
vor 11 Jahren

Mittels Select in LINQ bekommst Du - wie bei SQL eben - nicht nur einen Datensatz, sondern eine Collection. Demzufolge kannst Du auch nicht einfach so in ein einfaches PropertyInfo casten.
Das sagt allein die Handhabung von LINQ wie auch die Fehlermeldung.
Siehe auch [Hinweis] Syntaxfehler selbst lösen (Compilerfehlermeldungen)

Tipp: manchmal ist es besser, wenn man nicht alles in eine Zeile quetschen will.

5.941 Beiträge seit 2005
vor 11 Jahren

Hallo bigeddie

Wenn man technisch noch nicht so weit ist, ist die Fehlermeldung nicht so sprechend.

Siehe: Enumerable.SingleOrDefault-Methode

Aber die Frage ist der Nutzen, wenn du das jetzt in LINQ umänderst und so viel Aufwand hast.

Ein kleiner Tipp wie du den oberen Code verbessern könntest.
Ich nehme an dass du nur ein PropertyInfo suchst, daher kannst du nach tmpProp = ...... ein break; platzieren, dann fliegst du aus der Schleife raus und hast dein Ergebnisse ohne weitere unnütze durchläufe.

Gruss Peter

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
bigeddie Themenstarter:in
372 Beiträge seit 2007
vor 11 Jahren

Hallo,

@Abt: Erstmal Danke für den Tip mit der IEnumerable<> als Ergebnis der LINQ.
Den RUNTIME-Error umgehe ich jetzt wie folgt:


 Type tmpType = tmpMapper.GetType();
            FieldInfo[] tmpFieldInfo = tmpType.BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
            FieldInfo[] scalarFields = (from i in tmpFieldInfo
                                        where !i.GetValue(tmpMapper).GetType().IsArray && !i.GetValue(tmpMapper).GetType().IsGenericType
                                            select i).ToArray<FieldInfo>();
            PropertyInfo tmpProp = null;
            tmpProp = (PropertyInfo)scalarFields[0].GetValue(tmpMapper);
            Assert.AreEqual(tmpProp.Name,"ID");

oder alternativ (da die Namen der privaten Member ja bekannt sind und mir das beim Schreiben der Antwort grade aufgefallen ist)


Type tmpType = tmpMapper.GetType();
            FieldInfo[] tmpFieldInfo = tmpType.BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
            FieldInfo[] scalarFields = (from i in tmpFieldInfo
                                        where i.Name == "primaryKeyProperty"
                                            select i).ToArray<FieldInfo>();
            PropertyInfo tmpProp = null;
            tmpProp = (PropertyInfo)scalarFields[0].GetValue(tmpMapper);
            Assert.AreEqual(tmpProp.Name,"ID");

@Peter Bucher:
Danke für den Tip mit dem "break;", daran habe ich nicht gedacht, da ich es eigentlich mit bei switches verwende.

Viele Grüße

Jürgen

Man muß nichts wissen,
man muß nur wissen wer es wissen könnte
oder wo es steht😉

5.941 Beiträge seit 2005
vor 11 Jahren

Hallo bigeddie

Wieso so kompliziert?


Type tmpType = tmpMapper.GetType();
FieldInfo[] tmpFieldInfo = tmpType.BaseType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

FieldInfo fieldInfo = tmpFieldInfo.Where(i => i.Name == "primaryKeyProperty").SingleOrDefault(); // Oder FirstOrDefault() für den ersten.

[...]

--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011

B
bigeddie Themenstarter:in
372 Beiträge seit 2007
vor 11 Jahren

Hallo Peter,

danke für den Tip mit der verkürzten Schreibweise.
Das vereinfacht das Schreiben deutlich.

Viele Grüße

Jürgen

Man muß nichts wissen,
man muß nur wissen wer es wissen könnte
oder wo es steht😉

742 Beiträge seit 2005
vor 11 Jahren

Geht noch kürzer:


FieldInfo fieldInfo = tmpFieldInfo.SingleOrDefault(i => i.Name == "primaryKeyProperty")