nabend
ich habe eine methode, der ich den type bzw T mitgeben muss
private bool BaseUpdateChangedObject<T>(object updateObject)
{
// usw...
}
in einer anderen methode möchte ich diese aufrufen, kann aber nur dynamisch eventuell und nich direkt das T angeben
public bool UpdateAllChangedObjects()
{
foreach (var obj in changedObjects)
{
BaseUpdateChangedObject</*?????*/>(obj);
}
return SubmitChanges();
}
nur ich weiß nicht die richtige variable bzw p0latzhalter für T zu finden..
kann mir da jemand weiterhelfen ?
Hallo Gepro,
wenn ich dich richtig verstanden habe, dann weisst du zur Laufzeit nicht genau welchen Typ du da mitgeben musst.
Und du willst dann also sowas wie einen Default-Typ mitgeben.
Dafür würde sich natürlich object eignen.
Gruss
Michael
das geht leider nicht, denn an der stelle streikt er und gibt mir nur ein Object zurück, und keine auflistung meiner Einträge in der Datenbank.
var dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
Hallo Gepro
Wie willst du einen Typ mitgeben, den du nicht kennst?
Bitte spezifiziere dein Problem / Aufgabe mal ein bisschen, sonst wird das schwierig.
Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011
in den changedObjects können objekte verschiedener klassen vorhanden sein, und um die datensätze mit hilfe des querys
var dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
erhalten zu können brauchte ich den Typ.
nur "object.GetType()" bringt mir nichts, so geht das nicht, es geht nur wenn ich in dem methodenkopf das <T> reinschreibe und es in der methode anwende.
private bool BaseUpdateChangedObject<T>(object updateObject) //where T : class
{
// usw...
var dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
// usw...
}
nur in dieser auflistung sind objekte verschiedener klassen drinne, also kann ich keinen speziellen typ angeben. um die methode dynamisch zu halten muss ich halt einen anderen weg finden...
public bool UpdateAllChangedObjects()
{
try
{ BaseUpdateChangedObject</*?*/>(changedObjects); }
catch (Exception) { return false; }
return SubmitChanges();
}
Hallo Gepro
Das geht so nicht, generische Typangaben müssen statisch sein, d.h. zur Compilezeit bekannt.
Du kannst sowas höchstens mit Reflection lösen, jedoch sehe ich da eher ein Designproblem als ein Problem mit der Technologie selber.
Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011
und wie soll ich das in diesem fall mit reflections lösen?
probier hier zwar rum, aber bekomm das nicht hin.
Hallo Gepro,
schreib doch bitte erstmal, warum du meinst, das zu brauchen. Peter Bucher hatte ja schon vermutet, dass das Design vielleicht nicht optimal ist. Dann wäre es ungünstig, Reflection zu nehmen.
herbivore
Reflection ist da glaubig nicht so der Hit.
nur in dieser auflistung sind objekte verschiedener klassen drinne, also kann ich keinen speziellen typ angeben
Welche Klassen sind enthalten? Deine Eigenen? Gibts (außer System.Object) eine gemeinsame BasisKlasse?
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
von mir eigen erstelle klassen und es gibt keine basisklasse!!
ich zeig einfach mal den ganzen quellcode, is vllt besser:
List<object> changedObjects = new List<object>();
public bool UpdateAllChangedObjects()
{
try
{
foreach(var obj changedObjects)
{
BaseUpdateChangedObject</*?*/>(obj);
}
}
catch (Exception) { return false; }
return SubmitChanges();
}
private bool BaseUpdateChangedObject<T>(object updateObject) //where T : class
{
try
{
// Tabelle des Objekts
MetaTable table = dbContext.Mapping.GetTable(updateObject.GetType());
// Identitäts-Eigenschaft, zum Erhalten des identischen Objekts aus der Datenbank
string key == ""
key = table.RowType.IdentityMembers[0].Name;
// Wert der Primärschlüssel-Eigenschaft
var value = updateObject.GetType().GetProperty(key).GetValue(updateObject, null);
// Identisches Datenbank Objekt erhalten
/*****************************************************************************/
string tablename = dbContext.Mapping.GetTable(updateObject.GetType()).TableName;
string command = "SELECT * FROM " + tablename + " WHERE (" + key + " = '" + value + "')";
var dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
// Werte gleich setzten
/*****************************************************************************/
foreach (PropertyInfo prop in dbObject.GetType().GetProperties())
{
object resultValue = prop.GetValue(updateObject, null);
// Wert ersetzen
dbObject.GetType().GetProperty(prop.Name).SetValue(dbObject, resultValue, null);
}
// Objekt in die Liste mit veränderten Objekten speichern (falls Key noch nicht vorhanden)
var countSameObject = (from o in changedObjects where o.GetType().GetProperty(key).GetValue(updateObject, null) == value select o).Count();
if(countSameObject ==0)
{ changedObjects.Add(dbObject); }
}
catch (Exception ex)
{
if (OnEditException != null) { OnEditException(ex, ChangeAction.Update); return false; }
}
return true;
}
das ganze mache ich wegen mehrfach benutzungen der datenbank, ich hab schon gute gründe das so zu machen, nur ich könnte jetzt alle objekte einzelnt, nach den typen speichern (UpdateAllChangedObjects)
zb so
UpdateAllChangedObjects<IrgendeineKlasse>();
UpdateAllChangedObjects<NocheineKlasse>();
möchte aber alles, auf einmal machen, ohne bei der methode einen typen angeben zu müssen!
Nimm (binäre) Serialisation, geht besser und es ist möglich, Klassen unterschiedlich zu speichern.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
@ eichhörnchen: ich möchte doch gar nichts speichern ?? versteh deine aussage total nicht , auch nicht mit dem binären serialisation
Hallo Gepro,
ich habe zwar im Moment kein VS2008 zur Hand, aber versuche einmal
var dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
durch
T dbObject = dbContext.ExecuteQuery<T>(command, new object[0]).First();
zu ersetzten.
Spo
Edit:
Welche Signatur hat dbContext.ExecuteQuery<T>?
dann muss ich doch trotzdem das T angeben und dieses möchte ich auch gar nicht aus der BaseUpdateChangedObject<T> herausnehmen, sondern folgenden "Platzhalter" oder so für den Typen wissen
public bool UpdateAllChangedObjects()
{
try
{
foreach(var obj changedObjects)
{
BaseUpdateChangedObject</*?*/>(obj);
}
}
catch (Exception) { return false; }
return SubmitChanges();
}
Bei Generics musst du einen Datentyp angeben und das schon zur Enwticklungszeit. Platzhalter oder sowas gibt es nicht.
Eine Möglichkeit (wurde bereits genannt), eine gemeinsame Basis-Klasse zu finden/entwerfen bzw. das ganze über ein Interface zu entkoppeln.
Es zwingt dich keiner Generics zu benutzen, besonders nicht, wenn es eine einfache Lösung ohne gibt.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
mhh..
ich muss zugeben, hört sich zwar nett an, mh doch ich verstehe nicht wirklich wie ich es nach deiner meinung umsetzten kann..
also basisklasse möchte ich auf jedenfall nicht verwenden, das auf keinen fall
Salute Gepro
also basisklasse möchte ich auf jedenfall nicht verwenden, das auf keinen fall
Dann spricht doch nichts gegen ein Interface?
Gruss Peter
--
Microsoft MVP - Visual Developer ASP / ASP.NET, Switzerland 2007 - 2011
und wie soll ich das interface aufbauen ?
habe grade leider keine ahnung..
eine hilfe wär nich schlecht
Abstrahieren!
Du hast eine handvoll Klassen, wo du mit allen das selbe machst (BaseUpdateChangedObject). Alle Eigenschaften und Funktionen, die BaseUpdateChangedObject braucht, lagerst du in eine seperates Interfaces aus.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...