Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Friday, 13 April 2018

Understanding Delegates in C#

Background

Delegates are a very important part of C# programming language. A delegate in C# holds a reference to a method. Think of it as a pointer to the method. This reference or pointer can change at runtime. A delegate can also reference multiple methods and can invoke them all together. Think about event listeners for a Button in UI. You can add as many event listeners as you want and when the button is clicked all methods get the callback - much like the Observer Design Pattern. In this post well see how delegates work with an example.

Understanding Delegates in C#

Syntac of a delegate declaration is -
  • delegate <return type> <delegate-name> <parameter list>
For eg. consider -
  • public delegate void PriceChangeDelegate(int oldPrice, int newPrice); 

Now this delegate can point to any method that has return type void and parameters list (int, int). We will see a demo in a while. But the declaration syntax should be clear now.

So for this demo idea is to define an Item Object and with an attribute call price and we want to provide our own callback to receive updates whenever price of the item changes. We will do this using a delegate.

So let's first define our Item class -

namespace HelloWorld
{
    class Item
    {
        private int price;
        public PriceChangeDelegate PriceChanged;
        public int Price {
            get { return price; }
            set {
                if(value != 0)
                {
                    if(value != price)
                    {
                        PriceChanged(price, value);
                    }
                    price = value;
                }
            }
        }
    }
}



Notice how have created a private variable price (lower case by convention) and then a public property called Price (uppercase by convention) to encapsulate the price. Set method of this property is where our logic is. We are calling the delegate  PriceChanged when the old value price is different than current value. Also, notice how we have declared a public delegate member in class -
  • public PriceChangeDelegate PriceChanged;
 However, we have not yet declared our delegate type PriceChangeDelegate anywhere. Let's do that now -

namespace HelloWorld
{
    public delegate void PriceChangeDelegate(int oldPrice, int newPrice);
}


And there we go. Now our delegate instance can point to any methods of return type void and parameters (int, int) like we saw before. Now let's see all of this in action.


namespace HelloWorld
{
    class Program
    {
        public static void Main(string[] args)
        {
            Item item = new Item();
            item.PriceChanged = new PriceChangeDelegate(ItemPriceChangeCallback);
            item.Price = 100;
            Console.ReadLine();
        }
        public static void ItemPriceChangeCallback(int oldPrice, int newPrice) {
            Console.WriteLine("Item price changed from " + oldPrice + " to " + newPrice);
        }
    }
}


Here we are creating an instance of Item and setting a value for price to 100. Note the default value of primitive int is 0. So now when we set it to 100 we are essentially changing the price of the item. Also before that, we are assigning the delegate to the method we have locally called ItemPriceChangeCallback. So when items price will be changed ItemPriceChangeCallback will be called and our statement should get printed. Let's give it a try.




So that worked! Now like I said before a delegate can reference multiple methods as long as return type and paramters are same. Let's see how we can do that. Let's change our previous code a bit.


namespace HelloWorld
{
    class Program
    {
        public static void Main(string[] args)
        {
            Item item = new Item();
            item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback1);
            item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback2);
            item.Price = 100;
            Console.ReadLine();
        }
        public static void ItemPriceChangeCallback1(int oldPrice, int newPrice) {
            Console.WriteLine("ItemPriceChangeCallback1 :: Item price changed from " + oldPrice + " to " + newPrice);
        }
        public static void ItemPriceChangeCallback2(int oldPrice, int newPrice)
        {
            Console.WriteLine("ItemPriceChangeCallback2 : Item price changed from " + oldPrice + " to " + newPrice);
        }
    }
}


and the output is -


Notice our syntax for assigning delegate has changed. Instead of assigning we are adding it now -

  • item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback1);
  • item.PriceChanged += new PriceChangeDelegate(ItemPriceChangeCallback2);
instead of

  • item.PriceChanged = new PriceChangeDelegate(ItemPriceChangeCallback);

 We have defined two methods ItemPriceChangeCallback1 and ItemPriceChangeCallback2 to show this behavior. You can have as many as you wish as long as delegate contract in honoured - same return type and parameters type and number.

Also note you need not use new keyword again and again. C# compiler is intellegent enough to do this itself. You can simply do.

  • item.PriceChanged += ItemPriceChangeCallback1;
  • item.PriceChanged += ItemPriceChangeCallback2;
 It would give the same result.

Lastly you can remove all references by setting delegate as null -
  • item.PriceChanged = null;
 You would get a Null reference exception since are using delegate without instantiating our delegate and it is null by default. But this is not a desired behavior. To avoid this we can define our delegate as event. For this go back to our Item class and change -
  • public PriceChangeDelegate PriceChanged;
to
  • public event PriceChangeDelegate PriceChanged;
 and you can see that assigning null to PriceChanged is no longer possible.



 And that's all for delegates. Post your questions in comments below. Thanks.



Thursday, 5 April 2018

How to use a file to store all your logs in Xamrin Android App

Background

You can see the debug logs in the Device Log tab in Visual studio but you need to connect a USB to your android phone (not needed if you are using an emulator). However this is for realtime debugging and will not be useful to check logs that were present couple of hours back. In this post I will show you how you can log into a file in the android sd card so that you can refer it at any point in time to see what has happened.


How to use a file to store all your logs in Xamrin Android App

You can log to a file using following code snippet -

using System;
namespace Com.Osfg
{
    public class LogUtils
    {
        String logFilePath = null;

        public LogUtils()
        {
            String path = Android.OS.Environment.ExternalStorageDirectory.Path;
            logFilePath = System.IO.Path.Combine(path, "log.txt");
            if(!System.IO.File.Exists(logFilePath))
            {
                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(logFilePath, true))
                {
                    writer.WriteLine("Starting logging at " + DateTime.Now.ToString());
                }
            }
        }

        public void Log(String message)
        {
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(logFilePath, true))
            {
                writer.WriteLine(DateTime.Now.ToString() + " : " + message);
            }
        }
    }
}

Let's uderstand whats happening here -

In the constructor we are getting the external storage directory and creating a file called "log.txt" there. We are checking if the file already exists and if it does not we create it. Now anyone who want to log to this file can simple create an instance of LogUtils and call Log method on it.

You can do this on OnCreate of your main activity. For me external storage file is - /storage/emulated/0 so my complete log file path is /storage/emulated/0/log.txt

Make sure you have provided appropriate permissions in the manifest file -

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


Related Links



Friday, 30 March 2018

Hello World Xamrin Android project tutorial

Background

Xamrin are set of tools built on .NET framework . It allows you to develop applications for Android, iOS and Windows using C# language and the .NET framework.In this post I am going to show you how to develop a native android application using xamrin.

Setup

For this tutorial you need to have Visual Studio with Xamrin components installed on your Windows operating system. You can get it from Visual Studio installer. Or from Visual Studio you can go to Tools -> Get Tools and Features.


 Hello World Xamrin Android project tutorial

Click on File -> New Project  and choose Blank App(Android)

 One you have created the project you should see following code structure -


 Let's go over some of the important files here -
  1. MainActivity.cs : This is your main launcher activity.
  2. Resources/layout/Main.axml : This is your launcher ctivity layout file
  3. Resources/values/String.xml : This is your string resource file.
Go to  Resources/layout/Main.axml and add a EditText and a Button to the Linear Layout that you have. You can do that from  Designer mode with just drag and drop.



Change the id of EditText and Button to "helloWorldeditText" and "ckickMeButton" respectively. So your source would look like -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/helloWorldeditText"
        android:text="Hello World!" />
    <Button
        android:text="Click Me!"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ckickMeButton" />
</LinearLayout>
Now go to MainActivity.cs and make following changes. We are basically going to implement a button and  change the text of EditText on the click of the button.
using Android.App;
using Android.Widget;
using Android.OS;

namespace AndroidDemo
{
    [Activity(Label = "AndroidDemo", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);
            EditText helloWorldEditText = FindViewById<EditText>(Resource.Id.helloWorldeditText);
            Button clickButton = FindViewById<Button>(Resource.Id.ckickMeButton);
            helloWorldEditText.Text = "Hello World!";
            clickButton.Click += delegate { helloWorldEditText.Text = "Button Clicked!"; };
        }
    }
}



Notice the resource IDs we changed and use to reference it in the code. And that's it. Just deploy the code to an android device or an emulator and test our changes.





Related Links




t> UA-39527780-1 back to top