Laden...

Instanzname im Konstruktor ermitteln

Erstellt von Timo H vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.227 Views
T
Timo H Themenstarter:in
6 Beiträge seit 2007
vor 15 Jahren
Instanzname im Konstruktor ermitteln

Hallo,

gibt es eine Möglichkeit im Konstruktor einer Klasse den Namen seiner Instanz über Reflektion zu ermitteln?

In der Klasse, in der die Instanz angelegt ist, ist dies ja sehr einfach möglich.
Doch wie mache ich es im Konstruktor - wenn es überhaupt geht?

Gruß

Timo

Gelöschter Account
vor 15 Jahren

du meinst die variablenbezeichnung?

5.742 Beiträge seit 2007
vor 15 Jahren

Hallo Timo H,

so ganz verstehe ich dein Problem nicht. Welche Absicht verfolgst du denn?

Meinst du vielleicht den Namen des Typs?

Console.WriteLine(this.GetType().Name);
49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Timo H,

den Namen seiner Instanz

Instanzen haben keine Namen! Aber falls du den Namen der Variablen meinst, an die die neue Instanz zugewiesen werden wird: Nein, diesen Namen kannst du nicht herausfinden. Klingt aber ohnehin danach, als wäre nicht sinnvoll, was du da vorhast.

herbivore

T
Timo H Themenstarter:in
6 Beiträge seit 2007
vor 15 Jahren

Ja ich meine den Namen der Variablen.

Ich schreibe gerade eine Klasse, die die Settings für unsere HW-Testprogramme aus einer XML-Datei liest. Um das ganze pflegeleichter für meine Kollegen zu gestalten nutze ich Attribute und Reflection, um das Einlesen der Daten zu automatisieren.

Jede Variable der Klasse MinMax<> in der Klasse Settings, die das Attribute XmlConfigReadAttribute besitzt, wird mit dem Wert aus der XML-Datei gesetzt (in der Funktion SettingsBase.Load).
Alle Variablen mit dem Attribute XmlConfigShowAttribute werden in einer ListView angezeigt (in der Funktion SettingsBase.WriteSettingsToListView).

Im Moment lese ich die Attribute in der SettingsBase Klasse aus. Lieber wäre mir, dass die Klasse MinMax<> diese Daten schon bereitstellt. Ich kann natürlich auf die Attribute verzichten und die Daten der MinMax Klasse gleich über einen Konstruktor übergeben - ich finde allerdings die Wahl der Attribute übersichtlicher. Oder im Konstruktor der Settings Basisklasse mittels Reflektion die Daten den Variablen übergeben.

Hier Teile des Codes.


[AttributeUsage((AttributeTargets.Field | AttributeTargets.Property), AllowMultiple = false)]
class XmlConfigReadAttribute : Attribute
{
  private string path;
  private string node;

  /// <summary>
  /// Write the setting from the xml-file to this field or the set-property.
  /// </summary>
  /// <param name="path">Complete path to the node.</param>
  /// <param name="node">Name of the node.</param>
  public XmlConfigReadAttribute(string path, string node)
  {
    this.path = "/" + path.Trim(new char[] { ' ', '/' });
    this.node = node.Trim(new char[] { ' ', '/' });
  }

  public string Path
  {
    get { return path; }
  }
  public string Node
  {
    get { return node; }
  }
  public string FullName
  {
    get
    {
      return string.Format("{0}/{1}", path, node);
    }
  }
}

[AttributeUsage((AttributeTargets.Field | AttributeTargets.Property), AllowMultiple = false)]
class XmlConfigShowAttribute : Attribute
{
  private string name;
  private string group;

  public XmlConfigShowAttribute(string name)
  {
    this.name = name;
    group = string.Empty;
  }

  public XmlConfigShowAttribute()
  {
    name = string.Empty;
    group = string.Empty;
  }

  public string Name
  {
    get { return name; }
    set { name = value; }
  }
  public string Group
  {
    get { return group; }
    set { group = value; }
  }
}

public interface IReadFromXml
{
  bool ReadFromXmlNode(XmlNode node, string nodeName);
}

[TypeConverter(typeof(ExpandableObjectConverter))]
public class MinMax<T> : IReadFromXml where T : IConvertible
{
  private T min;
  private T max;

  private T minDefault;
  private T maxDefault;
  private bool useDefault;

  private bool valueMissing;
  private bool valueWrongFormat;
  private string errorMessage;

  public MinMax()
  {
    ResetStatus();

    useDefault = false;

    ////// Auslesen der XmlConfigReadAttribute und XmlConfigShowAttribute
  }

  public MinMax(T minValDefault, T maxValDefault)
    : this()
  {
    minDefault = minValDefault;
    maxDefault = maxValDefault;
    useDefault = true;
  }

  private void ResetStatus()
  {
    valueMissing = false;
    valueWrongFormat = false;
    errorMessage = String.Empty;
  }

  public override string ToString()
  {
    return String.Format("Min={0}, Max={1}", min.ToString(), max.ToString());
  }

  public bool ReadFromXmlNode(XmlNode node, string nodeName)
  {
    ResetStatus();

    string nodeValue;
    Type t = typeof(T);

    if (useDefault) {
      min = minDefault;
      max = maxDefault;
    }

    try {
      nodeValue = node.Attributes["Min"].Value;
    }
    catch {
      valueMissing = true;
      errorMessage = String.Format("Error in node {0}: Attribute \"Min\" not found!", nodeName);
      return false;
    }

    try {
      min = (T)System.Convert.ChangeType(nodeValue, t);
    }
    catch {
      valueWrongFormat = true;
      errorMessage = String.Format("Error in node {0}: Min value can't be converted into {1}!", nodeName, t);
      return false;
    }

    try {
      nodeValue = node.Attributes["Max"].Value;
    }
    catch {
      valueMissing = true;
      errorMessage = String.Format("Error in node {0}: Attribute \"Max\" not found!", nodeName);
      return false;
    }

    try {
      max = (T)System.Convert.ChangeType(nodeValue, t);
    }
    catch {
      valueWrongFormat = true;
      errorMessage = String.Format("Error in node {0}: Max value can't be converted into {1}!", nodeName, t);
      return false;
    }

    return true;
  }

  public T Min
  {
    get { return min; }
    private set { min = value; }
  }

  public T Max
  {
    get { return max; }
    private set { max = value; }
  }

  [Browsable(false)]
  public bool HasError
  {
    get { return (valueMissing || valueWrongFormat); }
  }

  [Browsable(false)]
  public bool ValueMissing
  {
    get { return valueMissing; }
  }

  [Browsable(false)]
  public bool ValueWrongFormat
  {
    get { return valueWrongFormat; }
  }

  [Browsable(false)]
  public string ErrorMessage
  {
    get { return errorMessage; }
  }
}

#pragma warning disable 0649
class Settings : SettingsBase
{

  #region Fields

  /************************************************************************/
  /************************************************************************/
  /************************************************************************/
  // XML content
  // Test limits
  [XmlConfigRead("/TesterConfig/TestLimits/CurrentConsumption", "CurrentForPosVolt_A")]
  [XmlConfigShow(Name = "Current For Pos Volt [A]", Group = "Limits")]
  public MinMax<float> currentForPosVolt_A = new MinMax<float>(0.0F, 0.0F);
  /************************************************************************/
  /************************************************************************/
  /************************************************************************/

  #endregion

  public Settings()
    : base()
  {
  }

  public override void CheckValues()
  {
    // Check the new values
  }
}
#pragma warning restore 0649


abstract class SettingsBase
{
  #region Fields

  private CultureInfo ciUSA = new CultureInfo("en-us");
  public string filename;

  private Object instanceObject = null;
  private Type instanceType = null;

  #endregion

  public SettingsBase()
  {
    instanceObject = this;
    instanceType = instanceObject.GetType();
  }

  // Methods

  /// <summary>
  /// Loads the setting from the xml-file.
  /// </summary>
  /// <param name="filename">Complete path with filename to the xml-File.</param>
  public void Load(string filename)
  {
    XmlDocument xmlDocument = new XmlDocument();
    XmlNode config;

    this.filename = filename;

    try {
      xmlDocument.Load(filename);
    }
    catch (Exception e) {
      throw new Exception("Error while loading XML-File: " + e.Message);
    }



    FieldInfo[] settingsFields = instanceType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    foreach (FieldInfo fi in settingsFields) {
      if (fi.IsDefined(typeof(XmlConfigReadAttribute), false)) {
        XmlConfigReadAttribute[] settingsAttr = (XmlConfigReadAttribute[])fi.GetCustomAttributes(typeof(XmlConfigReadAttribute), false);
        if ((fi.FieldType.Name == "MinMax`1") && (fi.FieldType.Namespace == "ComponentTest")) {
          try {
            config = xmlDocument.SelectSingleNode(settingsAttr[0].FullName);
          }
          catch {
            string errorMessage = String.Format("Error in node {0}: Node not found!", settingsAttr[0].FullName);
            throw new Exception(errorMessage);
          }
          /************************************************************************/
          /************************************************************************/
          /************************************************************************/
          IReadFromXml item = (IReadFromXml)fi.GetValue(instanceObject);
          item.ReadFromXmlNode(config, settingsAttr[0].FullName);
          /************************************************************************/
          /************************************************************************/
          /************************************************************************/
        }
      }
    }

    CheckValues();
  }


  /// <summary>
  /// Is called after reading the values from the XML-file.
  /// Override to check if the values are correct.
  /// </summary>
  public abstract void CheckValues();


  /// <summary>
  /// Shows all settings with the XmlConfigShowAttribute in a ListView.
  /// </summary>
  /// <param name="listView">Handle to the ListView.</param>
  public void WriteSettingsToListView(ListView listView)
  {
    listView.BeginUpdate();

    listView.Items.Clear();
    listView.Groups.Clear();
    listView.Columns.Clear();

    ColumnHeader columnHeader;
    columnHeader = new ColumnHeader();
    columnHeader.Text = "Property";
    listView.Columns.Add(columnHeader);
    columnHeader = new ColumnHeader();
    columnHeader.Text = "Value";
    listView.Columns.Add(columnHeader);


    Dictionary<String, ListViewGroup> lvgDict = new Dictionary<string, ListViewGroup>();
    ListViewGroup lvg;
    ListViewItem item;
    FieldInfo[] settingsFields = instanceType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    foreach (FieldInfo fi in settingsFields) {
      if (fi.IsDefined(typeof(XmlConfigShowAttribute), false)) {
        XmlConfigShowAttribute[] settingsAttr = (XmlConfigShowAttribute[])fi.GetCustomAttributes(typeof(XmlConfigShowAttribute), false);
        try {

          /************************************************************************/
          /************************************************************************/
          /************************************************************************/
          string itemName;
          if (string.IsNullOrEmpty(settingsAttr[0].Name)) {
            itemName = fi.Name;
          }
          else {
            itemName = settingsAttr[0].Name;
          }
          /************************************************************************/
          /************************************************************************/
          /************************************************************************/

          if (string.IsNullOrEmpty(settingsAttr[0].Group)) {
            item = new ListViewItem(itemName);
          }
          else {
            if (lvgDict.ContainsKey(settingsAttr[0].Group)) {
              lvg = lvgDict[settingsAttr[0].Group];
            }
            else {
              lvg = new ListViewGroup(settingsAttr[0].Group);
              lvgDict.Add(settingsAttr[0].Group, lvg);
              listView.Groups.Add(lvg);
            }

            item = new ListViewItem(itemName, lvg);
          }
          item.SubItems.Add(fi.GetValue(instanceObject).ToString());
          listView.Items.Add(item);
        }
        catch {
        }
      }
    }
    foreach (ColumnHeader header in listView.Columns) {
      header.Width = -1;
    }
    listView.EndUpdate();
  }
}

Diese Klassen sind noch nicht komplett und das Ganze soll um weitere Anzeigevarianten und Containerklassen wie MinMax<> erweitert werden.

Gelöschter Account
vor 15 Jahren

den variablennamen soll und darf man nciht benutzen.

T
Timo H Themenstarter:in
6 Beiträge seit 2007
vor 15 Jahren

Prinzipiell gebe ich Dir ja recht!

In diesem Fall soll der Variablenname im ListView verwendet werden, wenn kein anderer Name über XmlConfigShowAttribute definiert wurde. Es ist das gleiche Prinzip wie im PropertyGrid mit DisplayName.

O
778 Beiträge seit 2007
vor 15 Jahren

Man kann Variablennamen auslesen, der Reflector kann es ja auch, aber ich kenne keinen anderen Weg als den, den auch der Reflector geht: Ab in die Methode und dann das Byte-Array namens IL-Code auslesen. Viel Spaß dabei 🙂