Handle an external API event from a method C# - c#

I'm using Advance Steel API for a library I'm creating and I need to somehow handle an event.
This is the class the API provides
public class OpenDatabase : IDisposable {
public OpenDatabase();
~OpenDatabase();
public UnitsSet Units { get; set; }
public Database CADDatabase { get; }
public ASObjectsAPI.OpenDatabase* Native { get; set; }
public IntPtr Internal { get; }
...
public event DatabaseEventHandler ObjectAppended;
...
...
public void objectAppended(Database db, CADAccess.FilerObject fo);
...
protected void raise_ObjectAppended(object value0, DatabaseEventArgs value1);
public delegate void DatabaseEventHandler(object source, DatabaseEventArgs args);
public delegate void IdMappingEventHandler(object source, IdMappingEventArgs args);
}
I need to handle the event ObjectAppended from another method. How should I proceed? I don't know how to work with events.
I guess the method I need to use is objectAppended(Database, CAD.Access.FilerObject) because I need to get that FilerObject.

If you take a look at this documentation, you'll learn how to subscribe to events like this:
public void SomeMethod() {
yourOpenDatabase.ObjectAppended += ObjAppendHandler;
}
public void ObjAppendHandler(Database db, CADAccess.FillerObject fo) {
//Insert code to handle your event...
}

Related

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 ?
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.

How to substitute an event-based class for an observable-based class in C# and System.Reactive?

I have a class which has some events. At present, I decide to shift towards "Observables" since the benefits they propose. To reach this goal, I introduced an Observable property to be replaced with one of the events. Next, I made the event "private" to restrict its accessibility from out of the class. The event is invoked inside the class with a function when it is needed. However, I think It may be a better way to do this job. What is the proper practice? By the way, I am a novice in "System.Reactive," so if I have a misunderstanding with the concept, please clarify the matter. My code is below:
public class MyClass
{
public MyClass()
{
InformationSenderObservable=Observable.FromEventPattern<SolutionEventArg>(ev =>InformationSender += ev, ev => InformationSender -= ev);
}
private event EventHandler<SolutionEventArg> InformationSender;
public IObservable<EventPattern<SolutionEventArg>> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
InformationSender?.Invoke(this,new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
}
Thanks to Theodor Zoulias, I finally understood how I could better handle my class. I used ISubject<T> instead of events in my class to send information from my class to another class subscribing to the ISubject<T>.
public class MyClass
{
public MyClass()
{
InformationSenderObservable=new Subject<SolutionEventArg>();
}
public ISubject<SolutionEventArg> InformationSenderObservable { get; }
internal void DoSomething()
{
// long calculation
SendInformation();
}
private void SendInformation()
{
try
{
InformationSenderObservable.OnNext(new SolutionEventArg()
{
InfoProxyData = GetDetailsForBestCompressedData(),
ParallelProcess = parallelProcessing
});
}
catch (Exception e)
{
InformationSenderObservable.OnError(e);
}
}
}
ISubject<T> implements both IObservable<T> and IObserver<T> simultaneously.

How to pass abstract method as reference?

I will admit, i am doing homework and i am stuck on this one question (Part A). How do i pass the notice method as reference to the railway signal ? Can't i just find out which class was called in the abstract constructor and then print the class name within the notify method? For example:
RailwayUser
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.Writeline(className);
}
RailwaySignal Class
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
This kind of code / design is flawed, since what it does is RailwayUser, registers the object reference with the _watchers List in the RailWaySignal class, which in turn calls the public Notice method on each user when Notify is invoked, which is not how Event Signaling or Function Pointer works. In fact public _watchers is dangerous, as it can be cleared by any user, though that can be moderated using property access
Code with Issue
public void Notify()
{
foreach(RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(State)
}
}
Following shall be the actual code using events and delegates:
Correct Version
Code Snippet Online - https://www.jdoodle.com/embed/v0/uEc
void Main()
{
List<RailwayUser> railwayUsers = new List<RailwayUser>();
railwayUsers.Add(new RailwayUser());
railwayUsers.Add(new RailwayUser());
RailwayUser.TestNotification();
}
public enum Colour
{
Red,
Green,
NoSignal
}
public class RailwaySignal
{
public string Name {get; set;}
public RailwaySignal(string railwaySignalName)
{
Name = railwaySignalName;
}
// Delegate for handling event
public delegate void RailwaySignalEventHandler(object source, Colour e);
// Delagate object for handling event
private RailwaySignalEventHandler _railwaySignalEvent;
// Event Accessor
public event RailwaySignalEventHandler RailwaySignalEvent
{
add
{
lock (this)
{
_railwaySignalEvent += value;
}
}
remove
{
lock (this)
{
_railwaySignalEvent -= value;
}
}
}
// Invoke Event for subscribed clients
private void Notify()
{
if (_railwaySignalEvent != null)
_railwaySignalEvent.Invoke(this, Colour.Green);
}
// Test the Event Invocation
public void TestEvent()
{
Notify();
}
}
public class RailwayUser
{
private static RailwaySignal railwaySignal { get; set;} = new RailwaySignal("Signal1");
public RailwayUser()
{
railwaySignal.RailwaySignalEvent += this.Notice;
}
public static void TestNotification()
{
railwaySignal.TestEvent();
}
public void Notice(object sender, Colour color)
{
Console.WriteLine($"Notice Called, Colour is :: {color}, Sender is :: {((RailwaySignal)sender).Name}");
}
}
Result
Notice Called, Colour is :: Green, Sender is :: Signal1
Notice Called, Colour is :: Green, Sender is :: Signal1
Important Details
Signature of the event is, (object source, Colour e) which helps in passing the relevant information across to the RailwayUser called, We now know the RailwaySignal triggering the notification to the RailwayUser and its Colour value
Event / Delegate has same signature as called method (which is the basis of working of Delegate / function pointers)
For simplification RailwayUser is a non abstract class
Event is executed using Notify() method inside the RailwaySignal, we are calling it artificially using TestNotification() inside RailwayUser just for demo purpose, but ideally it shall be internally triggered and shall pass on current state like Colour
Pre-defined delegates like Func, Action are quite often used for similar notification mechanism, They internally works using similar mechanism, though declaring an explicit event which is internally a delegate is a well defined pattern, especially for the Ui controls
Standard events exposed by the .Net framework have the signature object sender, EventArgs e, where EventArgs can wrap all information from Event executor (RailwaySignal) to Event receiver (RailwayUser)
It seem like a Observer pattern.You can pass SubClass which inherit from RailwayUser object instance into RailwaySignal class
Your RailwayUser class need create public abstract void Notice(Colour state) method.
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
Driver class can inherit RailwayUser class then override Notice method.
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine($"Driver see the {state.ToString()}");
}
}
There are
List<RailwayUser> _watches contain observable object
use SubScript(RailwayUser user) subscription user on _watches List.
RailwayUser Notify() to invoke all your observable Notify method.
look like this.
public class RailwaySignal
{
private List<RailwayUser> _watches;
public Colour Stata { get; set; }
public RailwaySignal()
{
_watches = new List<RailwayUser>();
}
public void SubScript(RailwayUser user)
{
_watches.Add(user);
}
public void Notify()
{
foreach (RailwayUser u in _watches)
{
u.PrintClassName();
u.Notice(Stata);
}
}
}
sample:https://dotnetfiddle.net/GcdGMy
You can also use event to pass method into RailwaySignal then invoke Notify method.
public enum Colour
{
Green,
Red,
Disable
}
public abstract class RailwayUser
{
private string className;
public RailwayUser()
{
Type type = this.GetType();
className = type.Name;
}
public void PrintClassName()
{
Console.WriteLine(className);
}
public abstract void Notice(Colour state);
}
public class Driver : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Driver see the "+ state.ToString());
}
}
public class Controller : RailwayUser
{
public override void Notice(Colour state)
{
Console.WriteLine("Controller see the " + state.ToString());
}
}
public class RailwaySignal
{
public delegate void NoticeEvent(Colour state);
public event NoticeEvent Notifys;
public Colour Stata { get; set; }
public void Notify()
{
if (Notifys != null)
{
Notifys(Stata);
}
}
}
use like this.
RailwaySignal railway = new RailwaySignal() { Stata = Colour.Green};
railway.Notifys += new Driver().Notice;
railway.Notifys += new Controller().Notice;
railway.Notify();
sample : https://dotnetfiddle.net/GcdGMy

Instantiating a delegate method to be used in a class library

I'm building an email-monitoring framework that I'll be using for a handful of users, so I'm building a class library to wrap everything in. I'm instantiating the configuration (sender, subject, last-received, ...) in a static class. Therefore, I have something like this.
public static class MyConfig
{
public static int Sender { get; set; }
// and so on and so forth
public static void BuildMyConfig(string theSender, string theRecipient, ...)
{
Sender = theSender;
// yada yada yada...
}
}
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Obviously, what we do with the email will be something completely different in each case. What I'm trying to is instantiate that delegate. Where would I do that? The MyConfig class and then invoke it from there as a static method? The instance of the Monitoring class?
An application would look like...
public class SpecificMonitor
{
Monitoring.BuildMyConfig("foo#bar.com", "bar#foo.com", ...);
Monitoring m = new Monitoring();
m.StartMonitoring();
//But where do I build the delegate method???
}
I've gotten compiling errors with every option I've tried so far. I've also tried overriding a method instead of using a delegate, using interfaces... but I think delegation is where it's at.
Thanks in advance!
Consistent with the rest of your design (although I do not necessarily agree that the design is great) you could allow for the callback to be set in the configuration class
public static class MyConfig
{
public static string Sender { get; set; }
public static DoSomethingWithEmail EmailReceivedCallback { get; set; }
public static void BuildMyConfig(string theSender, string theRecipient,
DoSomethingWithEmail callback)
{
Sender = theSender;
EmailReceivedCallback = callback;
}
}
// Make sure you bring the delegate outside of the Monitoring class!
public delegate void DoSomethingWithEmail(string theContents);
When an incoming email is acknowledged by your application you can now pass the email to the callback assigned to the configuration class
public class Monitoring
{
public void StartMonitoring()
{
const string receivedEmail = "New Answer on your SO Question!";
//Invoke the callback assigned to the config class
MyConfig.EmailReceivedCallback(receivedEmail);
}
}
Here is an example of usage
static void Main()
{
MyConfig.BuildMyConfig("...", "...", HandleEmail);
var monitoring = new Monitoring();
monitoring.StartMonitoring();
}
static void HandleEmail(string thecontents)
{
// Sample implementation
Console.WriteLine("Received Email: {0}",thecontents);
}
Define the constructor so that when people instantiate a Monitoring object, they must define the delegate:
public class Monitoring
{
public delegate void DoSomethingWithEmail(EmailContents theContents);
public Monitoring(Delegate DoSomethingWithEmail)
{
this.DoSomethingWithEmail = DoSomethingWithEmail;
}
public void StartMonitoring() {
//When I get an email, I call the method
DoSomethingWithEmail(theEmailWeJustGot);
}
}
Then pass in the delegate you want when you instantiate each Monitoring:
Monitoring m = new Monitoring(delegate(EmailContents theContents)
{
/* Do stuff with theContents here */
});
m.StartMonitoring();

Communication between ViewModels via events

I have an application where I open a new view (with viewmodel) within another viewmodel. The new Viewmodel needs some parameters from the caller viewmodel.
Now I introduced a class called Messenger which looks like:
public class Messenger
{
private static Messenger instance;
public static Messenger Instance
{
get { return instance ?? (instance = new Messenger()); }
}
private Messenger() { }
public void SendMessage(Message message)
{
OnMessageSent temp = MessageSent;
if (temp != null)
temp(message);
}
public delegate void OnMessageSent(Message message);
public event OnMessageSent MessageSent;
}
The message-class looks like:
public class Message
{
public Type TargetType { get; set; }
public object Sender { get; set; }
public Type ValueType { get; set; }
public object Value { get; set; }
public string AdditionalInfo { get; set; }
}
The usage of this building is:
The receiver-viewmodel of a message has to add
Messenger.Instance.MessageSent += MessageSent;
to it's constructor. And in the implementation can look like:
private void MessageSent(Message message)
{
if(message.TargetType == typeof(SecondViewModel))
{
if (message.ValueType == typeof (double))
{
this.MyValue= (double) message.Value;
}
}
}
This works fine. My question is: Is this a good way for the communication between viewmodels or are there any weakenings in this design?
You don't need to re-invent the wheel when its already there.
Use EventAggregator which internally uses weak event pattern to prevent any memory leaks. Refer to tutorials here and here.
Also you can use Event Aggregator with Reactive Extensions.
Refer to the post for viable approaches you can reuse - Even Aggregator Implementation Sample/Best Practices.

Categories

Resources