C# EventHandler : How to handle EventHandler in client application? - c#

I have written a class library(dll) which handle Telephony calls. This class library has delegates that handle phone call events such as OnCallReceived, OnHoldCall etc.
So now i want to add this class library to my Windows Forms App, and be able to handle Phone Call events(OnCall, OnHolde etc) in my Windows Forms application. How can achieve this?
For example
//My Class Library
Class Test
{
ThirdParyLibrary tpl
public Test()
{
tpl= new tpl();
tpl.OnReceiveCall += Handler(OnReceiveCall);
}
public void OnReceiveCall()
{
//i want this event to take place in client app
}
}
//My Windows Forms App
Client App
public main()
{
Test t =new Test()
//i want OnReceiveCall to be processed here
//t.OnReceiveCall
{
Message.Show('You received a call');
}
}

// i want this event to take place in client app
Since you want the Event Handling mechanism to take place in the Client App, which I suppose is another Class containing Main, I have created a small console that replicates the problem scenario
Uploaded to fiddle as well
using System;
namespace Test
{
public class ThirdPartyLibrary
{
public delegate void dEeventRaiser();
public event dEeventRaiser OnReceiveCall;
public string IncomingCall(int x)
{
if (x > 0 && OnReceiveCall != null)
{ OnReceiveCall(); return "Valid "+x.ToString(); }
return "Invalid"+x.ToString();
}
}
public class EventSubscription
{
public EventSubscription()
{
ThirdPartyLibrary a = new ThirdPartyLibrary();
a.OnReceiveCall += HandleTheCall;
var iAnswer = a.IncomingCall(24198724);
Console.WriteLine("Call received from "+iAnswer);
}
public virtual void HandleTheCall()
{
Console.WriteLine("Default way I handle the call");
}
}
public class Program : EventSubscription
{
public override void HandleTheCall()
{
Console.WriteLine("Override sucessful, new way to handle the call ");
}
static void Main(string [] args)
{
Program pb = new Program(); // Control goes EnventSubscription constructor as it is derived
Console.Read();
}
}
}
Output:

Related

How to make possible to listen to another App song/audio

I am leaning Xamarin,
I have build a quick app that read audio effect file (mp3/wav).
My problem :
When I start the App while I was listened music ( spotify/deezer ) the musique stops because the app has started.
So, I would like to be able to listen to music ( spotify/deezer ) and use my app.
My audio C# class in Android looks like this :
public class MyAudioOutput : IAudioServiceOutput
{
public void GetAudioSetting()
{
var audioManager = (Android.Media.AudioManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.AudioService);
audioManager.Mode = Mode.Normal;
audioManager.SpeakerphoneOn = true;
}
}
My Audio C# classe in IOS looks like this :
public class MyAudioOutput : IAudioServiceOutput
{
public void GetAudioSetting()
{
var session = AVAudioSession.SharedInstance();
session.OverrideOutputAudioPort(AVAudioSessionPortOverride.Speaker, out NSError error);
session.SetCategory(AVAudioSessionCategory.Playback);
session.SetActive(true);
}
}
My interface in Xamarin Forms shared :
public interface IAudioServiceOutput
{
void GetAudioSetting();
}
In my Xamarin forms cs file , I use the function this way :
ISimpleAudioPlayer AudioPlayerGood;
void InitMyAudio()
{
string filenamegood = "Question.Good_Answer.mp3";
using (Stream streamGood = GetType().GetTypeInfo().Assembly.GetManifestResourceStream(filenamegood))
{
AudioPlayerGood = CrossSimpleAudioPlayer.CreateSimpleAudioPlayer();
AudioPlayerGood.Load(streamGood);
}
}
void OnPlayAnswerSong(bool goodanswer)
{
if (goodanswer == true)
{
AudioPlayerGood.Play();
}
else if (goodanswer == false)
{
AudioPlayerWrong.Play();
}
}
Thanks for you help
For this, you can refer to the following thread:Pause background service in Xamarin.Forms
The implementation on android platform is as follows:
[assembly: Dependency(typeof(StopMusicService))]
namespace TTSDemo.Droid
{
public class StopMusicService : IControl
{
AudioManager audioMan;
AudioManager.IOnAudioFocusChangeListener listener;
public void StopBackgroundMusic()
{
audioMan = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
listener = new MyAudioListener(this);
var ret = audioMan.RequestAudioFocus(listener, Stream.Music, AudioFocus.Gain);
}
}
internal class MyAudioListener :Java.Lang.Object, AudioManager.IOnAudioFocusChangeListener
{
private StopMusicService stopMusicService;
public MyAudioListener(StopMusicService stopMusicService)
{
this.stopMusicService = stopMusicService;
}
public void OnAudioFocusChange([GeneratedEnum] AudioFocus focusChange)
{
// throw new NotImplementedException();
}
}
}
And you can also check the updated part code by Nieminen included in above link.

Windows Workflow: Getting variable from WorkflowApplication

I'm using the Windows Workflow Foundation (WWF). I made an Activity (XAML) with one Sequence in which I defined a variable.
I run the activity in the console application by creating an instance of WorkflowApplication. How can I get the value of a variable in my console application?
I persist an instance of WorkflowApplication in XML and in it I saw my variable and its value. Is there any correct way to get the value of a variable from XML?
So in your last comment you stated you want to get the state in the console application before the workflow is completed. Unfortunately In/Out and Out arguments are only available upon completion of the workflow. But there are ways to communicate with the host process using other constructs than workflow variables and arguments.
One of the ways to do that is to use a custom extension that can be used to interact with the host process. An extensions can be of any type and is available to the workflow and the host process. A complete example:
using System;
using System.Activities;
namespace WorkflowDemo
{
class Program
{
static void Main(string[] args)
{
var app = new WorkflowApplication(new MyCustomActivity());
var myExtension = new MyCommunicationExtension();
myExtension.MyValueChanged += (s, e) => Console.WriteLine(myExtension.MyValue);
app.Extensions.Add(myExtension);
app.Run();
Console.ReadKey();
}
}
public class MyCommunicationExtension
{
public string MyValue { get; private set; }
public event EventHandler<EventArgs> MyValueChanged;
public void OnMyValueChanged(string value)
{
MyValue = value;
MyValueChanged?.Invoke(this, EventArgs.Empty);
}
}
public class MyCustomActivity : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
var extensionObj = context.GetExtension<MyCommunicationExtension>();
if (extensionObj != null)
{
extensionObj.OnMyValueChanged("Hello World");
}
}
}
}

Access statusbar on form from cplex callback function c#

I'm working with an C# .Net application that uses Cplex DLL's for an optimization operation, and during that operation I want to write status progress to a statusbar on the that initiated the operation.
This is the general layout of the specific form;
namespace ActResMain
{
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//...
cplex.Use(new Cplex_ContinuousCallback());
cplex.Solve()
}
public void Update_OptimizeStatusbarPanel(String strText)
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
//From here I want to edit the statusbar at FormOptimize. I can write progress to console without any problems, but cannot reach function "Update_OptimizeStatusbarPanel".
//If I include "FormOptimize formOpt = new FormOptimize" here, i get Visual studio exception on illegal window reference.
}
}
}
}
I have also tried invoking the Update_OptimizeStatusbarPanel function like this:
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize formOpt = new FormOptimize();
public override void Main()
{
FormCollection fc = Application.OpenForms;
var mpc = fc[1];
Type type = mpc.GetType();
MethodInfo dynMethod = type.GetMethod("Update_OptimizeStatusbarPanel");
dynMethod.Invoke(mpc, new object[] { String.Format("Running Optimization: {0} iterations ", Niterations)});
}
}
But then I get an exception from visual studio stating that an object created by one thread cannot be modified from another thread.
Maybe this is something stupid that I have missed, but help is greatly appriciated
EDIT: I edited the code as per Mohammad Dehghans suggestion,
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
cplex.Use(new Cplex_ContinuousCallback(this));
cplex.Solve()
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
if (Niterations % 10 == 0)
{
_formOptimize.Update_OptimizeStatusbarPanel(0, String.Format("Running Optimization: {0} iterations ", Niterations), 0);
}
}
}
public void Update_OptimizeStatusbarPanel(short panelIndex, String strText, short severity)
{
if (statusBar1.InvokeRequired)
statusBar1.Invoke(new Action<short, string, short>(Update_OptimizeStatusbarPanel), panelIndex, strText, severity);
else
{
if (panelIndex == 0)
{
//...
statusBarPanel_0.Text = strText;
}
else if (panelIndex == 1)
{
//...
statusBarPanel_1.Text = strText;
}
statusBar1.Refresh();
}
}
}
But by doing that I apparently broke something, as the application just ..stops after statusBar1.Invoke() is called the first time. If I pause the debugger it says that cplex.Solve() is executing, but then nothing more happens.
First of all, you need to pass the instance of your form to the implemented callback class, so when the Main method is called, you have access to the exact instance that is being shown on the screen.
Secondly, you need to use Invoke method to update the UI controls from anther thread (I've not worked with CPLEX so far, but I guess the callback is invoked from another thread. That's usual).
Read this for more information.
The complete code could be:
public class FormOptimize : System.Windows.Forms.Form
{
private callCplex()
{
//Misc code
cplex.Use(new Cplex_ContinuousCallback(this)); // <-- passing `this`
cplex.Solve()
//Misc code
}
public void Update_OptimizeStatusbarPanel(String strText)
{
if (statusBarPanel_1.InvokeRequired)
statusBarPanel_1.Invoke(Action<string>(Update_OptimizeStatusbarPanel), strText);
else
{
statusBarPanel_1.Text = strText;
statusBar1.Refresh();
}
}
internal class Cplex_ContinuousCallback : Cplex.ContinuousCallback
{
FormOptimize _formOptimize;
public Cplex_ContinuousCallback(FormOptimize formOptimize)
{
this._formOptimize = formOptimize;
}
public override void Main()
{
//...
_formOptimize.Update_OptimizeStatusbarPanel(String.Format("Running Optimization: {0} iterations ", Niterations));
}
}
}

windows application Logging mechanism

I am developing a Windows Application. I am displaying log information in the main form. I want to add logging information from another class. Below is the code on a button click event:
private void button1_Click(object sender, EventArgs e)
{
IDAL dal = new LoadCaseDAL();
Result result = new Result();
dal.Load(result);
AddToLogger("test end");
}
AddtoLogger(){ }
AddtoLogger() and button click event are in main form.
In dal.Load(result) method I am calling this function. I want to add log information in this function to the main form using AddToLogger() method.
protected internal void LoadLCFiles(BoltDataset.LoadCaseDataTable dt)
{
List<string> files = Helper.GetFiles("Text Files|*.txt");
**//AddToLogger("Total files: " + files.Count().ToString());**
Task loadFilesTask = Task.Factory.StartNew(() =>
{
foreach (string filePath in files)
{
LoadLCTextFile(filePath, dt);
}
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
**//AddToLogger("Loading Failed");**
}
else if (t.IsCompleted)
{
**//AddToLogger("Loading Succesfull");**
}
});
}
How can I achieve this ? Kindly suggest.
You can put your logging function in a static class. That way it will be available everywhere in your code and does not need an object in order to execute it.
public static class Tools
{
public static void AddToLogger(string msg) { ... }
}
Now build a delegate that you call inside AddToLogger() everytime you add a message:
// Delegate for new log entries
public delegate void LogEntryAddedDelegate(string message);
public static LogEntryAddedDelegate LogEntryAdded { get; set; }
Then call it in your AddToLogger() function. So your static class should then look something like this:
public static class Tools
{
// Delegate for new log entries
public delegate void LogEntryAddedDelegate(string message);
public static LogEntryAddedDelegate LogEntryAdded { get; set; }
public static void AddToLogger(string msg)
{
// Do some stuff here
// Call the event
LogEntryAdded(msg);
}
}
Then you can hook to your event in your form like this:
// Registers your function to get called when a new log message is added
Tools.LogEntryAdded += new Tools.LogEntryAddedDelegate(NewLogAdded);
protected void NewLogAdded(string msg)
{
// Update your textbox
}
Then you can add new log messages like this:
Tools.AddToLogger("msg");
This way your function NewLogAdded() gets called every time you add a new message to the log.
Also you might want to take a look at logging frameworks. They make logging stuff much easier and you don't have to code it on your own.
A good logging library for .Net is log4net

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

Categories

Resources