I usually try to encapsulate my web service calls in my client side apps.
Rather than doing this:
public Guid FindUserIDSelected(string userName)
{
MyWebServiceReference service = new MyWebServiceReference(GetEndpointBasedOnEnv(Env));
return service.GetUserIDFromName(userName);
}
I have a static class that encapsulates the communication with the web services. It handles the endpoint resolution via determining the environment (and other such things).
So the above code changes to look like this:
public Guid FindUserIDSelected(string userName)
{
return Communication.GetUserIDFromName(userName);
}
But now I am having an issue. Silverlight only supports Asynchronous calls (at least as far as I am seeing). So calling a web service and then returning the value in an encapsulated call does not work.
The best I can come up with is passing in a delegate that is used in the Communication class for the completed event:
private Guid foundUserID;
public void FindUserIDSelected(string userName)
{
Communication.GetUserIDFromName(userName, GetUserIDCompleted);
}
private void QuestionRecieved(object sender, GetUserIDFromNameCompletedEventArgs e)
{
foundUserID= e.Result();
}
This has several problems (in my opinion).
I now have elements of the web services that have broken encapsulation (the completed call is really the web service return. I don't want the rest of my classes to have to care about the services).
I have had to expose my result (foundUserID) at the class level.
Am I being too rigid? Is that good enough? Is there a better way?
Am I the only one who has this issue?
In my opinion, it'd better to use eventing from your communication class, especially if you have some thing like [EventAggregator]1, so you can filter an event based on your specific argument
Below is the code snippet, this may be helpful for you.
public static class Communication
{
public static event EventHandler<MyEventArgs> ServiceCallComplete;
public static void InvokeMyAcionComplete(MyEventArgs e)
{
EventHandler<MyEventArgs> handler = ServiceCallComplete;
if (handler != null) handler(null, e);
}
public static void CallService ()
{
//Performed async call
// Fire the event to notify listeners
OnServiceCalled();
}
private static void OnServiceCalled ()
{
InvokeMyAcionComplete(new MyEventArgs());
}
}
public class ClientCode
{
public void CallService()
{
Communication.CallService();
//Subscribe to the event and get notified when the call is complete
Communication.ServiceCallComplete += OnServiceCalled;
}
private void OnServiceCalled(object sender, MyEventArgs e)
{
//MyEventArgs is your customized event argument
//Do something with the result
}
}
Hope this help
Related
Is it possible to achieve in C++ similar behavior to that of events with custom arguments in C#?
I came across the following link:
https://www.tangiblesoftwaresolutions.com/articles/cplus_equivalent_to_csharp_events.html
Can that idea be applied to a situation where custom event args are used?
An example of C# code to be mimicked or implemented in C++ is below. For context, this is part of an (WinForms) application using the MVC architecture pattern.
// part of service layer of Model
// the View is subscribed to this class
public static class ModelService
{
// methods for using data access layer to interact with database...
// event for getting all customers
public static event EventHandler<GetAllCustomersEventArgs> OnGetAllCustomers = delegate { };
// custom event args
public class GetAllCustomersEventArgs : EventArgs
{
private List<Customer> customerList;
// ctor
public GetAllCustomersEventArgs(List<Customer> customerList)
{
this.customerList = customerList;
}
public List<Customer> getList()
{
return this.customerList;
}
}
}
// part of View
// subscribed to Model
public partial class ViewCustomersForm : Form
{
public ViewCustomersForm
{
// subscribe to the required Model events
CustomerOps.OnGetAllCustomers += new EventHandler<GetAllCustomersEventArgs>(customerEventHandler);
}
private void customerEventHandler(object sender, GetAllCustomersEventArgs e)
{
populateView(e.getList());
}
}
The idea is to implement this in a WxWidgets application in the future.
I understand that in C++, function pointers are equivalent to the use of delegates in C#. However, I am unfamiliar with the concept of function pointers, and seeking some guidance on how to use them in the context of what is desired to be achieved as described above, with perhaps some example code.
In my application I have a interface IEncoder that is having event EncoderCaller.
public interface IEncoder
{
event EncoderCaller EncoderCalled;
}
public delegate void EncoderCaller(object Source, EventArgs args);
public class Video
{
public string Title { get; set; }
}
public class VideoEventArgs : EventArgs
{
public Video xVideo { get; set; }
}
public class DetectionAction : IEncoder
{
public event EncoderCaller EncoderCalled;
public void Encode(Video video)
{
//some logic to encode video
OnVideoEncoded();
}
protected virtual void OnVideoEncoded()
{
if (EncoderCalled != null)
EncoderCalled(this, EventArgs.Empty);
}
}
public class Client1: IEncoder
{
}
I need some mechanism by which I should be able to share a contract, if that is implemented by any client then that event will trigger event in my class DetectionAction .
Can someone tell me, Am I doing right thing.
How it can be done?
If you have two classes in the same process, you could consider explicitly chain events like this:
public class Client1 : IEncoder
{
public event EncoderCaller EncoderCalled;
public Client1(IEncoder anotherEncoder)
{
// Listen to event raised on another instance and raise event on this instance.
anotherEncoder.EncoderCalled += OnAnotherEncoderCalled;
}
private void OnAnotherEncoderCalled(object source, EventArgs args)
{
if (EncoderCalled != null)
EncoderCalled(this, EventArgs.Empty);
}
}
In this case, for example, anotherEncoder is DetectionAction.
However, if you are seeking solution for sharing events between two different applications running in different processes, you might be looking at inter-process communication, like this post:
Listen for events in another application
And the above example code still works, but the IEncoder in this case is an implementation with IPC support, for example a message queue listener which raises the event on message received.
suppose we have this scenario :
a class that you are not allowed to modify anything in it :
public class ForbiddenClass_A
{
public void TheMethod()
{
//do stuff
}
}
and another read only class that calls a method from the previous class:
public class ForbiddenClass_B
{
ForbiddenClass_A fc_a;
void Update()
{
//some logic that if true it will call :
fc_a.TheMethod();
}
}
Now you have your class, that you do anything to it, and from it you want to know if TheMethod() :
public class MyClass
{
//call this when TheMethod() from ForbiddenClass_A is called.
public void TheMethod_Catcher()
{
}
}
Thank you!
Is there a way to catch a method call without subscribing it to any
sort of Events?
Decoupled messaging is probably where you want to be, event aggregator or any other pub sub method messaging system. Although you still have to subscribe to something, the participants need not know about each other allowing you to make the methods private.
Unity, MvvmLight both have these sorts of messaging systems, however they are truly dime-a-dozen, there are plenty
Example of how this might work
public CreateUserForm()
{
InitializeComponent();
EventPublisher.Instance.Subscribe<NewUserCreated>
(n => listBoxUsers.Items.Add(n.User.Name));
}
...
// some other class
private void Update()
{
var user = new User()
{
Name = textBoxUserName.Text,
Password = textBoxPassword.Text,
Email = textBoxEmail.Text
};
EventPublisher.Instance.Publish(new NewUserRequested(user));
}
Update
There are injection techniques if you are interest for .net
Dynamically replace the contents of a C# method?
i want to access static member which is located in WCF service.
public class PDFService : IPDFService
{
public string CreatePDF()
{ //some code
}
private static event EventHandler MyPrivateEvent;
public static event EventHandler MyEvent
{
add { MyPrivateEvent += value; }
remove { MyPrivateEvent -= value; }
}
}
I tried to access this MyEvent member from a Windows Store app, but it doesnt work.
I want to accomplish something like this (similar to example from msdn):
PDFServiceClient proxy = new PDFServiceClient();
//Wire the proxy to a completed handler to allow the async operation to be handled
proxy.MyEvent += new EventHandler<CreatePDFCompletedEventArgs>(
proxy_CreatePDFCompleted);
//Call the service asynchronously
await proxy.CreatePDFAsync();
Events are not exposed to the consumer of a WCF service. Neither are static members at all. The only things exposed are the operations in the service contracts, and any types used by those operations.
This question might be design related or code related, but I'm stuck so I'm open to any kind of answer; a pointer in the right way!
I have used MEF (Managed Extensibility Framework) to develop a piece of WPF software that will act as a form of orchestrator for plugins. The application is simply redirecting data between the plugins as of the users choice, so what the plugin does is not known at all (especially since they can be developed by 3rd party devs).
The application and the plugin are sharing an interface as a way of knowing what methods to call for, so the traffic goes both ways: a plugin calls a method in the main application sending it data and the main application is passing this data to another plugin.
This works so far, but I'm having a problem with synchronous behavior. All methods defined by the interface lack a return value (Void) and I'm struggling to get a "fire and forget" kind of approach where the calling application does NOT need to sit around waiting for the plugins receiving function to finish execute code (and calls that goes back to the main app!).
So whats the best approach to solving this? Letting every plugin (and the main app) put it's workload on a "stack" of some kind just to be able to return the control to the calling side and then have some mechanism that runs separately that works through the stack item by item (and do this stacking approach as async?)?
Other things worth noting is that the plugins are running in separate threads (according to the debugger thread window) and when they are initialized they get a reference from the calling main application so they can fire functions in the main app. The plugins also very often need to tell the main app what status they are in (idle, working, error etc) and also send data to be logged by the main app, so this very often creates a nested call hierarchy (if you follow me, hard to explain).
I'm using .Net 4.5 for this one.
Below is some simplified example of the code. I replaced some names, so if there is a spelling error somewhere, its just here and not in the real code. :)
The interface:
public interface IMyPluggableApp
{
void PluginStatus(string PluginInstanceGuid, PluginInstanceState PluginInstanceState);
void DataReceiver(string PluginInstanceGuid, string ConnectorGuid, object Data);
void Logg(string PluginInstanceGuid, LoggMessageType MessageType, string Message);
}
public interface IPluginExport
{
PluginInfo PluginInfo { get; set; }
void Initialize(string PluginInstanceGuid, Dictionary<string, string> PluginUserSettings, IMyPluggableApp MyPluggableApp);
void Start(string PluginInstanceGuid, List<ConnectorInstanceInfo> ConnectedOutputs);
void Stop(string PluginInstanceGuid);
void PluginClick(string PluginInstanceGuid);
void PlugginTrigger(string ConnectorGuid, object Data);
}
The plugin:
public static IMyPluggableApp _MyPluggableApp
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IPluginExport))]
public class PluginExport : IPluginExport
{
public void Initialize(string PluginInstanceGuid, Dictionary<string, string> pluginUserSettings, IMyPluggableApp refMyPluggableApp)
{
_MyPluggableApp = refMyPluggableApp; // Populate global object with a ref to the calling application
// some code for setting saved user preferences
_MyPluggableApp.PluginStatus(PluginInfo.PluginInstanceGuid, PluginInstanceState.Initialized); // Tell main app we're initialized
}
public void Start(string PluginInstanceGuid, List<ConnectorInstanceInfo> ConnectedOutputs)
{
// Some code for preparing the plugin functionality
_MyPluggableApp.PluginStatus(PluginInfo.PluginInstanceGuid, PluginInstanceState.Initialized); // Tell main app we started
}
public void PlugginTrigger(string ConnectorGuid, object Data)
{
_MyPluggableApp.PluginStatus(AvailablePlugins.PluginInfo.PluginInstanceGuid, PluginInstanceState.Running_Busy); // Tell main app we're busy
// Run the code that actually provides the functionality of this plugin
_MyPluggableApp.PluginStatus(AvailablePlugins.PluginInfo.PluginInstanceGuid, PluginInstanceState.Running_Idle); // Tell main app we're idle
}
// and so on ...
}
And the main application:
public partial class MainWindow : IMyPluggableApp
{
[ImportMany(typeof(IPluginExport))]
IPluginExport[] _availablePlugins;
public void PluginStatus(string PluginInstanceGuid, PluginInstanceState PluginInstanceState)
{
// Code for setting status in GUI
}
public void DataReceiver(string PluginInstanceGuid, string ConnectorGuid, object Data)
{
ConnectorInfo connector_source = GetConnectorInfo(ConnectorGuid);
PluginInfo plugin_source = GetPluginInfo_ByPluginInstanceGuid(PluginInstanceGuid);
ConnectorInstanceInfo connector_destination = (from i in _project.PluginInstances
from y in i.ConnectedConnectors
where i.PluginInstanceGuid == PluginInstanceGuid
&& y.ConnectedFromOutput_ConnectorGuid == ConnectorGuid
select y).FirstOrDefault();
_availablePlugins.Where(xx => xx.PluginInfo.PluginInstanceGuid == connector_destination.ConnectedToInput_PluginInstanceGuid).First().PlugginTrigger(ConnectorGuid, Data);
}
public void Logg(string PluginInstanceGuid, LoggMessageType MessageType, string Message)
{
// Logg stuff
}
}
It's the DataReceiver function in the main app thats receives the data, looks what plugin should have it, and then sends it (via PlugginTrigger function).
A couple of observations:
Fire and forget is a requirement of the host so not something the plug-in implementations should have to worry about.
I don't think (please correct me if I am wrong) the CLR supports calling methods in a "fire-and-forget"-ful way within the same AppDomain. If your plug-ins were loaded in to separate processes, and you were communicating with them using WCF then you could simply set the IsOneWay property on your OperationContractAttribute.
The second point suggests one solution, which seems slight overkill for your situation - but let us mention it anyway. Your plug-ins could host in-process WCF services, and all the communication between the WPF application and the plug-ins could be done through the WCF service proxies. However, this comes with a configuration nightmare and is really opening a can of worms to a whole bunch of other issues you would have to solve.
Let us start with a simple example of the initial problem, and attempt to solve it from there. Here is the code for Console application with a plug-in:
public class Program
{
private static void Main(string[] args)
{
var host = new CompositionHost();
new CompositionContainer(new AssemblyCatalog(typeof(Plugin).Assembly)).ComposeParts(host);
var plugin = host.Plugin;
plugin.Method();
Console.ReadLine();
}
private class CompositionHost: IPartImportsSatisfiedNotification
{
[Import(typeof (IPlugin))] private IPlugin _plugin;
public IPlugin Plugin { get; private set; }
public void OnImportsSatisfied()
{
Plugin = _plugin;
}
}
}
public interface IPlugin
{
void Method();
}
[Export(typeof(IPlugin))]
public class Plugin : IPlugin
{
public void Method()
{
//Method Blocks
Thread.Sleep(5000);
}
}
The problem is the call to plugin.Method() is blocking. To solve this, we change the interface that is exposed to the Console application to the following:
public interface IAsyncPlugin
{
Task Method();
}
A call to an implementation of this interface will not block. The only thing we need to change is the CompositionHost class:
private class CompositionHost: IPartImportsSatisfiedNotification
{
[Import(typeof (IPlugin))] private IPlugin _plugin;
public IAsyncPlugin Plugin { get; private set; }
public void OnImportsSatisfied()
{
Plugin = new AsyncPlugin(_plugin);
}
private sealed class AsyncPlugin : IAsyncPlugin
{
private readonly IPlugin _plugin;
public AsyncPlugin(IPlugin plugin)
{
_plugin = plugin;
}
public Task Method()
{
return Task.Factory.StartNew(() => _plugin.Method());
}
}
}
}
Obviously this is a very simple example, and the implementation may have to vary slightly when applying it to your WPF scenario - but the general concept should still work.