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

Wednesday, October 28, 2009

GetHashCode is useful, who knew?

If you’re like me, you’re inclined to lazily ignore warnings to override object.GetHashCode for your custom types if you’ve already overriden object.Equals.  If I’m using a Dictionary and using one of my objects as a key, then sure, I can see the point.  But if I’m just throwing it in a generic List, object.Equals is good enough, right?

Well, yes, but apparently this isn’t a safe assumption to make for any given collection type or operation.  I learned this the hard way with LINQ’s Enumerable.Intersect method (an extension method of IEnumerable<T>).

Without going into detail about set theory, the Enumerable.Intersect method will take two collections of objects, and return a collection of objects which both source sets contain.  So, for example, if I have two sets of ints:

A = { 1, 5, 7, 9 }
B = { 4, 5, 9, 13 }

The intersected set would contain only the values that both sets share:

{ 5, 9 }

Now, if the items in my sets are of my own custom type, I thought it would be sufficient to override object.Equals for this type.  But no, if I do this, Enumerable.Intersect will return an empty collection, indicating that none of the objects are equal, even if they are.  When I implemented object.GetHashCode as the compiler repeatedly pestered me to do, everything worked fine.

Monday, January 26, 2009

The Poor Man’s Stock Quote Web Service

Ever wanted to programmatically fetch stock quotes? Ever look into it? I did. StrikeIron charges top dollar for their stock quote service, and, frankly, I don’t have that kind of money. But I can always go to finance.yahoo.com, and get the same information for free. Let’s exploit that, let’s create The Poor Man’s Stock Quote Web Service.

See it in action!

Using Windows Communication Foundation (Wcf), we will build a web service that takes a ticker symbol for a stock, grabs the text from the yahoo finance webpage, parses out the relevant stock quote information, and then returns a sweet StockQuote struct full of information. The legality of all this in a commercial application could probably be put to question, but we’ll leave that as an exercise for the reader.

Building a Wcf Service is very straightforward, and the source linked at the bottom is a Wcf sample perfect to introduce you to Wcf. This article isn’t an intro to Wcf, but if you’re quick, which I’m sure you are, you could pick it all up from the sample. See my other blog post to see how to host a Wcf service on a shared hosting plan.

First, we must define the ServiceContract for our Wcf Service:

[ServiceContract]    
public interface IStockQuoteService    
{    
    [OperationContract]    
    StockQuote GetQuote(string ticker);    
    [OperationContract]    
    List<StockQuote> GetQuotes(string[] tickers);    
}

As mentioned earlier, I’m going to use the Yahoo Finance to provide information for my Stock Quotes. Thus, the YahooStockService was born:

/// <summary>    
/// The Stock Quote Web Service that scrapes values from Yahoo's finance stock page.    
/// </summary>

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]    
public class YahooStockService : IStockQuoteService

In our Wcf service, we programmatically grab the text from a website using the HtmlScraper.GetPageContent function:

public static string GetPageContent(string url)    
{    
    WebRequest wreq = HttpWebRequest.Create(url);    
    WebResponse wres = wreq.GetResponse();    
    StreamReader sr = new StreamReader(wres.GetResponseStream());    
    string content = sr.ReadToEnd();    
    sr.Close();

    return content;    
}

Now that we have the page’s text, we can clumsily parse the text for the value that prefixes the content we are looking for. I usually break in my debugger, grab the Html page’s string value from the Watch window, and paste it in notepad. Then I look for the company name, and copy whatever’s in front of it.

Here is a simple example of the YahooStockService parsing for the Company Name:

private string ParseCompanyName(string page)    
{    
    // Regex pattern pasted from Html page.    
    Regex parseFor = new Regex("<div class=\"yfi_quote_summary\"><div class=\"hd\"><h1>");    
    return HtmlScraper.ParseContent(page, parseFor, "</h1>");    
}       


And now here’s the source. Many other parse functions exist in the sample, and we eventually end up with all the stock information we could need. Now go forth, poor one, and gather stock information to your heart’s content. At the time of this writing, it’s probably all going down anyways. GGgggooooo Bailout!

One note about the sample: it uses a Silverlight web app to consume the Wcf Service, you might need to install the Silverlight SDK.

References: Building a Web Service to Provide Real-Time Stock Quotes

Sunday, January 18, 2009

Objective-C versus C#, part 1: Searching for a substring within a string

 

I’ve been wanting to create a series of comparisons between the syntax of Objective-C and C#.  I’ve been writing a lot of both these days, so I have a lot of experience with each.  For our first example, let’s say we wanted to check for a substring within a string:

Objective-C

if ([myString rangeOfString:@"mySubstring"].location == NSNotFound)) {
   NSLog(@"mySubstring not found in myString: %@", myString);
}

I don’t know how you could get any more intuitive than that, but just for kicks let’s look at the C# equivalent:

C#

if (!myString.Contains(“mySubstring”))
{
    Console.WriteLine(“mySubstring not found in myString: “ + myString);
}

Sunday, January 4, 2009

Using the PollingDuplexHttpBinding for a Silverlight Group Chat

1) A Quick Intro to the PollingDuplexHttpBinding

Comet technologies, such as AJAX push and HTTP server push, allow web pages to have data pushed to them from the server, rather than always having the client pull information. It mimics this feature by having the browser poll the server at regular but short intervals (~1 second) to check for updates. Now web pages can be updated dynamically without any user input. Lucky for us, Silverlight supports this using the PollingDuplexHttpBinding Wcf Binding, which does most of the heavy lifting.

In this article, we hope to build a basic Silverlight group chat application by connecting a PollingDuplexHttpBinding to a Wcf Service hosted on a shared hosting plan.

There are excellent introductory articles to this technology that are pretty much required reading if unfamiliar with the PollingDuplexHttpBinding (Skim the first link if pressed for time):

  1. Basketball score server by Dan Wahlin
  2. Stock quote server by Peter McGrattan

The bulk of the PollingDuplexHttpBinding functionality is covered in the blogs listed above. From here on out, I will talk about some of the higher level details involved in making the simple chat program on top of the PushDataReceiver.

2) The static list of clients.

Every time a client connects to our webservice, we instantiate a new instance of the GameStreamClient class and keep it in a static List<ChatClient>. This does restrict us to only being able to run our chat server on one appdomain.

private static List<IGameStreamClient> clients = new List<IGameStreamClient>();

Our service gets instantiated on a Per Session basis as shown by the mark up below. In retrospect, I actually think it should have been a singleton, but that's for another time.

[ServiceBehavior(InstanceContextMode =
    InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Single,AutomaticSessionShutdown = true)]


3) The inactivity timeout and the stay alive ping.

Each Wcf connection has an inactivity timeout that defaults to around 10 minutes. We want our clients to be able to idle in the chat room, and not get booted for inactivity. Here we introduce a stay alive packet to reset this inactivity timeout. The end user will know nothing of it, and this way they can idle all they want.

Message gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive","stayalive");

gameDataMsg.Properties.Add("Type", "StayAlive");

this.localClient.BeginReceive(gameDataMsg, EndSend, this.localClient);

4) I remove when I catch an exception when sending to a client.

With the PollingDuplexHttpBinding, the only way we will know if a client disconnects, is when the server fails to deliver a message. We cannot rely on the client to tell us when they are disconnecting, especially when considering that they are connecting from a browser; there's no real way to elegantly close out the client. Plus, they could just crash. As a result, there is no real disconnect, there is more of a send failure mechanism, that removes clients from the static list of ChatClients. In the proceeding ChatMessage broadcast, any clients that throw a CommunicationException/TimeoutException are removed from the server's client list. These timeouts could block the server however, so we must handle this asynchronously so as not to penalize connected clients.

foreach (IGameStreamClient client in clients)
{
    try
    {
        //Send data to the client
        if (client != null)
        {
            Message gameDataMsg =
                Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive",data,this.serializer);

            gameDataMsg.Headers.Add(MessageHeader.CreateHeader("Type", "", "DataWrapper"));
            client.BeginReceive(gameDataMsg, EndSend, client);
        }
    }
    catch (Exception ex)
    {
        // Exception caught when trying to send message to client so remove them from client list.
        // Should probably catch a more specific exception but I'll leave that as an exercise for the reader.
        clientsToRemove.Add(client);
    }
}
foreach (IGameStreamClient client in clientsToRemove)
{
    clients.Remove(client);
}


5) Using DataContracts and DataContractSerializers to send complex types.

Sending strings back and forth is not really fun. Complex types such as structs would allow for much richer data transfer. So it's a good thing Wcf supports DataContracts and has a DataContractSerializer that makes this process seemless.

private readonly DataContractSerializer serializer = new DataContractSerializer(typeof(ChatData));
// Serialize
Message
gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive",chatData,this.serializer);

// Deserialize
ChatData
chatData = receivedMessage.GetBody<ChatData>(this.serializer);


6) Adding Header information to the Message object so the Processor can serialize to the appropriate type.

When your application gorws in complexity, you will probably have multiple DataContracts, but your Wcf Callback contract will only have one message handler, and you will need to programmatically handle the Message Body. To know what that body is so you can deserialize it, the sample tags the outgoing message with type strings in the Headers. This acts as a form of metadata for the message and allows the caller to deserialize the DataContract to the message of the passed type, allowing proper complexity to the callback contract. This is a lot better than clumsily having a class with a body and a type, and dealing with deserialization logic yourself.

//Server creates the message and tags it with a type.
Message gameDataMsg =
    Message.CreateMessage(MessageVersion.Soap11,"Silverlight/IGameStreamService/Receive","stayalive");

gameDataMsg.Properties.Add("Type", "StayAlive");

// Receiver parses the message type and deserializes using the correct deserializer.
// Check message type
string type = string.Empty;
for (int i = 0; i < receivedMessage.Headers.Count; i++)
{
    if (receivedMessage.Headers[i].Name == "Type")
    {
        type = receivedMessage.Headers.GetHeader<string>(i);
        break;
    }
}
// Dispatch message based on type.
switch (type)
{
    case "StayAlive":
    break;
    case "DataWrapper":


7) Source code.

Source code