why not make a Processor
class just have single properties Architecture
, Cores
etc and take a ManagementObject
instance in its constructor? you can then pull the required data from the management object in the constructor of the Processor
and just create many Processor
s in your PC
object.
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"];
}
}
if you are worried about performance then you should hide your public fields behind properties and then make the calls lazily as you need them. Obviously this is a trade off between loading the data when you need it (which might involve delays at the time of access) or preloading all of it, (which might mean a delay at the start but will be quick when you need it). The desired result is down to whether you always needs all the data and how it is going to be used.
you could store the WMIData object in the Processor class and just read the values when you access the properties. It depends on where the slow bits are:
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
if you need more than 1 WMI query, then either pass the results of each WMI call to the object so it can get the data from them (sounds like it'll be slow) or give it just enough data so it can make those calls when it needs to:
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"]};};
}
this approach allows you to only do each api call as a property from it is needed, and ensures that it is only done once regardless of how many properties from it are used. you could combine the constructors and allow the management objects passed in to be null, then you could provide the index which would be used to look up and ManagementObject instances which were not passed in with the constructor, but leave you free to pass in some ManagementObjects which could be preloaded if they were available or cheap...
EDIT 2
As for dealing with a refresh, assuming that refresh needs to ensure that next time data is accessed the latest info from the APi is requested you should be able to simply do this:
public void Refresh()
{
this.physicalMediaInfo=null;
this.smartDataInfo=null;
}
This will then mean that next time Sectors is called the "Sectors" value will be re-queried from the WMIData as the existing WMIObject will be replaced.