Throw event thru classes
I have long process and sometimes I want to return process status. I have the following code:
public delegate Task DeviceOnSureMdmResetIMEIHandler(TabletWithoutDeviceIdDto sureMdmTablet, string oldIMEI);
public delegate Task LocalTabletGroupIsNotFoundHandler(TabletWithoutDeviceIdDto sureMdmTablet);
public delegate Task ExistingDeviceIsNotTabletHandler(Device device);
public delegate Task ErrorCombiningDevicesHandler(string result);
public interface ISureMdmTabletService
{
List<TabletWithoutDeviceIdDto> Tablets { get; set; }
event DeviceOnSureMdmResetIMEIHandler DeviceOnSureMdmResetIMEIEvent;
event LocalTabletGroupIsNotFoundHandler LocalTabletGroupIsNotFoundEvent;
event ExistingDeviceIsNotTabletHandler ExistingDeviceIsNotTabletEvent;
event ErrorCombiningDevicesHandler ErrorCombiningDevicesEvent;
List<string> DeviceIsChanged(TabletWithoutDeviceIdDto newItem, Device dbDevice);
string ImeiIsChanged(TabletWithoutDeviceIdDto newItem, Tablet dbTablet);
List<string> TabletIsChanged(TabletWithoutDeviceIdDto newItem, Tablet dbTablet);
bool ShouldPhoneNumberBeUpdated(TabletWithoutDeviceIdDto newItem, Device device);
bool ShouldICCIDBeUpdated(TabletWithoutDeviceIdDto newItem, Device device);
bool ShouldIMSIBeUpdated(TabletWithoutDeviceIdDto newItem, Device device);
void UpdateAlreadyExistingTablets();
void AddNewTablets();
void DeletedTablets();
Task DuplicateImeiRecordsAsync();
Task<UpdateTabletsFromSureMdmResultDto> UpdateTabletsSaveChangesAsync();
}
public class SureMdmTabletService : ISureMdmTabletService
{
public event DeviceOnSureMdmResetIMEIHandler DeviceOnSureMdmResetIMEIEvent;
public event LocalTabletGroupIsNotFoundHandler LocalTabletGroupIsNotFoundEvent;
public event ExistingDeviceIsNotTabletHandler ExistingDeviceIsNotTabletEvent;
public event ErrorCombiningDevicesHandler ErrorCombiningDevicesEvent;
private List<TabletWithoutDeviceIdDto> _tablets;
public List<TabletWithoutDeviceIdDto> Tablets
{
get
{
return _tablets;
}
set
{
_tablets = value;
}
}
private List<string> _tabletsIMEI { get; set; }
private List<string> _tabletsIds { get; set; }
private List<Tablet> _alreadyExistsTablets { get; set; }
private List<Tablet> _allTablets { get; set; }
private readonly ICombine2DevicesIntoOneService _combine2DevicesIntoOneService;
private readonly DataContext _dbContext;
private readonly IMapper _mapper;
private DeviceModel _deviceModel;
public SureMdmTabletService(DataContext dbContext, ICombine2DevicesIntoOneService combine2DevicesIntoOneService)
{
// .....
}
public List<string> DeviceIsChanged(TabletWithoutDeviceIdDto newItem, Device dbDevice)
{
// .....
}
public string ImeiIsChanged(TabletWithoutDeviceIdDto newItem, Tablet dbTablet)
{
// .....
}
public List<string> TabletIsChanged(TabletWithoutDeviceIdDto newItem, Tablet dbTablet)
{
// .....
}
// .....
public void UpdateAlreadyExistingTablets()
{
**DeviceOnSureMdmResetIMEIEvent.Invoke(...);**
}
}
and wrapper about it:
public interface ISureMdmTabletUpdateCommandService
{
Task<UpdateTabletsFromSureMdmResultDto> CommandAsync(List<TabletWithoutDeviceIdDto> tablets);
}
public class SureMdmTabletUpdateCommandService : ISureMdmTabletUpdateCommandService
{
private readonly ISureMdmTabletService _sureMdmTabletService;
public SureMdmTabletUpdateCommandService(ISureMdmTabletService sureMdmTabletService)
{
_sureMdmTabletService = sureMdmTabletService;
}
public async Task<UpdateTabletsFromSureMdmResultDto> CommandAsync(List<TabletWithoutDeviceIdDto> tablets)
{
_sureMdmTabletService.Tablets = tablets;
_sureMdmTabletService.UpdateAlreadyExistingTablets();
_sureMdmTabletService.AddNewTablets();
_sureMdmTabletService.DeletedTablets();
await _sureMdmTabletService.DuplicateImeiRecordsAsync();
return await _sureMdmTabletService.UpdateTabletsSaveChangesAsync();
}
}
this wrapper is used by client app:
var resultTablets = await _sureMdmTabletUpdateCommandService.CommandAsync(tablets);
I want to subscribe on events from client app like this:
_sureMdmTabletUpdateCommandService.DeviceOnSureMdmResetIMEIEvent +=
but ISureMdmTabletUpdateCommandService does not have, nested class has it. How to throw these events carefully and without dummy intermediate events inside ISureMdmTabletUpdateCommandService ?
Solution 1:
Having wrapper requires you to have all the infrastructure on it and you are not required to have full event there just a intermediate methods to attach and detach so you can do explicit event implementation:
object objectLock = new Object();
event DeviceOnSureMdmResetIMEIHandler DeviceOnSureMdmResetIMEIEvent
{
add
{
lock (objectLock)
{
_sureMdmTabletService.DeviceOnSureMdmResetIMEIEvent += value;
}
}
remove
{
lock (objectLock)
{
_sureMdmTabletService.DeviceOnSureMdmResetIMEIEvent -= value;
}
}
}
the lock is required as += and -= operations are not atomic its read modify write.
Having that sad I do not recommend using events at all. I would just passed as a parameter an Action<TabletWithoutDeviceIdDto, string>
not even declaring custom delegate for it. Its just simpler approach and it can event support asynchronous operation if you use Func<TabletWithoutDeviceIdDto, string, Task>
in contrast to events.