Sponsors

Chủ Nhật, 28 tháng 7, 2013

Implicit/Explicit Conversion Operators

I saw some code yesterday which at first glance looked odd. A method was accepting a parameter of a custom type named Money and the calling code was passing in a double value. After a bit of confusion I recalled that the C# language natively supports conversion operators.

If you have a custom type, you have the option to define conversion operators on your type which let you convert from your custom type to a target type and from the target type back to the custom type. Conversion can be implicit or explicit. Implicit conversion means that users of your custom type can convert to the target type without having to perform a type cast operation. Explicit conversion forces a type cast to be performed.

To demonstrate this, we'll use the case I came across. Imagine we have a Money class which is composed of a currency and a value that the money represents. We may initially decide that we want the Money class to be flexible so that users of the class can treat it is a value (a double type in this case). This means that when a double is expected (e.g. as an argument to a method), the user of the class can pass the Money instance which will implicitly be converted to its value form. Moreover, we can also make the conversion from double to Money implicit, meaning that whenever a Money instance is expected, we can pass in a double. Our initial attempt at the Money class implementation would therefore look something like:
public class Money
{
    public string Currency { get; set; }
    public double Value { get; set; }

    // Implicit conversion from Money to double
    public static implicit operator double(Money money)
    {
        return money.Value;
    }

    //  Implicit conversion from double to Money
    public static implicit operator Money(double @double)
    {
        return new Money { Value = @double };
    }
}
With the above class, the following code would therefore compile:
var money = new Money() { Currency = "GBP", Value = 10.5 };
            
// Implicitly convert Money to a double
double moneyValue = money;

// Convert a double to Money (Money.Currency will be null!)
Money moneyInstance = moneyValue;
Notice that when converting a Money instance to a double, we would lose information on the Money instance (the currency in this case). Also, when converting a double to a Money, the currency is never set. It would therefore make more sense in this scenario to use explicit conversion operators so that the user is forced to be aware that they could lose information in the conversion or have a partially initialised Money instance (it isn't a straight-forward conversion). To define explicit conversion on the Money class, the only change required would be to replace the "implicit" keyword with the "explicit" keyword on the two conversion methods. The Money class would now look like:
public class Money
{
    public string Currency { get; set; }
    public double Value { get; set; }

    // Explicit conversion from Money to double
    public static explicit operator double(Money money)
    {
        return money.Value;
    }

    //  Explicit conversion from double to Money
    public static explicit operator Money(double @double)
    {
        return new Money { Value = @double };
    }
}
After making this change, the example calling code above would fail to compile with the following two compile-time error messages:

Cannot implicitly convert type 'ConversionOperators.Money' to 'double'. An explicit conversion exists (are you missing a cast?)
Cannot implicitly convert type 'double' to 'ConversionOperators.Money'. An explicit conversion exists (are you missing a cast?)

As the errors point out, we now need to explicitly cast between the types - as demonstrated in the code below.
var money = new Money() { Currency = "GBP", Value = 10.5 };
            
double moneyValue = (double) money;

Money moneyInstance = (Money) moneyValue;

You can download the example code by clicking here.

Chủ Nhật, 7 tháng 7, 2013

JQuery DataTables Editable in Asp.net c#


Asp.Net How To Edit JQuery DataTables Using Asp.Net GridView , C#

The purpose of this article is to show how you can implement JQuery DataTables   with Asp.net Gridview Control. The jQuery DataTables plugin is an excellent client-side component. This plugin adds lots of functionalities to the plain HTML tables that are placed in web pages such as  sorting, searching, pagination, changing page length etc

HTML Markup:
Here you will see in html markup theres a pencil image which on click becomes editable  and so user can edit the values also look at classname .i.e set classname as update_ + id  using string.Concat().   where id is  database rowId.

<asp:GridView ID="myGridview" runat="server" BackColor="White"   AutoGenerateColumns="False" CssClass="gvmyalign"    
       BorderColor="Gray" BorderStyle="Solid" BorderWidth="1px" CellPadding="4"  ForeColor="Black" GridLines="None" Width="500px"
       AllowPaging="True"  ShowFooter="false"  >
       <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
        <HeaderStyle BackColor="#A86E07" Font-Bold="True" ForeColor="White" />
           <Columns>
            <asp:TemplateField HeaderText="Id" Visible="false">
              <ItemTemplate>
                    <asp:Label ID="lblid" runat="server" Text='<%# Eval("Id") %>'></asp:Label>
              </ItemTemplate>
              </asp:TemplateField>
               <asp:TemplateField HeaderText="Name"   ItemStyle-Width="230">
                 <ItemTemplate>
                       <asp:Label ID="lblname" runat="server" Text='<%# Eval("Name") %>'></asp:Label>
                 </ItemTemplate>
               </asp:TemplateField>
               <asp:TemplateField ShowHeader="False" ItemStyle-Width="90" >
               <ItemTemplate>
                 <asp:Image ID="Image1" ToolTip="Edit" style="cursor:pointer;" CssClass=' <%# string.Concat("update_",Eval("Id")) %>' ImageUrl="~/images/pencil.png" runat="server" />
                </ItemTemplate>
           </asp:TemplateField>
        </Columns>
       <PagerStyle BackColor="#A86E07" ForeColor="White" HorizontalAlign="Center" />
    <EditRowStyle BackColor="#d9d9d9" />
  <AlternatingRowStyle BackColor="White" ForeColor="#A86E07" />
</asp:GridView>

Code Behind: DefaultPage.aspx
You need to add Page_PreRender event on .cs where we set gridview's UseAccessibleHeader=true .
protected void  (object sender, EventArgs e)
{
if (myGridview.Rows.Count > 0) {
myGridview.UseAccessibleHeader = true;
myGridview.HeaderRow.TableSection = TableRowSection.TableHeader;
}
}

protected void Page_Load(object sender, EventArgs e) {
if (!Page.IsPostBack) { gvBind(); }
}

public void gvBind() {
myGridview.EmptyDataText = "No Record";
DataTable dt = getData();
myGridview.DataSource = dt;
myGridview.DataBind();
}

Now the Real coding part comes here using JQuery Datatables .
Add JqueryDatable Script Files 
<link href="jquery.dataTables_themeroller.css" rel="stylesheet" type="text/css" />
<script src="../js/jquery.dataTables.js" type="text/javascript"></script>
<script src="../js/jquery.dataTables.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var oTable;
$(".gvmyalign span").contents().unwrap();
oTable = $(".gvmyalign").dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers"

});
});
</script>
Now after apply JQuery DataTable Gridview look like below image. ScreenShot:
Now:


Edit Mode:


Edit Row:On Click of pencil image we convert Lable into Textboxes and place it inside JQueryDatables which we stored using variable oTable. Here on EDIT mode we replace pencil image with SAVE and CANCEL image button, also set respected ids into classes as same we did for pencil img. On cancle img click we Undo editmode, when the user finishes editing an click Save img button a AJAX call is sent to the server-side page that updates the records into database. Also u need to check some JQuery Datatable's method which have used like fnUpdate(),  fnDraw(),  fnGetData(nRow);

Client Side:

<script type="text/javascript">

var oTable;
function editRow(oTable, nRow) {
var aData = oTable.fnGetData(nRow);
var jqTds = $('>td', nRow);
var gtval = aData[1];
var absValue = $("#hdid").val();
var mySav_Class = absValue.replace('update_', 'sav_');
var myCnl_Class = absValue.replace('update_', 'cnl_');
var sname = $("#hdname").val();

jqTds[0].innerHTML = '<input class="edt1" type="text" value="' + sname + '">';
jqTds[1].innerHTML = '<img class="' + mySav_Class + '" title="Save" src="save.png" /><img class="' + myCnl_Class + '" title="Cancel" src="cancle.png" />';
}

function restoreRow(oTable, nRow) {
var aData = oTable.fnGetData(nRow);
var jqTds = $('>td', nRow);
for (var i = 0, iLen = jqTds.length; i < iLen; i++) {
oTable.fnUpdate(aData[i], nRow, i, false);
}
oTable.fnDraw();
}

function updatevalidDatarow() {
if ($('.edt1').val() == "") {
alert("Enter name.");
return false
}
return true;
}

$(document).ready(function () {

//One Pencil Img click make it editable mode
var nEditing = null;
$("img[class^='update_']").live('click', function (event) {
event.preventDefault;
var getId = $(this).attr("class");
$("#hdid").val(getId); // hdid is hidden field
var nRow = $(this).parents('tr')[0];
var setName = $.trim($(this).closest('tr').find('td').eq(0).text());
$("#hdname").val(setName); // hdname is hidden field

if (nEditing !== null && nEditing != nRow) {
restoreRow(oTable, nEditing);
editRow(oTable, nRow);
nEditing = nRow;
}
else {
editRow(oTable, nRow);
nEditing = nRow;
}
});

//On cancle Img click undo editable mode ie not editable
$("img[class^='cnl_']").live('click', function (event) {
var abc = $(this).attr("class");
var datetxt = $("#hdname").val();
$('.edt1').replaceWith(datetxt);
var arr = [];
arr = abc.split('_');
var id = arr[1];
var updateclass = "update_" + id;
var updatebtn = '<img src="pencil.png" style="cursor:pointer;" title="Edit" class="' + updateclass + '">';
$('.' + abc).replaceWith(updatebtn);
$('.sav_' + id).replaceWith("");
});


//On save Img Click update Query fire and saves the record into database.
$("img[class^='sav_']").live('click', function (event) {
var s = $(this).attr('class');
var arr = [];
arr = s.split('_');
var id = arr[1];
var updateclass = "update_" + id;
var updatebtn = '<img src="pencil.png" title="Edit" style="cursor:pointer;" class="' + updateclass + '">';
var upName = $(".edt1").val();
var dataString = id+"="+upName;
var nposition = $(this).closest("td").get(0);
var aPosition = oTable.fnGetPosition(nposition);

if (updatevalidDatarow()) {

$.ajax({
type: "POST",
url: "ajax_function/updatefn.asmx/updateName",
data: "{ 'prefix': '" + dataString + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
var success = data.d;
if (success == "Record Updated") {
alertify.alert("Record is updated successfully.");
$('.edt1').replaceWith(upName);
$('.' + s).replaceWith(updatebtn);
$('.cnl_' + id).replaceWith("");
nEditing = null;
oTable.fnUpdate(upName, aPosition[0], 0, false);
oTable.fnDraw();
}
},
error: OnErrorCall
});
}
});
function OnErrorCall(response) {
alert(response.statusText);
}

$(".gvmyalign span").contents().unwrap();
oTable = $(".gvmyalign").dataTable({
"bJQueryUI": true,
"sPaginationType": "full_numbers"

});
});
</script>

Server Side: 

Code Behind : updatefn.asmx 
In updatefn.asmx  we have a WebMethod  updateName(), whicih fires Update query and return result stuatus. which we will display as resulting message on ajax call of success.
[WebMethod]
public string[] updateName(string prefix)
{
List d = new List();
string resultmessage = "";
string[] value = prefix.Split('=');
int update_id = Convert.ToInt32(value[0]);
string update_name = value[1];
int result = updateIndustry_Query(update_id, update_name);
if (result > 0)
{ resultmessage = "Record Updated"; }

d.Add(string.Format("{0}",resultmessage));
return d.ToArray();
}



Soundex Algorithm in C#

I caught the end of a conversation about the Soundex algorithm at work the other day which inspired me to write an implementation of it in C#. If you are not familiar with what Soundex is then the Wikipedia article on Soundex is a good place to start. I first came across this algorithm in a Natural Language Processing module during my university education. In a nutshell, when the Soundex algorithm is applied to a word, a Soundex Code is produced as output. Words that differ in spelling but sound the same (homophones) should produce the same Soundex Codes. For instance, "to" and "two" are spelt differently, but sound the same and therefore produce the same Soundex Code of "T000".

This is a useful little algorithm and I particularly like it for its simplicity and the fact that the heuristics used in the algorithm work well in most cases (one limitation of Soundex is that it falls short of covering words that sound the same but have a different first letter, e.g. "site" and "cite" produce different Soundex codes). Soundex is useful when writing search functionality where you want to account for misspellings in the users query. It's worth pointing out that SQL Server natively supports Soundex (see the Soundex function in T-SQL, for example).

My C# implementation is below - I opted to implement it in a static class that exposes one public method "For". You can download the Visual Studio solution from here (the zip contains a class library project with a corresponding test project). Note that the downloadable solution includes code comments.

public static class Soundex
{
    public static string For(string word)
    {
        const int MaxSoundexCodeLength = 4;

        var soundexCode = new StringBuilder();
        var previousWasHOrW = false;

        word = Regex.Replace(
            word == null ? string.Empty : word.ToUpper(),
                @"[^\w\s]"
                    string.Empty);

        if (string.IsNullOrEmpty(word)) 
            return string.Empty.PadRight(MaxSoundexCodeLength, '0');

        soundexCode.Append(word.First());

        for (var i = 1; i < word.Length; i++)
        {
            var numberCharForCurrentLetter = 
                GetCharNumberForLetter(word[i]);

            if (i == 1 && 
                    numberCharForCurrentLetter == 
                        GetCharNumberForLetter(soundexCode[0]))
                continue;

            if (soundexCode.Length > 2 && previousWasHOrW && 
                    numberCharForCurrentLetter == 
                        soundexCode[soundexCode.Length - 2])
                continue;

            if (soundexCode.Length > 0 && 
                    numberCharForCurrentLetter == 
                        soundexCode[soundexCode.Length - 1])
                continue

            soundexCode.Append(numberCharForCurrentLetter);

            previousWasHOrW = "HW".Contains(word[i]);
        }

        return soundexCode
                .Replace("0"string.Empty)
                    .ToString()
                        .PadRight(MaxSoundexCodeLength, '0')
                            .Substring(0, MaxSoundexCodeLength);
    }

    private static char GetCharNumberForLetter(char letter)
    {
        if ("BFPV".Contains(letter)) return '1';
        if ("CGJKQSXZ".Contains(letter)) return '2';
        if ("DT".Contains(letter)) return '3';
        if ('L' == letter) return '4';
        if ("MN".Contains(letter)) return '5';
        if ('R' == letter) return '6';

        return '0';
    }
}
Example:

// Both lines below output R100
Console.WriteLine(Soundex.For("Ravi"));
Console.WriteLine(Soundex.For("Ravee"));