Object Name, Typ und Wert auslesen

andralin

Erfahrenes Mitglied
Hallo Leute,

vielleicht weis einer von Euch weiter.

Problemstellung auf ein denkbar einfachstes heruntergeschraubt.

Aufruf einer Methode mit folgender Syntax:
Code:
int xAlter = 29;
int xName = "Andralin";
trans("Hallo {xName}, Du bist {xAlter} Jahre", xName, xAlter)

und so die Methode mal grob geschildert
Code:
public void trans(string x, params Object[] myParams)
{
   
// so finde ich den übergebenen Typ
   string VarArt1 = myParams[0].GetType().Name;
     // also quasi 'String'

   string VarArt2 = myParams[1].GetType().Name;
    //oder hier 'Int32'

}

So finde ich zwar den übergebenen Typen, aber ich brauch den Namen der Varibalen/des Members der übergeben wurde.

Also für myParams[1] muss ich quasi xAlter bekommen
und für myParams[0] dann xName!

Wer weis wie ich daran komme.

LG Andralin

Hie rnoch einmal ein komplettes Beispiel-Projekt:
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace myProj
{
    class Program
    {

        static void Main(string[] args)
        {   
            string xName = "Andralin"; string xOrt = "zu Hause";            
            //statt dem hier: 
            Console.WriteLine(translate("Hallo {0}, Du bist jetzt {1}", xName, xOrt));

            // möchte ich so aufrufen
            //Console.WriteLine(translate("Hallo {xName}, Du bist jetzt {xOrt}", xName, xOrt));
            Console.WriteLine("Drück mal ne Taste");
            Console.ReadKey();

        }

        public static string translate(string x, params Object[] myParams)
        {

            // für die 2. Art auf zu rufen, benötige ich aber den namen der übergebenen Variablen
            // also tmp = myParams[nr].Name   / oder so was

            string tmpStr = x;
            int pos = tmpStr.IndexOf("{", 0);

            string xxx = myParams[0].GetType().Name;

            while (tmpStr.IndexOf("{") > -1)
            {
                int p1 = tmpStr.IndexOf("{");
                int p2 = tmpStr.IndexOf("}");
                string tmpX = tmpStr.Substring(p1, p2 - p1 + 1);
                tmpX = tmpX.Substring(1, tmpX.Length - 2);
                int tmp = Convert.ToInt32(tmpX);

                tmpStr = tmpStr.Substring(0, p1) + myParams[tmp] + tmpStr.Substring(p2 + 1);
            }

            return tmpStr;
        }
    }
}
 
Zuletzt bearbeitet:

Nico Graichen

Erfahrenes Mitglied
Hi

Versteh ich das richtig? Du willst die beiden Werte in den String einfügen?
Dann:
C#:
string xName = "Andralin"; 
string xOrt = "zu Hause";
string text = String.Format("Hallo {0}, Du bist jetzt {1}", xName, xOrt);
Console.WriteLine(text);
 

Kyoko

Erfahrenes Mitglied
Code:
string xName = "Andralin"; 
string xOrt = "zu Hause";
string text = String.Format("Hallo {0}, Du bist jetzt {1}", xName, xOrt);
Console.WriteLine(text);

Oder noch kürzer:

Code:
int xAlter = 29;
string xName = "Adralin";
Console.WriteLine("Hallo {0}, du bist {1} Jahre alt!", xName, xAlter);
 

andralin

Erfahrenes Mitglied
Ich möchte ähnlich einen String übergeben, in dem ich die Parameter schon als Platzhalter festlegen kann, aber nicht als %1, %2, etc sondern mit dem Object-Namen.

Beispiel:

string x; string y

so wäre das normalerweise
test("ausgabe {%1}, irgendwas {%2}", x, y)

so möchte ich das:
test("ausgabe {x}, irgendwas {y}", x, y)

es geht um eine Übersetzungsmöglichkeit wo ich parametrisierte Ausgaben übersetzen kann.

Die Methode wird nachher den komplette String inklusiver der Parameter-Positionen, aus einer Datenbank suchen und das anderssprachige Gegenstück raussuchen, dann die Parameter an der anderssprachigen Übersetzung setzen.

Zur besseren Wartbarkeit möchte ich aber anstatt der Platzhalter %1, %2, etc die Variablen-namen einsetzen, das man schon im String erkennt was für eine Art wert Textstellen enthalten werden, ... so kann auch wer das ganze warten, der nicht weis was für variablen eingesetzt werden. denn in der datenbank stehen nur die strings OHNE DIE VARS

also suche ich was das so funktioniert:
string tmpStr = "test"
Object test = tmpStr;
test.Name gibt es leider nicht, das sollte dann tmpStr ausgeben weil das der Name der Variable ist die in Object test geladen wurde.



Beispiel Deutsch:
alter = 20, name = andralin
"Hallo {name}, Du bist {%alter} Jahre alt", alter, name
Ausgabe:Hallo Andralin, Du bist 20 Jahre alt

oder englisch:
alter = 20, name = andralin
"Hi, your age is {alter} years, {name}", alter, name
Ausgabe: "Hi, your age is 20 years, Dirk", alter, name

Dabei möchte ich dynamisch bleiben, so das in der Datenbank folgendes steht

Deutsch: "Hallo {name}, Du bist {%alter} Jahre alt"
Englisch: "Hi, your age is {alter} years, {name}"

So brauche ich nur den String zu suchen, mit {} tags und lasse mir die Übersetzung ebenfalls mit den {} tags übergeben, kann die Tags auch mit [] machen oder mit anderen Zeichen,... Muss diese dann nur escapen wenn die im Text normal genutzt werden müssen.

Beispiel: "Hallo {name}, Du bist \{Sie sind\} {%alter} Jahre alt"
so würde er nur die { nutzen die ohne \ in der DB stehen.

Ich komme aber nicht weiter, weil ich den übergebenen Objectnamen nicht analysieren kann.

also translate(string text, params[])
nun muss ich nur den namen des jeweiligen über params[] übergebenen Parameters bekommen.

Beispiel:

translate("Hallo {name}, Du bist {%alter} Jahre alt", alter, name);

methode:
void translate(string text, params[])
{
string name = params[1].;

nun sollte ich irgendwie herausbekommen das daer Name für
params[0] = alter und für
params[1] = name ist.

dann kann ich im string die ausgabe dynamisch platzieren.
}
 
Zuletzt bearbeitet:

andralin

Erfahrenes Mitglied
Oder noch kürzer:

Code:
int xAlter = 29;
string xName = "Adralin";
Console.WriteLine("Hallo {0}, du bist {1} Jahre alt!", xName, xAlter);

OK, das ist der Standard, aber ich möchte ohne {%1} etc arbeiten sondern in den {} den tatsächlich genutzten namen sezten, sonst wird man in der Datenbank nicht wissen was das für Parameter sind.
 

Alexander Schuc

crazy-weasel
Hi.

Du könntest es über ein Dictionary lösen.. z.b. so:

C#:
using System.Collections.Generic;

public static string translate(string x, Dictionary<string, object> param)
{
  foreach (string key in param.Keys)
  {
    x = x.Replace(
      string.Format("{{0}}", x),
      param[key]
      );
  }
}



Dictionary<string, object> param = new Dictionary<string, object>();

param.Add("alter", 29);
param.Add("name", "Adranlin");

string muh = translate("Hallo {xName}, Du bist {xAlter} Jahre", param);
 

andralin

Erfahrenes Mitglied
Hi.

Du könntest es über ein Dictionary lösen.. z.b. so:...

so mit Dictionary und so....

Wow, schon mal ein erster sinnvoller Ansatz, den ich mal ins Auge fasse, ...
Aber noch umständlich, da ich hier jede Variable im Dic definieren muss. Also waartungsunfreundlich bei größeren Projekten. Ein String oder Integer haben imer einem Member Namen, den muss man doch auslesen können wenn man die als object gecastet hat, immerhin weis das system dann doch auch immer noch was es eigentlich ist.

Aber schon mal ein guter Ansatz, der vielleicht besser ist als in den Tabellen der Datenbank nachher noch jedesmal Kommentare pflegen zu müssen welche variablen das sind.

Hier mal ein Beispielprojekt wie ich das momentan löse. Die Sprachakten noch hardgecoded und mit wenig sinnvollen Texten.
Code:
using System;


namespace myProj
{
    class Program
    {
        static string[] germanCode = new string[0];
        static string[] englishCode = new string[0];
        static string[] spanischCode = new string[0];
        static string[] currentCode;
        static string[] standardCode;

        static void Main(string[] args)
        {
            setLanguageTables();
            standardCode = germanCode;
            currentCode = spanischCode;

            string xName = "Andralin";
            int xAge = 25;

            // an dieser Stelle möchte ich aber mit Namen statt mit den Indexen arbeiten
            trPrint("Mein Name ist {0} und ich bin {1} Jahre alt", xName, xAge);
            trPrint("und hier ein Text ohne Parameter");

            Console.WriteLine("Drück mal ne Taste");
            Console.ReadKey();
        }

        static void setLanguageTables()
        {
            addToTable(ref germanCode, "Mein Name ist {0} und ich bin {1} Jahre alt");
            addToTable(ref englishCode, "My Name is {0} and I am {1} years old");
            addToTable(ref spanischCode, "me llamo {0}, y soy {1} años");

            addToTable(ref germanCode, "und hier ein Text ohne Parameter");
            addToTable(ref englishCode, "and here a flat string without any options");
            addToTable(ref spanischCode, "aqui, una translatión que hay no parametres");

            addToTable(ref germanCode, "dritter");
            addToTable(ref englishCode, "third");
            addToTable(ref spanischCode, "tercero");

            addToTable(ref germanCode, "vierter");
            addToTable(ref englishCode, "fourth");
            addToTable(ref spanischCode, "cuarto");

            addToTable(ref germanCode, "letzter");
            addToTable(ref englishCode, "last one");
            addToTable(ref spanischCode, "por Último");
        }

        static void trPrint(string dText, params Object[] dParams)
        {
            string tmpStr = translate(dText, currentCode);

            while (tmpStr.IndexOf("{") > -1)
            {
                int p1 = tmpStr.IndexOf("{");
                int p2 = tmpStr.IndexOf("}");
                string tmpX = tmpStr.Substring(p1, p2 - p1 + 1);
                tmpX = tmpX.Substring(1, tmpX.Length - 2);
                int tmp = Convert.ToInt32(tmpX);

                tmpStr = tmpStr.Substring(0, p1) + dParams[tmp] + tmpStr.Substring(p2 + 1);
            }
            Console.WriteLine(tmpStr);
        }

        static string translate(string d_text, string[] d_table)
        {
            string RetVal = null;

            int i = 0;
            foreach (string s in standardCode)
            {
                if (s == d_text)
                    return d_table[i];
                i++;
            }

            throw new Exception("translation ERROR on " + d_text);
            //return d_text + "(translation ERROR)";
        }

        private static void trace(string p)
        {
            throw new NotImplementedException();
        }

        static void addToTable(ref string[] d_table, string d_text)
        {
            int fld_ctr = d_table.Length + 1;
            string[] tmp = new string[fld_ctr];
            if (fld_ctr == 1)
                tmp[0] = d_text;
            else
            {
                fld_ctr = 0;
                foreach (string text in d_table)
                {
                    tmp[fld_ctr] = d_table[fld_ctr];
                    fld_ctr++;
                }
                tmp[fld_ctr] = d_text;
            }
            d_table = tmp;
        }

    }
}

LG Andralin!
 

Kyoko

Erfahrenes Mitglied
Das wirst du ohne Liste oder ähnliches nicht hinbekommen.

Du willst der Methode immerhin den Namen der lokalen Variable übergeben, und dabei scheinst du was vergessen zu haben/nicht zu wissen: lokale Variablen haben eigentlich gar keinen Namen! Klar, sie haben für dich in C#/VB/whatever einen Namen, aber direkt in Intermediate Language gibt es eigentlich gar nicht sowas wie "lokale Variablen".

Sie sind unter .NET in einem speziellen Array, dem local variables array, abgespeichert. Gleiches trifft auf Paramter zu.

Hier gilt es natürlich wieder in Werte- und Referenztypen zu unterteilen, aber lassen wir das. Fakt ist, lokale Variablen haben keinen Namen!
 

andralin

Erfahrenes Mitglied
Das wirst du ohne Liste oder ähnliches nicht hinbekommen.

Du willst der Methode immerhin den Namen der lokalen Variable übergeben, und dabei scheinst du was vergessen zu haben/nicht zu wissen: lokale Variablen haben eigentlich gar keinen Namen! Klar, sie haben für dich in C#/VB/whatever einen Namen, aber direkt in Intermediate Language gibt es eigentlich gar nicht sowas wie "lokale Variablen".

Sie sind unter .NET in einem speziellen Array, dem local variables array, abgespeichert. Gleiches trifft auf Paramter zu.

Hier gilt es natürlich wieder in Werte- und Referenztypen zu unterteilen, aber lassen wir das. Fakt ist, lokale Variablen haben keinen Namen!

OK, das ist aufschlussreich und plaubibel... Dann muss ich mir nur noch einen sinnvollen Weg suchen wie das Warungsfreundlich bleibt. Danke Dir