My goal is to pass an object to an event. The event has a given signature I can't change (so I can't define my own EventArgs). Specifically, I am talking about a passkey that is required for a Bluetooth pairing event, but the question is a general one. I subscribe to the event before starting the pairing procedure:
public async Task MyPairAsync(Device device)
{
var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(device.Id);
DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested = CustomPairing_PairingRequested;
var result = await customPairing.PairAsync(DevicePairingKinds.ProvidePin);
// Do more stuff (evaluate result etc.)...
}
The class "Device" contains the Id of the BLE device and the passkey:
public class Device
{
public ulong Id { get; }
public string Passkey { get; private set; }
public Device(ulong id, string passkey)
{
Id = id;
Passkey = passkey;
}
}
The signature of the PairingRequested event is fixed, so CustomPairing_PairingRequested needs to follow that signature:
private void CustomPairing_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
args.Accept(device.Passkey); // This doesn't work, since device is unknown in this context.
}
The class DevicePairingRequestedEventArgs is sealed, so I can't extend a class from it that could contain a Device instance.
How can I pass the Device object (and with it, the passkey information) to the CustomPairing_PairingRequested event? I could of course define a global Device variable, set it to the current Device object in MyPairAsync() and read it in the event, but that seems very ugly. Is there a better option to do this?
CodePudding user response:
What about wrapping all the publishing-subscribeing code along with the device
instance?..
Replace
customPairing.PairingRequested = CustomPairing_PairingRequested;
var result = await customPairing.PairAsync(DevicePairingKinds.ProvidePin);
// Do more stuff (evaluate result etc.)...
with
var prWrapper = new PairingRequestWrapper(device);
var result = await prWrapper.PairAsync(customPairing, () => {
// doing some stuff after `args.Accept(device.Passkey)`
});
// Do more stuff (evaluate result etc.)...
Where PairingRequestWrapper
is
public class PairingRequestWrapper{
private Device device;
public PairingRequestWrapper(Device d){
device = d;
}
private Action callbackAction;
// I mean, the result type
public async Task<Result> PairAsync(DeviceInformationCustomPairing customPairing, Action callbackAction = null){
this.callbackAction = callbackAction;
customPairing.PairingRequested = CustomPairing_PairingRequested;
return await customPairing.PairAsync(DevicePairingKinds.ProvidePin);
}
// no need to `CustomPairing_PairingRequested` in the original code.
private void CustomPairing_PairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
args.Accept(device.Passkey);
callbackAction?.Invoke();
}
}
CodePudding user response:
Have you tried to define extension method on event handler?
public static void RaiseEvent(this EventHandler @event, DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs e, Device device)
{
if (@event != null)
{
e.Accept(device.PassKey);
@event(sender, e);
}
}