Einige ODB++ Projekte können unterschiedliche Varianten als Komponenten haben. Ein einfacher Weg diese Varianten zu finden ist es, alle Attribute zu überprüfen und sie in einem Übersichtslexikon aufzulisten. Nachfolgend finden Sie den Code einer Klasse, die mit Varianten mit Hilfe von Strings umgeht. Sobald Sie eine Liste mit allen Varianten haben, ist es möglich die Variantennamen abzuspeichern und sie aus einer Datei zu laden. In dem unten stehenden Beispiel sind zwei Standardwerte enthalten.

Um die Varianten zu finden, müssen Sie CreateVariantList aufrufen, um das Übersichtslexikon mit allen Varianten zu erhalten. To find the variants, you have to call CreateVariantList and get the dictionary with all variants. Hier finden Sie die Lösungsdatei als ZIP: download

using PCBI.Automation;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
 
namespace PCBVariantReport
{
  public class VariantXMLClass
  {
    //list who contains all variant names
    public List<string> VariantenTable = new List<string>() { "VARIANT_INSTANCE", "comp_variant_list" };
 
    /// <summary>
    /// The list is saved as simple xml and its possible to load it with an XmlSerializer.
    /// </summary>
    /// <param name="fullpath">The file path + filename</param>
    /// <returns>ture if new list is loaded</returns>
    internal bool LoadList(string fullpath)
    {
      if (!File.Exists(fullpath))
        return false;
 
      XmlSerializer x = new XmlSerializer(typeof(VariantXMLClass));
      FileStream fs = null;
      try
      {
        using (fs = new FileStream(fullpath, FileMode.Open))
        {
          XmlReader reader = new XmlTextReader(fs);
          VariantXMLClass mainJobEntries = (VariantXMLClass)x.Deserialize(reader);
 
          //add the loaded names to the standards, this can be change to replace if standard values not interesting
          this.VariantenTable.AddRange( mainJobEntries.VariantenTable);
 
          fs.Close();
        }
        return true;
      }
      catch (Exception ex)
      {
        Console.WriteLine("Error wihle loading xml "+ex.ToString());
        if (fs != null) //get sure to close the files stream
          fs.Close();
 
        return false;
      }
    }
    /// <summary>
    /// Save custom setting of list, this is necessary if you have special attributes for variants.
    /// </summary>
    /// <param name="filename"></param>
    internal void SaveFileEntries(string filename)
    {
      try
      {
        XmlSerializer x = new XmlSerializer(typeof(VariantXMLClass));
        TextWriter writer = new StreamWriter(filename);
        x.Serialize(writer, this);
 
        writer.Close();
      }
      catch (Exception ex)
      {
        Console.WriteLine("Error while saving xml file " + ex.ToString());
      }
    }
    /// <summary>
    /// Check the complete step and sort variants in the list.
    /// </summary>
    /// <param name="parent">the current PCBI Window</param>
    /// <returns>a list of variants for both component layers</returns>
    internal Dictionary<string, VariantOverview> CreateVariantList(IPCBIWindow parent)
    {
      Dictionary<string, VariantOverview> PartList = new Dictionary<string, VariantOverview>();
      IStep step = parent.GetCurrentStep(); //can be changed for all steps
      if (step == null) return null;
 
      ICMPLayer topLayer = step.GetCMPLayer(true);
      ICMPLayer botLayer = step.GetCMPLayer(false);
      if (topLayer != null)
      {
        AddCMPsForOneLayer(PartList, topLayer);
      }
      if (botLayer != null)
      {
        AddCMPsForOneLayer(PartList, botLayer);
      }
      return PartList;
    }
    /// <summary>
    /// The actions for one cmp layer.
    /// </summary>
    /// <param name="PartList">List for variants</param>
    /// <param name="relCMPLayer">the relevant component layer</param>
    private void AddCMPsForOneLayer(Dictionary<string, VariantOverview> PartList, ICMPLayer relCMPLayer)
    {
      foreach (ICMPObject cmp in relCMPLayer.GetAllLayerObjects())
      {
        Hashtable attribs = cmp.GetComponentAttributeHashtable(); //get attributes
        bool added = false;
        foreach (string variant in VariantenTable)
        {
          if (attribs.ContainsKey(variant)) //check the variant is included?
          {
            #region variant element
            VariantOverview overview;
            if (!PartList.ContainsKey(variant))
            {
              overview = new VariantOverview();
              overview.Variant = variant;
              PartList.Add(variant, overview);
            }
            else
              overview = PartList[variant];
 
            //add to the correct list
            if (overview.VariantValueAndList.ContainsKey((string)attribs[variant]))
              overview.VariantValueAndList[(string)attribs[variant]].Add(cmp);
            else
              overview.VariantValueAndList.Add((string)attribs[variant], new List<ICMPObject>() { cmp });
 
            added = true; //maybe there is no variant
            #endregion
          }
        }
        if (!added) //all cmps without variant
        {
          #region no variant
          string noVariant = "no variant";
          if (!PartList.ContainsKey(noVariant))
            PartList.Add(noVariant, new VariantOverview() { Variant = noVariant });
 
          if (PartList[noVariant].VariantValueAndList.ContainsKey(noVariant))
            PartList[noVariant].VariantValueAndList[noVariant].Add(cmp);
          else
            PartList[noVariant].VariantValueAndList.Add(noVariant, new List<ICMPObject>() { cmp });
          #endregion
        }
      }
    }
    /// <summary>
    /// we have a simple class to sort the variants with lists
    /// </summary>
    internal class VariantOverview
    {
      public string Variant = "";
      public Dictionary<string, List<ICMPObject>> VariantValueAndList = new Dictionary<string, List<ICMPObject>>();
    }
  }
}