Come richiamare un metodo quando si accede alla classe (qualsiasi metodo) - "OnClassEnter"

0

Sto lavorando a un progetto di micro quadro C # net, in particolare una gestione / classe del bus I2C.

Ho diversi dispositivi I2C diversi definiti in classi separate che contengono tutti i metodi unici dei dispositivi. Nel mio caso, posso avere solo un I2CDevice oggetto "attivo" per comunicare con e per passare a un altro dispositivo I2C per comunicare con esso richiede una chiamata come I2CBus.Config = DeviceConfig1 .

Ad esempio (pseudo-codice):

Class Device1 
-DeviceConfig1
-Method 1
-Method 2
-Method 3

Class Device2
-DeviceConfig2
-Method 1
-Method 2
-Method 3


Main Program
{
I2cBus = new I2CDevice(configuration)
Device1.Method1
Device2.Method3
}

Quindi, da qualche parte tra Device1.Method1; e Device2.Method3; Quando si passa da un dispositivo all'altro, ho bisogno di cambiare la proprietà I2CDevice.Config. Lo chiamo un "evento OnClassEnter" che verificherebbe che le impostazioni del dispositivo siano corrette prima di procedere. Sto cercando un modo elegante in modo tale che ogni volta che chiamo un metodo per un dispositivo, che l'I2CBus.Config venga automaticamente controllato e modificato. C'è un modo in cui non ho bisogno di ri-digitare questo codice di configurazione in ogni metodo? Hai un metodo interno separato che viene chiamato ogni volta che accedo a uno di questi metodi? Forse qualcosa ereditato da una classe base o interfaccia, ma dove non devo ricordare chiamarlo da ogni metodo nella classe Device.

    
posta GisMofx 08.04.2014 - 20:02
fonte

2 risposte

2

Invece di tentare di catturare quando il controllo passa alla classe e aggiornare la configurazione, aggiornare la configurazione immediatamente prima che venga utilizzato il dispositivo I2CD.

Scrivi un wrapper per I2CDevice che prende DeviceConfig e I2CDevice come parametri per il suo costruttore.

Il wrapper può fornire le proprie versioni dei metodi I2CDevice (sembra che ce ne siano solo 3), quindi assicurerebbe la configurazione I2C prima di eseguire il corrispondente metodo I2CDevice .

Utilizzerai quindi questo wrapper all'interno delle tue classi Device1, Device2 invece di usare direttamente I2CDevice.

public class I2CDeviceWrapper 
{
   private readonly I2CDevice _i2cdevice;
   private readonly DeviceConfig _config;

   public I2CDeviceWrapper(DeviceConfig config, I2CDevice device)
   {
       _config = config;
       _i2cdevice= device;
   }
   private void EnsureConfiguration()
   {
       //verify or set configuration so this wrapper's device is active.
   }
   public int Execute(I2CTransaction[] xActions, int timeout)
   {
       EnsureConfiguration();
       return _i2cdevice.Execute(xActions, timeout);
   }
   public I2CReadTransaction CreateReadTransaction (byte[] buffer)
   {
        EnsureConfiguration();
        return _i2cdevice.CreateReadTransaction(buffer);
   }
   public I2CWriteTransaction CreateWriteTransaction (byte[] buffer)
   {
        EnsureConfiguration();
        return _i2cdevice.CreateWriteTransaction(buffer);
   }

}

EDIT: se il dispositivo I2CD viene passato nel wrapper, il wrapper non deve tentare di gestirne il ciclo di vita. I2CDevice fornisce un metodo Dispose (), nella mia esperienza (che non include il micro framework) indica che si rischia una perdita di risorse se non viene chiamata. Se questo vale per il micro framework, si vorrebbe fornire anche uno per il wrapper che chiami quello di I2CD.

Wrapper as Abstract Base:

Se utilizzi il wrapper come base per ciascuna delle tue classi Device1, Device2, la visibilità dei metodi Execute, I2CGetReadTransaction, I2CGetWriteTransaction e forse il campo _config dovrebbero essere protetti.

public class Device1: I2CDeviceWrapper
{
    public Device1(DeviceConfig config, I2CDevice device):base(config, device)
    {}

    public something Method1()
    {
        ... 
        Execute(...);
        ...
    }        
}

Wrapper come campo membro: Se il wrapper è un membro delle tue classi Device1, Device2, passerai comunque il tuo i2cBus come parametro a quei costruttori, creerai un wrapper A per Device usando la configurazione di quel dispositivo e i2cBus e poi usalo andando avanti come avresti usato in precedenza i2cBuss.

public class Device1
{
    private readonly I2CDeviceWrapper _i2cBus;

    public Device1(I2CDevice i2cBus)
    {
         var config = //set up configuration
         _i2cBus = new I2CDeviceWrapper(config, i2cBus);
    }
    public void Method1()
    {
        ...
        _i2cBus.Execute(...);
        ...
    }
}
    
risposta data 08.04.2014 - 20:52
fonte
1

Dichiarazione di non responsabilità: la mia esperienza con C # è probabilmente inferiore a 8 ore, pertanto la sintassi che segue potrebbe non essere accurata.

So, somewhere between Device1.Method1; and Device2.Method3; When switching between devices, I need to change the I2CDevice.Config property.

Puoi organizzarlo in modo che l'unico modo per ottenere un dispositivo sia attraverso un metodo come

public void With(DeviceConfig config, Action<Device> function) {
    // configure the hardware
    Device device = /* get the device */
    function(device);
}

In modo che tu possa fare questo:

With(device1Config, (device1) => {
    device1.Method1();
    device1.Method2();
    device1.Method3();
});
With(device2Config, (device2) => {
    device2.Method1();
    device3.Method2();
});

Ciò garantisce che non è possibile ottenere una sospensione di un dispositivo senza prima configurarlo, ma consentirebbe di effettuare più chiamate senza riconfigurazione.

    
risposta data 08.04.2014 - 20:36
fonte

Leggi altre domande sui tag