1

私のクラスの現在の構造は、次のようになります。PC.Processor.Architecture [0] =最初のプロセッサのアーキテクチャ(マルチプロセッサシステムを想定)。

私が理想的に望んでいるのは、PC.Processor [0] .Architectureのようなものです。これは、この方法ではもう少し自明だからです。

私が持っているものでこれを行うためのかなり効率的な方法はありますか?プロセッサ、マザーボード、メモリなどの各クラスに9000を超えるプロパティがあり、WMI呼び出しはCPUで実行するのが安価ではないことに注意してください。

これが私のクラスの重要なスニペットです

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の両方(またはクラスが実際に何であれ)を利用する必要があります。

4

3 に答える 3

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);

同時に、実際に要求されたときにのみその情報を取得します。

于 2012-03-06T21:29:07.397 に答える
1

Processorクラスに単一のプロパティなどを持たせArchitecture、そのコンストラクターでインスタンスを取得してみませんか?次に、のコンストラクターで管理オブジェクトから必要なデータを取得し、オブジェクトに多数のを作成できます。CoresManagementObjectProcessorProcessorPC

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;
    }
}

編集

複数の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呼び出しのみを実行でき、使用されているプロパティの数に関係なく、一度だけ実行されるようになります。コンストラクターを組み合わせて、渡される管理オブジェクトをnullにすることができます。次に、ルックアップに使用されるインデックスと、コンストラクターで渡されなかったManagementObjectインスタンスを提供できますが、一部のManagementObjectsは自由に渡すことができます。それらが利用可能または安価である場合、これはプリロードされる可能性があります...

編集2

更新の処理に関しては、次回データにアクセスするときにAPiからの最新情報が要求されるように更新する必要があると仮定すると、次のようにするだけで済みます。

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

これは、次にSectorsが呼び出されたときに、既存のWMIObjectが置き換えられるため、WMIDataから値が再照会されることを意味します。

于 2012-03-06T21:26:27.747 に答える
0

回答してくださった皆様、ありがとうございました。私は自分のニーズに合った適度にエレガントなソリューションを考え出しました。

PCクラスの例:

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()メソッドの追加パラメーターとして一覧表示できます。

于 2012-03-07T19:06:57.773 に答える