2012-03-06 2 views
1

Текущая структура моих классов выглядит примерно так: PC.Processor.Architecture [0] = Архитектура первого процессора (предполагающая многопроцессорную систему).Свойства массива C# и структура классов

Как я в идеале хочу, чтобы это было больше: PC.Processor [0] .Архитектура, потому что это немного более понятно.

Есть ли достаточно эффективный способ сделать это с помощью того, что у меня есть? Имейте в виду, что более 9000 свойств в каждом из классов Процессоры, Материнская плата, Память и т. Д. И вызовы WMI не являются ЦП-дешевыми для запуска.

Вот важные фрагменты моих классов

class PC 
{ 
    public Processor Processor; 
    public Motherboard Motherboard; 

    // Constructor 
    public PC() 
    { 
     Processor = new Processor(); 
     Motherboard = new Motherboard(); 
    } 

    // Method to get all info sequentially 
    public void GetAllInfo() 
    { 
     Processor.GetInfo(); 
     Motherboard.GetInfo(); 
    } 
} 

class Processor 
{ 
    public string[] Architecture; 
    public string[] Availability; 
    public UInt16[] Cores; 

    public void GetInfo() 
    { 
     // Get WMI Information from custom process 
     // Returns as an array of ManagementObjects for each matched device (which is a bit like an array of dictionaries) 
     ManagementObject[] WMIData = DataRetriever.GetWMIData("Win32_Processor"); 
     try 
     { 
      for (int i = 1; i < WMIData.Length; i++) 
      { 
       this.Architecture[i] = (string)WMIData[i]["Architecture"]; 
       this.Availability[i] = (string)WMIData[i]["Availability"]; 
       this.Cores[i] = (UInt16)WMIData[i]["NumberOfCores"]; 
      } 
     } 
     catch (NullReferenceException e) 
     { 
      // To be implemented 
     } 
    } 
} 

КРОМЕ
Там может быть более чем один поисковый запрос WMI в классе. Например, HardDrive нужно использовать как Win32_PhysicalMedia и ATAPI_SmartData (или любой другой класс на самом деле.)

+1

Итак, один экземпляр класса Processor используется для представления N процессоров? Это похоже на проблему с дизайном. Позаботьтесь о том, чтобы объяснить это? Почему процессор не представляет собой один процессор? – Servy

+2

@sll, о чем вы говорите? Прежде всего, список поддерживается массивом. Во-вторых, бокс/unboxing не встречается со ссылочными типами. –

+0

В вашем классе ПК должна быть коллекция экземпляров Процессора, возможно, член под названием Процессоры (с s). Заполняйте свою коллекцию процессоров на ПК. Таким образом, вы можете достичь того, чего хотите: PC.Processors [0] .Cores – Tung

ответ

0

Спасибо всем, кто ответил. Я придумал достаточно элегантное решение, которое соответствует моим потребностям.

ПК Класс Пример:

public class PC 
{ 
    public List<Processor> Processor; 

    // Constructor 
    public PC() 
    { 
     this.Processor = new List<Processor>(); 
    } 

    // Method to get all info sequentially 
    public void GetAllInfo() 
    { 
     // These temporary stores fetch WMI data as ManagementObjects 
     // Most cases will only need one WMI class. 
     ManagementObject[] WMIDataTemp1; 
     ManagementObject[] WMIDataTemp2; 

     WMIDataTemp1 = DataRetriever.GetWMIData("Win32_Processor"); 
     foreach (ManagementObject Object in WMIDataTemp1) 
     { 
      this.Processor.Add(new Processor(Object)); 
     } 
    } 

    public void RefreshAll() 
    { 
     // Delete the lists and start again 
     // Another option would be to foreach through the list elements and initialise each object again. 
     this.Processor.Clear(); 
     GetAllInfo(); 
    } 

    public void RefreshVolatileData() 
    { 
     // Extra function that will do some cool stuff later. 
    } 
} 

Процессор класса Пример: Пример

public class Processor 
{ 
    // Define properties 
    public string Architecture = "N/A"; 
    public string Availability = "N/A"; 
    public UInt32 CacheL2 = 0; 
    public UInt32 CacheL3 = 0; 

    // Overloaded constructor method 
    // The one with no arguments does nothing to initialise the class 
    // The one with the ManagementObject argument will call GetInfo to arrange the held data into the properties above 
    public Processor() { } 
    public Processor(ManagementObject wmiProcessor) 
    { 
     this.GetInfo(wmiProcessor); 
    } 

    // The main information handler for the classes. 
    // This splits out the data in the ManagementObject into the class's own properties 
    public void GetInfo(ManagementObject wmiProcessor) 
    { 
     // If anything fails, the try loop will just end without making a fuss 
     // Because of the default values, N/A will be displayed everywhere if something fails here. 
     try 
     { 
      this.Architecture = (string)wmiProcessor["Architecture"]; 
      this.Availability = (string)wmiProcessor["Availability"]; 
      this.CacheL2 = (UInt32)wmiProcessor["L2CacheSize"]; 
      this.CacheL3 = (UInt32)wmiProcessor["L3CacheSize"]; 
     } 
     catch (Exception e) 
     { 

     } 
    } 
} 

Использование:

public PC Computer = new PC(); 
Computer.GetAllInfo(); 
textbox1.Text = Computer.Processor[0].Architecture 

В случае, если устройство должно запрашивать более одного класса WMI, каждый дополнительный класс может быть указан как дополнительный параметр в конструкторе устройства и методе GetInfo().

1

почему бы не сделать Processor класс только одинарные свойства Architecture, Cores и т.д., и принять ManagementObject экземпляр в конструктор? вы можете вытащить необходимые данные из объекта управления в конструкторе Processor и просто создать много Processor s в вашем PC объекте.

class PC 
{ 
    //I'd encapsulate these in a property rather than a public field 
    public Processor[] Processors; 
    public Motherboard Motherboard; 

    // Constructor 
    public PC() 
    { 

     Motherboard = new Motherboard(); 
    } 

    // Method to get all info sequentially 
    public void GetAllInfo() 
    { 
     ManagementObject[] WMIData = DataRetriever.GetWMIData("Win32_Processor"); 
     Processors = new Processor[WMIData.Length-1]; 
     for (int i = 1; i < WMIData.Length; i++) 
      { 
      Processors[i-1] = new Processor(WMIData[i-1]); //assuming 0 based     
      } 

     Motherboard.GetInfo(); 
    } 
} 

class Processor 
{ 
    public string Architecture; 
    public string Availability; 
    public UInt16 Cores; 

    public Processor(ManagementObject WMIData) 
    { 
     this.Architecture = (string)WMIData["Architecture"]; 
     this.Availability = (string)WMIData["Availability"]; 
     this.Cores = (UInt16)WMIData["NumberOfCores"]; 
    } 
} 

, если вы беспокоитесь о производительности, то вы должны скрывать свои открытые поля позади свойств, а затем сделать вызовы лениво, как вам необходимо. Очевидно, что это компромисс между загрузкой данных по мере необходимости (что может быть связано с задержками во время доступа) или предварительной загрузкой всего этого (что может означать задержку с самого начала, но будет быстро, когда вам это нужно). Желаемый результат зависит от того, нужны ли вам все данные и как они будут использоваться.

вы можете сохранить объект WMIData в классе Processor и просто прочитать значения при доступе к свойствам. Это зависит от того, где медленные биты:

class Processor 
{ 
    private ManagementObject WMIData; 
    // obviously you might want to cache this value once it has been retrieved once 
    public string Architecture{get{return (string)WMIData["Architecture"];}} 
    public string Availability {get{return (string)WMIData["Availability"];}} 
    public UInt16 Cores{get{return (UInt16)WMIData["NumberOfCores"]}} 

    public Processor(ManagementObject WMIData) 
    { 
     this.WMIData = WMIData; 
    } 
} 

EDIT

, если вам нужно больше, чем 1 запрос WMI, а затем либо передать результаты каждого вызова WMI к объекту, чтобы он мог получить данные из них (звучит, как это будет медленно) или дать ему достаточно просто данные, поэтому он может сделать эти звонки, когда это необходимо:

class HardDrive 
{ 
    private int index; 
    private ManagmentObject physicalMediaInfo; 
    private ManagementObject smartDataInfo; 

    // choose one of these constructors. this one lets you delay all the WMI calls till you need to do them 
    public HardDrive(int index) 
    { 
     this.index=index; 
    } 

    //this one means you have to make the calls in advance 
    public HardDrive(ManagmentObject physicalMediaInfo,ManagementObject smartDataInfo) 
    { 
     this.physicalMediaInfo=physicalMediaInfo; 
     this.smartDataInfo=smartDataInfo; 
    } 

    private ManagementObject PhysicalMediaInfo 
    { 
     get 
     { 
      if(physicalMediaInfo==null) 
      { 
       ManagementObject[] WMIData = DataRetriever.GetWMIData("Win32_PhysicalMedia"); 
       physicalMediaInfo=WMIData[index]; 
      } 
      return physicalMediaInfo;   
     } 
    } 

    private ManagementObject SmartDataInfo 
    { 
     get 
     { 
      if(smartDataInfo==null) 
      { 
       ManagementObject[] WMIData = DataRetriever.GetWMIData("ATAPI_SmartData"); 
       smartDataInfo=WMIData[index]; 
      } 
      return smartDataInfo;   
     } 
    } 

    //property for getting the details of the hard disk 
    //uses the private property to ensure that the management object for the is only loaded when its needed 
    public int Sectors{get{return (int)PhysicalMediaInfo["Sectors"]};}; 

    //Same for the smart data. 
    public int SomeSmartData{get{return (int)SmartDataInfo["SomeSmartData"]};}; 

}

этот подход позволяет вам выполнять только каждый вызов api, поскольку требуется от него свойство, и гарантирует, что он выполняется один раз независимо от того, сколько его свойств используется. вы могли бы объединить конструкторы и разрешить объекты управления, которые были переданы, равными нулю, тогда вы могли бы предоставить индекс, который будет использоваться для поиска, и экземпляры ManagementObject, которые не были переданы вместе с конструктором, но оставляют вас свободными для передачи в некоторых ManagementObjects которые могут быть предварительно загружены, если они были доступны или дешево ...

EDIT 2

Что касается борьбы с обновлением, при условии, что обновления необходимо убедиться, что в следующий раз, данные доступ к последней информации от Апи испрашивается вы должны быть в состоянии просто сделать это:

public void Refresh() 
{ 
    this.physicalMediaInfo=null; 
    this.smartDataInfo=null; 
} 

Это означает, что в следующий раз, когда Sectors называется, значение «Sectors» будет повторно запрошено из WMIData, поскольку существующий WMIObject будет заменен.

+0

Ядра и доступность, возможно, не должны быть массивами. Я предполагаю, что ядра - это количество ядер, которые имеет процессор, а доступность - это наличие процессора – Tung

+0

@Tung, да скопируйте и вставьте ошибку :) спасибо. –

+0

Проблема с этой идеей заключается в том, что я не могу полностью заполнить информацию о процессоре только одним запросом WMI (как обновлено в дополнительной информации). Мне может потребоваться несколько данных запроса, чтобы успешно построить то, что мне нужно. Именно тогда производительность начинает снижаться.Разве есть способ слияния ManagementObjects? – CJxD

2

Вы, вероятно, следует делать эти вызовы лениво, например .:

class PC 
{ 
    public IEnumerable<Processor> Processors {get; private set;} 

    // Constructor 
    public PC() 
    { 
     Processors = new List<Processor>(); 
     for (var i = 0; i < GetProcessorCount(); i++) 
      Processors.Add(new Processor(i)); 
    } 
} 

class Processor 
{ 
    public int ProcessorIndex { get; private set; } 

    private String _architecture; 
    public string Architecture { 
     get { 
      // Return architecture if it's already been retrieved, 
      // otherwise retrieve it, store it, and return it. 
      return _architecture ?? (_architecture == getArchitecture(ProcessorIndex)); 
     } 
    } 
    public Processor(int processorIndex) { 
     ProcessorIndex = processorIndex; 
    } 
} 

Таким образом, вы получаете семантику вы хотите, например,

Console.Out.WriteLine(myPCInstance.Processors[0].Architecture); 

и в то же время вы только извлекаете эту информацию, когда ее действительно спрашивают.

+0

Я могу показаться идиотом, но с помощью вызова get {} для каждого свойства приведет к невероятно массивному коду. Можно ли это адаптировать, просто присваивая значения свойствам? – CJxD

+0

Зачем это нечитабельно? Вам понадобятся тысячи * кое-что * для тысяч свойств. Правильное использование дополнительных вложенных классов, алфавитного порядка и, возможно, регионов должно сделать это приемлемым, но не вникать в словарь и использовать строки, чтобы добраться до него, у вас просто будет много кода для тысяч свойств. –

+0

500 свойств x 1 строка каждая = 500 строк кода для просмотра; 500 свойств x 5 строк каждый = 2500 строк кода для просмотра. – CJxD

Смежные вопросы