Hidden calling of a function - c#

Let's say I have two objects, Master and Slave.
Slave has a method named Init();. The thing about Init() is, that I need it to be virtual, because it contains user's initialization code, but I also need it to get called automatically when the Slave is added to Master's List. But the method must not be callable by the user, it has to be automatic.
The first thing that I tried is an event - create an event SlaveInitialized that a Slave object could handle in its OnSlaveInitialized handler. This wouldn't work though, because there's a lot of Slave objects and I have no control over the order in which they get created and need to be initialized.
The second thing that I tried is internal method - internal Init() would be called when the object is added to Master's list and all seems okay, until I realized that by doing so I cannot inherit the method in a public class.
So the third thing I did and that worked is this - I created an internal method called _Init() that simply calls a protected virtual Init(), which solved my problem.
Now I want to ask - do I just have a major strike of being stupid, because I am missing the painfully obvious solution here, or is this the way it's normally done? What is the proper way? I hope I got the point of what I'm asking across, I tried my best to explain the problem.
Thanks for any help
This is the gist of the code I now have. Its point is to have Init() invisibly and automatically called when you add any Slave object to the Master's list via Master.AddSlave();
public class Master
{
private List<Slave> _slaves;
public void AddSlave(Slave slave)
{
// Call the "hidden" init
slave._Init();
_slaves.Add(slave);
}
}
public class Slave
{
internal void _Init()
{
// Call the topmost overloaded method.
Init();
}
protected virtual void Init()
{
}
}
public class SuperSlave : Slave
{
protected override void Init()
{
// Now this method gets called automatically
// when Master.AddSlave adds this object.
}
}

As far as I can tell, there are two basic ways to do this.
Like you already tried, an internal InitInternal() method that calls a protected virtual Init()
A protected internal virtual Init(), which outside of your assembly automatically becomes a protected method.

While this doesn't answer the question the way you might want it, however I feel this could be an approperiate solution.
I would recommend throwing an InvalidOperationException if the Init method gets called multiple times.
Description: The exception that is thrown when a method call is invalid for the object's current state.
In my opinion it should not be your responsibility to police your objects from being abused, so long as documentation is written properly, your objects properties and method names describe what they do, it should be enough for most users (developers) consuming your code to understand how it works.
For those who decide to call Init themselves and then add to the Master object, you can throw that exception so they will know that their method for using the class is incorrect.
EDIT:
Naming the method OnInit might be a good idea, that way the user of the class has an indication that it should not be directly called by themselves.

Related

How to secure delegate instance reference

In the perspective of callbacks, I am facing a strange situation when I knew that myDelegate.Target contains the reference to the class whose method it contains. (I searched it on SO, however I excuse if I missed some thread already answering this)
For example
public delegate void TravePlanDelegate();
public class Traveller
{
//Papa is planing a tour, along with Mama
public void Planner()
{
//Asking me (delegate) to hold a letter about PlanA's detail
TravelPlanDelegate myPlan = PlanA;
//Sending me to TravelAgency office with letter
new TravelAgency().ExecuteTravelPlan(myPlan);
}
public void PlanA()
{
//Papa's open plan with Mama
Console.WriteLine("First Berline, then New Yark and finally Lahore");
}
public void PlanB()
{
//Papa's secret plan
Console.WriteLine("First Dubai, and then Lahore");
}
}
public class TravelAgency
{
public void ExecuteTravelPlan(TravePlanDelegate tp)
{
Traveller traveller = (Traveller)tp.Target;
//Here it should execute plan
//tp.Target - A reference to Traveler class, which can lead travel
//agency to Papa's secret plan (And exposes it to Mama)
}
}
In this example, TravelAgency can get information from delegate about papa's secret plan too. Did I get delegate concept properly or missing something?
Your assumption is correct. Unfortunately, however you try to "encapsulate" your object- there must always be a reference to it somewhere, otherwise it would be impossible to invoke it's instance method.
As some kind of counter measure, you can proxy the method invocation to a lambda expression:
TravelPlanDelegate myPlan = (args) =>PlanA(args);
This makes it less likely that any rogue code will attempt to carry out some ill intended operations on your code, since knowing how your code looks like in advance will not help it accomplish a thing.
Note that this does not ensure a thing, since the produced delegate still has a Target property to an object which holds a reference to yours.
Crackers which are smart enough can still apply reflection to the generated class and obtain a reference to your object.
Conclusion:
Only consume code you trust - it is not much of a problem in today's Open Source driven world.

C# Xamarin - AddTarget to UILongPressGestureRecognizer passing it a Selector implemented in a parent UIViewController

I am having difficulties raising an event from a UICollectionViewCell to a handler which exists within a parent UIViewController. I am trying to detect a LongPress upon a UICollectionViewCell and fire a method in the UIViewController - placing the view into an "Edit Mode" show/hiding UI elements and reloading etc. To do so my UIViewController method must call a data access layer and thus it makes sense the method is placed at this level in the view hierarchy.
I have followed the official documentation and techniques from Xamarin and the great advice from Adam Kemp here.
There are so many conflicting methodologies for achieving this in Xamarin.IOS. Alas, at present, none seem to work in my case. I must be doing something fundamentally wrong!
I have a custom class which inherits from UICollectionViewCell which contains a private UILongPressGestureRecognizer _recognizer; and method named UpdateCell as follows:
public virtual void UpdateCell(bool CanEdit)
{
// Other properties and logic omitted for brevity (no relevance to question)
this._recognizer = new UILongPressGestureRecognizer();
this._recognizer.MinimumPressDuration = 0.5;
this._recognizer.AddTarget(this, new ObjCRuntime.Selector("OnEditModeActivated"));
this.AddGestureRecognizer(_recognizer);
}
I want the Long press to fire the following method within my UIViewController:
[Export("OnEditModeActivated")]
public async void OnEditModeActivated()
{
if (recognizer.State == UIGestureRecognizerState.Ended)
{
this._canEdit = true;
// call Data Access layer using await
_source.Dispose(); // dispose of current UICollectionViewSource object
_source = new UICollectionViewSource(_data, _canEdit);
UICollectionView.Source = _source;
}
}
The line causing issues is
`this._recognizer.AddTarget(this, new ObjCRuntime.Selector("OnEditModeActivated:"));`
The selector should point to the parent UIViewController which has a public void OnEditModeActivated decorated with [Export("OnEditModeActivated:")].
I can see the compiler running into the "unrecognized selector" exception due to this (1st arg passed to AddTarget) obviously being the UICollectionViewCell rather than the UIViewController and thus it will look to resolve AddTarget by UICollectionViewCell (instance) -> OnEditActivated (does not exist).
Instead of this I need to reference the parent UIViewController but I don't want to pass it by reference to the UpdateCell method - this would mean passing the reference through many layers thus my code becoming somewhat spaghetti like.
If anyone can explain a better way, by all means feel free. I looked at raising an event within the UICollectionViewCell instance but to no avail. Moreover I can't seem to get the delegation pattern right in Xamarin!
The problem is the hierarchy I am using being: UIViewController -> UICollectionView -> UICollectionViewSource -> UICollectionViewCell.
I am sure it is possible to raise an event/call delegate/call method and resolve at the view controller level...
Thanks for taking the time to help on this.
All the best,
John
Wiring up the _recognizer to the ContentView and declaring a method within this fixed my issue.
I changed:
this.AddGestureRecognizer(_recognizer);
to:
cell.ContentView.AddGestureRecognizer(_recognizer);
and created a OnLongPressed method at the same level decorated with Export["OnLongPressed:"] which raises an event resolved at theUIViewController` level.
As an aside, the UILongPressGestureRecognizer raises mutliple events and one should check the long press has actually ended otherwise any further events / method calls will occur more than once, for example:
if(recognizer.State == UIGestureRecognizerState.Ended)
{
// Raise events call methods here only when the long press ended
}
UILongPressGestureRecognizers will fire with multiple states which you can test using the State property documentation here.

Capturing the OnExit event in WPF with MVVMCross

I need to explicitly close and dispose of a SerialPort object when my MVVMCross WPF application exits, i.e. when the red X is clicked. In order to do this, I need to call a method of the current ViewModel.
I have been trying to do this by following the MVVMCross n=42 video and adding an IKillable interface with a public abstract void KillMe() method in an abstract BaseViewModel class that implements IKillable. Then, in the WPF project I added a BaseView class, exactly as he does in the video. I am able to access methods of the current view model at this point.
In the video, the examples are IOS, Droid, and Windows Phone, where one can override events such as OnNavigatedTo, etc. In WPF, there is no OnExit() which I could override available in the BaseView class.
I am wondering, is there any way that I can call this method of the current view model when the application exits? I am able to do this:
protected override void OnExit(ExitEventArgs e)
{
// Do Something
base.OnExit(e);
}
in the App.Xaml.Mvx.cs class that came with the MVVMCross Nuget package, and I believe that this is the right place to put the code I want to execute when the program exits. The problem is that I do not have any reference to the current viewmodel.
If anyone could help me out I would really appreciate it. Thanks!
EDIT/UPDATE:
I found a work around, it seems somewhat "hacky" but it gets the job done. The class which holds the reference to the SerialPort I need to close is registered as a singleton within MVVMCross. So, I added a field of the interface type of that singleton to the App.Xaml.Mvx.cs class, then at the end of DoSetup(), I call Mvx.Resolve<>(); on that type and assign that result to the field I created. Then, I have the protected override void OnExit(ExitEventArgs e), where I can call the Close() and Dispose() methods on the field. This does what I need it to do.
I am still interested if there is a better, "more correct" way to do it with MVVMCross, however.
If you close an app the OnSuspending method is called and there I would write code for a SerialPort and because you want to fire a method of current ViewModel I would just have object representing current ViewModel in the App.xaml.cs so I can call method of it inside OnSuspending()
I would do it this way, but I don't know if it's better or can do what you need. But maybe it will give you an idea.

Events and Delegates Vs Calling methods

I hope this question is not to closely related to others but others don't seem to fill the gap in knowledge.
This seems to be hot topic to try and understand Events and Delegates and after reading many SO questions and MSDN articles I'm afraid to say I still don't understand. After some years creating great web applications, I found myself getting extremely frustrated in not understanding them. Please can anyone clarify this in common code. So the question is, why would you use events and delegates over calling a method?
Below is some basic code I written at work. Would I be able to leverage events and delegates?
Public Class Email
{
public string To {get;set;}
//Omitted code
public void Send()
{
//Omitted code that sends.
}
}
Public Class SomeClass
{
//Some props
Public void DoWork()
{
//Code that does some magic
//Now Send Email
Email newEmail = new Email();
newEmail.To = "me#me.com";
newEmail.Send();
}
}
This is probably not the best example but is there anyway that the DoWork() method can subscribe to the Email? Would this work? Any help for me to truly understand events and delegates would be greatly appreciated.
Regards,
The biggest reason I have found in real-world programming for the use of events and delegates is easing the task of code maintenance and encouraging code reuse.
When one class calls methods in another class, those classes are "tightly coupled". The more classes you have tightly coupled, the more difficult it becomes to make a change to one of them without having to also change several others. You may as well have written one big class at that point.
Using events instead makes things more "loosely coupled" and makes it much easier to change one class without having to disturb others.
Taking your example above, suppose we had a third class, Logger, that should log when an email is sent. It uses a method, LogEvent(string desc, DateTime time), to write an entry to the log:
public class Logger
{
...
public void LogEvent(string desc, DateTime time)
{
...//some sort of logging happens here
}
}
If we use methods, we need to update your Email class' Send method to instantiate a Logger and call its LogEvent method:
public void Send()
{
//Omitted code that sends.
var logger = new Logger();
logger.LogEvent("Sent message", DateTime.Now);
}
Now Email is tightly coupled to Logger. If we change the signature of that LogEvent method in Logger, we will also have to make changes to Email. Do you see how this can quickly become a nightmare when you are dealing with even a medium-sized project? Furthermore, no one wants to even try to use the LogEvent method because they know that if they need to make any sort of change to it, they will have to start changing other classes, and what should have been an afternoon's worth of work quickly turns into a week. So instead, they write a new method, or a new class, that then becomes tightly coupled to whatever else they are doing, things get bloated, and each programmer starts to get into their own little "ghetto" of their own code. This is very, very bad when you have to come in later and figure out what the hell the program is doing or hunt down a bug.
If you put some events on your Email class instead, you can loosely couple these classes:
Public Class Email
{
public event EventHandler<EventArgs> Sent;
private void OnSent(EventArgs e)
{
if (Sent!= null)
Sent(this, e);
}
public string To {get;set;}
//Omitted code
public void Send()
{
//Omitted code that sends.
OnSent(new EventArgs());//raise the event
}
}
Now you can add an event handler to Logger and subcribe it to the Email.Sent event from just about anywhere in your application and have it do what it needs to do:
public class Logger
{
...
public void Email_OnSent(object sender, EventArgs e)
{
LogEvent("Message Sent", DateTime.Now);
}
public void LogEvent(string desc, DateTime time)
{
...//some sort of logging happens here
}
}
and elsewhere:
var logger = new Logger();
var email = new Email();
email.Sent += logger.Email_OnSent;//subscribe to the event
Now your classes are very loosely coupled, and six months down the road, when you decide that you want your Logger to capture more or different information, or even do something totally different when an email is sent, you can change the LogEvent method or the event handler without having to touch the Email class. Furthermore, other classes can also subscribe to the event without having to alter the Email class, and you can have a whole host of things happen when an email is sent.
Now maintaining your code is much easier, and other people are much more likely to reuse your code, because they know they won't have to go digging through the guts of 20 different classes just to make a change to how something is handled.
BIG EDIT: More about delegates. If you read through here: Curiosity is Bliss: C# Events vs Delegates (I'll keep links to a minimum, I promise), you see how the author gets into the fact that events are basically special types of delegates. They expect a certain method signature (i.e. (object sender, EventArgs e)), and can have more than one method added to them (+=) to be executed when the method is raised. There are other differences as well, but these are the main ones you will notice. So what good is a delegate?
Imagine you wanted to give the client of your Email class some options for how to send the mail. You could define a series of methods for this:
Public Class Email
{
public string To {get;set;}
//Omitted code
public void Send(MailMethod method)
{
switch(method)
{
case MailMethod.Imap:
ViaImap();
break;
case MailMethod.Pop:
ViaPop();
break;
}
}
private void ViaImap() {...}
private void ViaPop() {...}
}
This works well, but if you want to add more options later, you have to edit your class (as well as the MailMethod enum that is assumed here). If you declare a delegate instead, you can defer this sort of decision to the client and make your class much more flexible:
Public Class Email
{
public Email()
{
Method = ViaPop;//declare the default method on instantiation
}
//define the delegate
public delegate void SendMailMethod(string title, string message);
//declare a variable of type SendMailMethod
public SendMailMethod Method;
public string To {get;set;}
//Omitted code
public void Send()
{
//assume title and message strings have been determined already
Method(title, message);
}
public void SetToPop()
{
this.Method = ViaPop;
}
public void SetToImap()
{
this.Method = ViaImap;
}
//You can write some default methods that you forsee being needed
private void ViaImap(string title, string message) {...}
private void ViaPop(string title, string message) {...}
}
Now a client can use your class with its own methods or provide their own method to send mail just about however they choose:
var regularEmail = new Email();
regularEmail.SetToImap();
regularEmail.Send();
var reallySlowEmail = new Email();
reallySlowEmail.Method = ViaSnailMail;
public void ViaSnailMail(string title, string message) {...}
Now your classes are somewhat less tightly coupled and much easier to maintain (and write tests for!). There are certainly other ways to use delegates, and lambdas sort of take things up a notch, but this should suffice for a bare-bones introduction.
Ok, I understand this answer wont strictly speaking be correct, but I'll tell you how I came to understand them.
All functions have a memory address, and some functions are simple get/set for data. It helps to think of all variables as being functions with only two methods - get and set. You're quite comfortable passing variables by reference, which means (simplistically) you are passing a pointer to their memory, which enables some other code to call their get/set methods, implicitly by using "=" and "==".
Now translate that concept to functions and code. Some code and functions have names (like variable names) which you give them. you are used to executing those functions by calling their name; but the name is just a synonym for their memory location (simplistically). By calling the function you are de-referencing its memory address using its name, and then calling the method which lives at that memory address.
As I said, this is all very simplistic and in various ways, incorrect. But it helps me.
So - is it possible to pass the memory address of a function but not call it ? In the same way you pass a reference to a variable without evaluating it ? I.e. what is the equivalent of calling
DoSomeFunction(ref variablePointer)
Well, the reference to a function is called a delegate. But because a function can also take parameters (which a variable cannot) you need to use a calling syntax more elaborate than just ref. You set up the call you want to make into a delegate structure and pass that delegate stucture to the recipient, who can either immediately evaluate (call) that delegate, or store it for later use.
Its the "store for later use" that is the key to understanding event handlers. The special (and somewhat confusing) syntax around event handlers is just another way of setting up a function pointer (delegate) and add it to a list of function pointers that the recipient class can evaluate at some convenient time.
A simple way of looking at event handlers would be;
class myClass
{
public List<delegate> eventHandlers = new List<delegate>();
public void someMethod()
{
//... do some work
//... then call the events
foreach(delegate d in eventHandlers)
{
// we have no idea what the method name is that the delegate
// points to, but we dont need to know - the pointer to the
// function is stored as a delegate, so we just execute the
// delegate, which is a synonym for the function.
d();
}
}
}
public class Program()
{
public static void Main()
{
myClass class1 = new myClass();
// 'longhand' version of setting up a delegate callback
class1.eventHandlers.Add(new delegate(eventHandlerFunction));
// This call will cause the eventHandlerFunction below to be
// called
class1.someMethod();
// 'shorthand' way of setting up a delegate callback
class1.eventHandlers.Add(() => eventHandlerFunction());
}
public static eventHandlerFunction()
{
Console.WriteLine("I have been called");
}
It gets slightly more complicated when you want the caller of the delegate to pass in some values to the function, but otherwise all delegate concepts are the same as the concepts of "ref" variables - they are references to code which will be executed at a later date, and typically you pass them as callbacks to other classes, who will decide when and whether to execute them. In earler languages delegates were pretty much the same as "function pointers" or (in beloved long departed Nantucket Clipper) "Code blocks". Its all much more complex than simply passing around a memory address of a block of code, but if you hang on to that concept, you wont go far wrong.
Hope that helps.
The simplest way of thinking about the use of delegates is to think in terms of when you want to call a method, but you don't not yet know which one (or ones).
Take a control's Click event handler, for example. It uses the EventHandler delegate. The signature is void EventHandler(object sender, EventArgs e);. What this delegate is there for is that when someone clicks the control I want to be able to call zero or more methods that have the EventHandler signature, but I don't know what they are yet. This delegate lets me effectively call unknown future methods.
Another example is LINQ's .Select(...) operator. It has the signature IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector). This method contains a delegate Func<TSource, TResult> selector. What this method does is takes a sequence of values from source and applies an as yet unknown projection to produce a sequence of TResult.
Finally, another good example is Lazy<T>. This object has a constructor with this signature: public Lazy(Func<T> valueFactory). The job of Lazy<T> is to delay the instantiate of T until the first time it is used, but then to retain that value for all future uses. It presumably is a costly instantiation that would be ideal to avoid if we don't need the object, but if we need it more than one we don't want to be hit with the cost. Lazy<T> handles all the thread locking, etc, to make sure that only one instance of T is created. But the value of T returned by Func<T> valueFactory can be anything - the creators of Lazy<T> has no idea what the delegate will be, and nor should they.
This, to me, is the most fudamentally important thing to understand about delegates.
why would you use events and delegates over calling a method?
In the context of the example you posted, if you wanted to send emails asynchronously, you would have to implement a notification mechanism.
See the SmtpClient implementation for an example: https://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.sendcompleted%28v=vs.110%29.aspx
If more of an explanation is required, rather than code examples, I'll try to explain why you would use a Delegate or Event in the example you gave above.
Imagine that you wish to know if the email was sent or not after you called Email.Send().
In the Email Class you would have two events - one for a failed send, and one for a successful send.
When the Email Class sends without an error, it would look to see if there are any subscribers to the 'SuccessfulSend()' event, and if there are, it raises that event. This would then notify the subscribers that wanted to be informed if the send was successful so that they can perform some other task.
So you could have an event handler that is notified of the successful send, and in this handler, you could call another method (DoMoreWork()).
If the Email.Send() failed, you could be notified of this, and call another method that logs the failure for later reference.
With regards to Delegates, if there were three different Email Classes that used different functionality (or servers) to send mail, the client calling the Email.Send() method, could supply the relevant Email Class to use when sending the email.
The Email Class would use the IEmail interface, and the three Email Classes would implement IEmail (To, From, Subject, Body, Attachments, HTMLBody etc.), but could perform the interactions/rules in different ways.
One could require a Subject, another require an Attachment, one could use CDONTS, another use a different protocol.
The client could determine if it needs to use CDONTS depending on where it is installed, or it could be in an area of the app where an attachment is required, or would format the body in HTML.
What this does is to remove the burden of logic from the client and all of the places where these checks and logic should be checked, and move it into the single versions of the relevant Class.
Then the client simply calls the Email.Send() after providing the correct object to use in its constructor (or by using a settable property).
If a fix or change to a particular email object's code is required - it is carried out in one place rather than finding all areas in the client and updating there.
Imagine if your Email Class was used by several different applications...

Does the OnNavigatedTo() event know who navigated to it?

If I have to, I will pass an arg to a page when I navigate to it, but is it necessary - is there a way to know which page called Navigate() without doing this?
Keep a static property in the Application object called PreviousPage. In the OnNavigatedFrom event of every page (or in the base class) set the PreviousPage to "this" (current page). In the OnNavigatedTo event, you can check that Application.PreviousPage property and use it how you see fit. This is the most effective way of accessing the previous page as there is no Frame.BackStack property in the framework for Windows Store Applications.
You could use GetNavigationState but it has some undesirable side-effects (it navigates away from the current page and the string is internal with no guarantees about how it might/might not change). I think you're best off passing it.
Calling this method will call Page.OnNavigatedFrom for the current
page using NavigationMode.Forward. GetNavigationState is usually
called when the application is being suspended, so the current page is
navigated away from.
Note:
The serialization format used by these
methods is for internal use only. Your app should not form any
dependencies on it. Additionally, this format supports serialization
only for basic types like string, char, numeric and GUID types.
I ran into this exact problem and Caleb's answer was very helpful. I just wanted to post some code to clarify how I used his solution.
DISCLAIMER I'm a bit (very!) new to C#, I'm sure there's a better way to do this, but I wanted to provide it as a starting point in case somebody else was looking for a bit more detail.
I created a global variable in the application's namespace to hold the previous page state:
public static class global_vals{
static object _previousPage;
public static object previousPage
{
get
{
return _previousPage;
}
set
{
_previousPage = value;
}
}
}
The OnNavigatedFrom method on each of my pages looks something like this:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
global_vals.previousPage = this;
}
And the OnNavigatedTo method checks the global variable like this:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (global_vals.previousPage.GetType().ToString() == "AppName.SomePage")
{
//do something
}
}

Categories

Resources