Posts Tagged ‘.NET’

Enumeration class for string parameter

September 4, 2009

When I write the Google API for .NET, there are a lot of string parameters, like imageColor and safeLevel etc.

So I create an enum for every kind of parameter.

public enum SafeLevel
{
    off,
    moderate = 0,
    active,
}

I even set the moderate of SafeLevel as default value. And I can use the ToString method to get the string value most of the time.

Not every string parameter are so readable. They use “r” for relevance and “d” for date for instance.

At this time, I use extension method + switch.

public string GetString(this SortType value)
{
    switch (value)
    {
        case SortType.relevance:
            return "r";
        case SortType.date:
            return "d";
        default:
            return null;
    }
}

Or I use some helper class like LanguageUtility.

Everything is OK until Google add more choices of parameters.

Someone complained Google now can translate XXX language. Then I have to release a new version to follow the pace of Google!

The bad day has gone. Now I use string parameter directly. One can translate any language Google supported without complain and waiting.

But without enum and the helper class, API user need to check every parameter code from Google (like me).

For keeping life easy for all of you, I create the simple Enumeration class

public enum SafeLevel
    /// <summary>
    /// The enumeration. For parameters of Google APIs.
    /// </summary>
    public abstract class Enumeration
    {
        private readonly string name;

        private readonly string value;

        private readonly bool isDefault;

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        protected Enumeration(string value)
            : this(value, value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        protected Enumeration(string name, string value)
            : this(name, value, false)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <param name="isDefault">if set to <c>true</c> it is default value.</param>
        protected Enumeration(string name, string value, bool isDefault)
        {
            this.name = name;
            this.isDefault = isDefault;
            this.value = value;
        }

        /// <summary>
        /// Gets a value indicating whether this instance is default.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is default; otherwise, <c>false</c>.
        /// </value>
        public bool IsDefault
        {
            get
            {
                return this.isDefault;
            }
        }

        /// <summary>
        /// Gets the value.
        /// </summary>
        /// <value>The value.</value>
        public string Value
        {
            get
            {
                return this.value;
            }
        }

        /// <summary>
        /// Gets the name.
        /// </summary>
        /// <value>The name.</value>
        public string Name
        {
            get
            {
                return this.name;
            }
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="Google.API.Enumeration"/> to <see cref="System.String"/>.
        /// </summary>
        /// <param name="enumeration">The enumeration.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator string(Enumeration enumeration)
        {
            if (enumeration.IsDefault)
            {
                return null;
            }

            return enumeration.Value;
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.Name;
        }

        /// <summary>
        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
        /// </summary>
        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
        /// <returns>
        ///     <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            if (obj == null)
            {
                return false;
            }

            if (!this.GetType().IsInstanceOfType(obj))
            {
                return false;
            }

            return this.Value == ((Enumeration)obj).Value;
        }

        /// <summary>
        /// Returns a hash code for this instance.
        /// </summary>
        /// <returns>
        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
        /// </returns>
        public override int GetHashCode()
        {
            Debug.Assert(this.Value != null, "Value cannot be null.");

            return this.Value.GetHashCode();
        }
    }
}

It has three readonly properties: Name, Value and IsDefault.

It can also convert to string implicitly. Then you can use it as string. Or you can make it looks like the type of parameter is Enumeration but not string.

TranslateClient client = new TranslateClient();
string translated = client.Translate(text, Language.ChineseSimplified, Language.English);

It looks the same of the old enum parameter version. But the Language is not a enum but a subclass of Enumeration and the English is a public static readonly field.

public static readonly Language English = new Language("English", "en");

Here I want add two more static method and a implicit convert method.

public static Language GetDefault();

public static ICollection<Language> GetEnums();

public static implicit operator Language(string value)

It’s not hard using reflection. But I need repeat them in every subclasses of Enumeration.

Although code template tool can help me a lot, but I do not think it’s a good I idea. Don’t repeat yourself!

So I create a generic Enumeration class:

public abstract class Enumeration<T> : Enumeration, IEquatable<T> where T : Enumeration<T>

This class has a very interesting constrain. We can only create a subclass like this:

public sealed class SortType : Enumeration<SortType>

The subclass must pass itself as the generic parameter. (Tell me if I’m wrong.) In other words, the T in Enumeration is must be the type of subclass.

Here I marked SortType as sealed, because the Enumeration can only know it subclass but not sub-subclass.

Here is the whole code of Enumeration:

    /// <summary>
    /// The enumeration. Provide more static methods and properties for every concrete enumeration.
    /// </summary>
    /// <typeparam name="T">The type of concrete enumeration.</typeparam>
    public abstract class Enumeration<T> : Enumeration, IEquatable<T>
        where T : Enumeration<T>
    {
        private static T @default;

        private static IDictionary<string, T> dictionary;

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        protected Enumeration(string value)
            : base(value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        protected Enumeration(string name, string value)
            : base(name, value)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Enumeration&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="value">The value.</param>
        /// <param name="isDefault">if set to <c>true</c> it is default value.</param>
        protected Enumeration(string name, string value, bool isDefault)
            : base(name, value, isDefault)
        {
        }

        /// <summary>
        /// Gets the dictionary of value and enumeration.
        /// </summary>
        /// <value>The dictionary.</value>
        protected static IDictionary<string, T> Dictionary
        {
            get
            {
                Initialize();
                return dictionary;
            }
        }

        /// <summary>
        /// Gets the default enumeration.
        /// </summary>
        /// <returns>The default enumeration</returns>
        public static T GetDefault()
        {
            Initialize();
            return @default;
        }

        /// <summary>
        /// Gets all enumerations.
        /// </summary>
        /// <returns>All enumerations</returns>
        public static ICollection<T> GetEnums()
        {
            return Dictionary.Values;
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public bool Equals(T other)
        {
            if (other == null)
            {
                return false;
            }

            return this.Value == other.Value;
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        protected static void Initialize()
        {
            if (dictionary == null)
            {
                dictionary = new Dictionary<string, T>();

                var type = typeof(T);

                ////var enums =
                ////    from propertyInfo in
                ////        type.GetProperties(
                ////        BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.GetProperty)
                ////    where
                ////        propertyInfo.PropertyType.IsAssignableFrom(typeof(T)) &&
                ////        propertyInfo.GetIndexParameters().Length == 0
                ////    select propertyInfo.GetValue(null, null) as T;

                var enums =
                    from fieldInfo in
                        type.GetFields(
                        BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.GetField)
                    where fieldInfo.FieldType.IsAssignableFrom(type)
                    select fieldInfo.GetValue(null) as T;

                foreach (var @enum in enums)
                {
                    Debug.Assert(@enum != null, "enum cannot be null.");

                    dictionary[@enum.Value] = @enum;

                    if (@default == null && @enum.IsDefault)
                    {
                        @default = @enum;
                    }
                }
            }
        }

        /// <summary>
        /// Converts the specified value to this enumeration.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="construct">The constructor function.</param>
        /// <returns>The enumeration.</returns>
        protected static T Convert(string value, Func<string, T> construct)
        {
            if (value == null)
            {
                return GetDefault();
            }

            T @enum;

            if (!Dictionary.TryGetValue(value, out @enum))
            {
                @enum = construct(value);
            }

            return @enum;
        }
    }

Here I use the lazy load trick but not initialize in the static constructor, because the static constructor will run before than the static fields in subclass have been assigned.

And the implement convert operation can only defined in the subclass. So I put most of the logic into the Convert method.

Here is what a subclass looks like:

    /// <summary>
    /// The search safety level.
    /// </summary>
    public sealed class SafeLevel : Enumeration<SafeLevel>
    {
        /// <summary>
        /// Disables safe search filtering.
        /// </summary>
        public static readonly SafeLevel Off = new SafeLevel("Off", "off");

        /// <summary>
        /// Enables moderate safe search filtering. Default value.
        /// </summary>
        public static readonly SafeLevel Moderate = new SafeLevel("Moderate", "moderate", true);

        /// <summary>
        /// Enables the highest level of safe search filtering.
        /// </summary>
        public static readonly SafeLevel Active = new SafeLevel("Active", "active");

        private SafeLevel(string value)
            : base(value)
        {
        }

        private SafeLevel(string name, string value)
            : base(name, value)
        {
        }

        private SafeLevel(string name, string value, bool isDefault)
            : base(name, value, isDefault)
        {
        }

        /// <summary>
        /// Performs an implicit conversion from <see cref="System.String"/> to <see cref="SafeLevel"/>.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The result of the conversion.</returns>
        public static implicit operator SafeLevel(string value)
        {
            return Convert(value, s => new SafeLevel(s));
        }
    }

Although the solution has some smell, like visit static method in superclass and static protected method.

I hope it can solve my problem well.

Thanks for reading.

Advertisements

.NET’s CultureInfo do not support all languages in ISO 639-1

July 4, 2009

When I wanna replace the Language enum in Google translate API for .NET, I found that, there are at two three language that Google supported but .NET Framework not.

The Filipino (tl) or Tagalog;

The Maltese (mt).

And the Hebrew, Google use “iw” as the code for its language api, but .NET and ISO 639 use “he”.

Well, where is the Babel?!

FileSystemRightsHelper

January 8, 2009

The FileSystemRightsHelper class is a utility class to get the IO permission of a directory or a file.

DirectorySecurity security = System.IO.Directory.GetAccessControl(path);

AuthorizationRuleCollection rules = security.GetAccessRules(true, true, typeof(SecurityIdentifier));

FileSystemRightsHelper rights = new FileSystemRightsHelper(rules);

if (rights.CanWrite && rights.CanRead)
{
    Console.WriteLine("R/W access");
}
else
{
    if (rights.CanWrite)
	{
        Console.WriteLine("Only Write access");
    }  
	else if (rights.CanRead) 
	{
        Console.WriteLine("Only Read access");
    }
	else
	{
        Console.WriteLine("No Read and Write accesses");
    }
}

When I want to know “Do I have permission to Read or Write this file?”, I found this article by Bruce Hatt, “Testing File Access Rights in .NET 2.0“.

Thanks Bruce Hatt, I can get the answer of this common question.

Everything is OK, exception the code itself. I DO NOT LIKE THE CODE AT ALL!

So I rewrited my FileSystemRightsHelper (not just simple refactor).

Now it’s more effective and elegent.

Check it out!

FileSystemRightsHelper.cs

Google Search API for .NET 0.2 beta and Google Translate API for .NET 0.2 beta released

October 8, 2008

Update4

No more default http referrer. User must set it as a parameter of constructor.

Delete old Translator and Searcher classes.

Updated comments for better document.

Update3

Change all API Using string parameter instead of enum parameter.

Add new Enumeration class and enumerations for API parameters.

The API changed a lot this time. Please let me know whether you like these changes or not.

Update2

All codes are refacted (StyleCop format).

Update the APIs to support latest Google APIs.

Now can customize referrer, accept language, API key and timeout times.

Update1

Update the supported language list for Google translate api.

Set “http://code.google.com/p/google-api-for-dotnet/&#8221; as the default http referrer. (Now you cannot set your own http referrer)

No more v0.2, new features will come with v0.3.

Google APIs for .NET

Provides simple, unofficial, .NET Framework APIs for using Google Ajax RestFULL APIs (Search API, Language API etc.)

How LAZY I am. I should release nearly a month ago.

Indeed, 99+% of source have been finished when I release the Google Search API for .NET 0.1 and Google Translate API for .NET 0.1.1.

I just wait some bugs from the last versioin, so I can do some change.

I do fixed one bug, only one.

Ok, see what’s new.

The new versions are nearly no different for using, but the foundation is changed.

Replace Json.NET 2.0 by Microsoft official WCF.

And implement the HttpUtility, so not need the System.Web any more.

It now support .NET 3.5 sp1 Client Profile.

You can download here:

GoogleSearchAPI_0.3.1.zip

GoogleTranslateAPI_0.3.1.zip

More in formations, please visit the project’s site:

http://code.google.com/p/google-api-for-dotnet/

How to excute a LINQ Expression

October 8, 2008

Linq for .NET 3.5 is a very interesting new feature. It provide you some abilities that compiler has.

Thanks for Expression (under System.Linq.Expressions namespace), we can keep the expression tree but not compiled MSIL code.

When you use Linq like this,


var count = from dataItem in data where dataItem.Value &gt; 100 select data.Value2;

You do not need to know the expression tree (You even do not need to add the using of System.Linq.Expressions), .NET compiler and runtime to all the things for you.

That good most of the times.

Sometimes, you need to do something by yourself. Just like my current project, I need get the result directly from a expression tree.


object GetResult(Expression m);

T GetResult<T>(Expression m);

The only one I can find to do this directly is Excute method in IQueryProvider interface.


public interface IQueryProvider
{
Object Excute(Expression expression);

TResult Excute
(Expression expression);
}

Looks great, but useless. It use an interface, and I cannot find a impliment in the framework.

Ok, it’s time to show you the truth. No more words. Just the code below.


public static object GetResult(this Expression m)
{
    if (m == null)
        throw new ArgumentException("m");
    Type type = typeof (Func<>).MakeGenericType(m.Type);
    LambdaExpression lambda = Expression.Lambda(type, m);
    Delegate callback = lambda.Compile();
    object result = callback.DynamicInvoke();
    return result;
}

public static T GetResult<T>(this Expression m)
{
    if (m == null)
        throw new ArgumentNullException("m");
    Expression<Func<T>> lambda = Expression.Lambda<Func<T>>(m);
    Func<T> callback = lambda.Compile();
    T result = callback();
    return result;
}

Compile to MSIL at runtime, isn’t it cool?!

Google Search API for .NET 0.1 released

September 17, 2008

Well! Use this API to search Lehman Brothers.

Google Search API for .NET is a part of Goolge APIs for .NET project.

This project provides simple, unofficial, .NET Framework APIs for using Google Ajax RestFULL APIs (Search API, Language API etc.)

Description:

Provides a simple, unofficial, .NET Framework API for using Google Ajax Search API service.

Feature:

  • Support all 8 Google Search APIs.
  • CLS compatible. It can be used by any .NET languages (VB.NET, C++/CLI etc.)
Google Search APIs State
Google Web Search API supported
Google Local Search API supported
Google Video Search API supported
Google Blog Search API supported
Google News Search API supported
Google Book Search API supported
Google Image Search API supported
Google Patent Search API supported

Required:

  • .NET Framework 3.5. (You can build your own project on .NET 2.0, but you need to install .NET 3.5 to run this library).

Update:

You can download here:

GoogleSearchAPI_0.1.zip

You can visit the site of the project for all downloads, source,  examples and other information.

http://code.google.com/p/google-api-for-dotnet/

NUnitExtension.DataDriven – an NUnit AddIn for data-driven testing

July 14, 2008

DataDriven Extension is an NUnit Addin that allows you to create test cases from any data sources (like database or plain text files etc.) and can used for parameterized test.

DataFactoryAttibute (like the FactoryAttribute in NUnit 2.5 alpha 3), indicate class of the test case factory. You can also set some arguments for creating test cases.

Test case factory class must have a defualt constructor and a method with IEnumerable as the return value for create test cases. And this method should be marked by the DataSourceAttribute (like the TestCaseFactory in NUnit 2.5 alpha 3).

TestCaseItem (like the TestCaseData in NUnit 2.5 alpha 3) is a constraint-oriented test case task class. You can set the arguments for parameterized test method or normal test method and set some constraints to check the return value or expected exception throwed by the test method.

You can download here:

NUnitExtension.DataDriven_0.1_alpha.zip

To get the source code or more information, please visit the project site:

http://code.google.com/p/nunit-extension-datadriven/

Request

  • NUnit 2.5 alpha 3 (May be compiled against other NUnit versions)
  • .NET Framework 2.0 (Not tested under .NET Framework 1.1 and mono)

Install

  1. Copy the NUnitExtension.DataDriven.AddIn.dll to “…\NUnit 2.5\net-2.0\addins\”.
  2. Add reference to NUnitExtension.DataDriven.dll and write your own data-driven tests.

Example

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using NUnit.Framework;
using NUnit.Framework.Constraints;
using NUnit.Framework.Syntax.CSharp;
using NUnitExtension.DataDriven;

[TestFixture]
public class DataDrivenTest
{
    Random random = new Random();

    [DataFactory(typeof(RandomFactory), 10)]
    public double Add(double a, double b)
    {
        return a + b;
    }

    [DataFactory(typeof(RangeFactory))]
    public double NextDouble()
    {
        return random.NextDouble();
    }

    [DataFactory(typeof(ExceptionFactory), typeof(int))]
    public void ThrowException(Type exceptionType)
    {
        if (typeof(Exception).IsAssignableFrom(exceptionType))
            if (exceptionType.GetConstructor(new Type[0]) != null)
            {
                throw (Exception) Activator.CreateInstance(exceptionType);
            }
    }
}

public class RandomFactory
{
    [DataSource]
    public IEnumerable GetTestCases(int count)
    {
        Random random = new Random();
        for(int i = 0; i

System.Web.HttpUtility for .Net Compact Framework and Sliverlight

July 4, 2008

I know some one like me wanna use the UrlEncode when he/she code on the .Net Compact Framework or Sliverlight.

Here I copy and fix the code from System.Web.dll via reflector.

Its include all the UrlEncode / UrlDecode and other utility methods.

You can use they in any .Net Frameworks.

Download the c# source code here (both files are needed):

HttpUtility.cs

HtmlEntities.cs

Google Search API for .NET 0.1 alpha 6 (support 7 Google Search APIs)

June 21, 2008

I’m so tired.

You cannot image how tired I am.

It’s not about this project but other things. Everyone will encounter some problems. It’s OK. It will be gone.

I keep working on this project, even I think my brain will bomb at any moment.

It’s nearly finished.

Now I need stop and have a rest. I need more test and response.

I love open source.

Google Search API for .NET is a part of Goolge APIs for .NET project.

This project provides simple, unofficial, .NET Framework APIs for using Google Ajax RestFULL APIs (Search API, Language API etc.)

Description:

Provides a simple, unofficial, .NET Framework API for using Google Ajax Search API service.

Feature:

  • Now support 7 Google Search APIs.
  • CLS compatible. It can be used by any .NET languages (VB.NET, C++/CLI etc.)
Google Search APIs State
Google Web Search API supported
Google Local Search API not support
Google Video Search API supported
Google Blog Search API supported
Google News Search API supported
Google Book Search API supported
Google Image Search API supported
Google Patent Search API supported

Required:

  • .NET Framework 2.0 or newer version.

You can download here:

GoogleSearchAPI_0.1_alpha_6.zip

You can visit the site of the project for all downloads, source,  examples and other information.

http://code.google.com/p/google-api-for-dotnet/

Google Search API for .NET 0.1 alpha 5

June 13, 2008

Google Search API for .NET is a part of Google APIs for .NET.

This project will provides simple, unofficial, .NET Framework APIs for using Google Ajax RestFULL APIs (Search API, Language API etc.)

The Google Translate API for .NET will also be a part of it (Indeed I have just released a new version there).

Now it support the Google Web Search API ,Google News Search API, Google Blog Search API and Google Video Search API.

I’ll add the support of all Google Search APIs(GwebSearch, GlocalSearch, GvideoSearch, GblogSearch, GnewsSearch, GbookSearch, GimageSearch, GpatentSearch) in the future.

Google Search API for .NET 0.1 alpha 5

Description:

Provides a simple, unofficial, .NET Framework API for using Google Ajax Search API service.

Feature:

  • Now support the Google Web Search API ,Google News Search API, Google Blog Search API, Google Video Search API and Google Book Search API.
  • CLS compatible. It can be used by any .NET languages (VB.NET, C++/CLI etc.)

Required:

  • .NET Framework 2.0 or newer version.

Example:

Google Web Search:

class Example
{
    public static void Main()
    {
        // Search 32 results of keyword : "Google APIs for .NET"
        IList<IWebResult> results = GwebSearcher.Search("Google API for .NET", 32);
        foreach(IWebResult result in results)
        {
            Console.WriteLine("[{0}] {1} => {2}", result.Title, result.Content, result.Url);
        }
    }
}

Google News Search:

class Example
{
    public static void Main()
    {
        // Search 16 results of keyword : "Olympic", local : "Beijing"
        IList<INewsResult> results = GnewsSearcher.Search("Olympic", 16, "Beijing");
        foreach(INewsResult result in results)
        {
            Console.WriteLine("[{0}, {1} - {2:d}]{3} => {4}", result.Publisher, result.Location, result.PublishedDate, result.Title, result.Url);
        }
    }
}

Google Blog Search:

class Example
{
    public static void Main()
    {
        // Search 32 results of keyword : "Coldplay"
        IList<IBlogResult> results = GblogSearcher.Search("Coldplay", 32);
        foreach(IBlogResult result in results)
        {
            Console.WriteLine("[{0} - {1:d} by {2}] {3} => {4}", result.Title, result.PublishedDate, result.Author, result.Content, result.BlogUrl);
        }
    }
}

Google Video Search:

class Example
{
    public static void Main()
    {
        // Search 32 results of keyword : "South"
        IList<IVideoResult> results = GVideoSearcher.Search("South Park", 32);
        foreach(IVideoResult result in results)
        {
            Console.WriteLine("[{0} - {1} seconds by {2}] {3} => {4}", result.Title, result.Duration, result.Publisher, result.Content, result.Url);
        }
    }
}

Google Book Search:

class Example
{
    public static void Main()
    {
        // Search 10 result of keyword : "Grimm's Fairy Tales"
        IList<IBookResult> results = GbookSearcher.Search("Grimm's Fairy Tales", 10);
        foreach(IBookResult result in results)
        {
            Console.WriteLine("{0} [by {1} - {2} - {3} pages] {4}", result.Title, result.Authors, result.PublishedYear, result.PageCount, result.BookId);
        }
    }
}

You can download here:

GoogleSearchAPI_0.1_alpha_5.zip

Visite the Google APIs for .NET project for more information.