Google API for .NET architecture (Part 2)

Part 1: Google API for .NET architecture (Part 1) 

Today is Harvey Nash - 10 years in Viet Nam celebration day. I very happy about that, and I also drunk some beer, so I have been eager to write this post. In last post, I had been analyze about Domain Model of Gapi4net, some of people maybe like it. That is a reason I write this post in next. And what will I write in this post? As you knew in last post, I will be analyze about some technical I used in Gapi4net. Three of techniques that I will present is download data, build the Url and make Fluent Interface for Gapi4net.

+ Download data: I use a technical that post from this link for implemented the asynchronous request to Google services. I want to execute it in asynchronous because it will save a little bit time when request to Google services, and I will continue to process something else until the request to Google services are completed. I thought I will not explain it clearly, because everyone also knew why we use the asynchronous request. Next step, I only need to code the Downloader, this code will be show as below:

    public interface IDownloader : IDisposable
    {
        void Add(string url);

        int Count { get; }

        IEnumerable<IAsync> DownloadAll(Action<Async<string>> action);
    }
    internal class Downloader : IDownloader
    {
        private readonly IList<string> _urls;

        public Downloader()
        {
            _urls = new List<string>();
        }

        public void Add(string url)
        {
            Contract.Assert(!string.IsNullOrEmpty(url), "Url is null or empty");

            _urls.Add(url);
        }

        public IEnumerable<IAsync> DownloadAll(Action<Async<string>> action)
        {
            return _urls.Select(url => Async.Parallel(
                ProcessResultFromDownloadContentFromUrl(url, action)
                                           ));
        }

        private IEnumerable<IAsync> ProcessResultFromDownloadContentFromUrl(string url, Action<Async<string>> action)
        {
            var req = WebRequest.Create(url);

            // asynchronously get the response from http server
            var response = req.GetResponseAsync();
            yield return response;

            var resp = response.Result.GetResponseStream();

            // download HTML using the asynchronous extension method
            // instead of using synchronous StreamReader
            var html = resp.ReadToEndAsync().ExecuteAsync<string>();

            yield return html;

            action(html);
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        public int Count
        {
            get { return _urls.Count; }
        }
    }

 + Build the Url: Because my request is a Url, so I must to build the Url to request to Google services. I will convert from the input entities to Url, so I must to reflection the entities for get metadata and use it to build Url. To be clearly this, I will show one sample, assume that I have a input entity as:

    public abstract class EntityBase : IEntity
   {
        public string Query { getset; }

        public string Version { getset; }

        public string UserIp { getset; }

        public int ResultSize { getset; }

        public string HostLanguage { getset; }

        public string Key { getset; }


        public int Start { getset; }

        public abstract string SearchWebUrl();
    }
    public class Web : EntityBaseIWeb
    {
        public string UniqueId { getset; }

        public string Linked { getset; }

        // Safe type
        public Safe Safe { getset; }

        // ParticularLanguage type
        public ParticularLanguage ParticularLanguage { getset; }

        // Filter type
        public Filter Filter { getset; }

        // CountryCode type
        public CountryCode CountryCode { getset; }
     }

It is a web's entity, so we need knowing what are the fields that we need to build? To do that, we need creating a custom attribute as:

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property,
                    AllowMultiple = false,
                    Inherited = true)]
    public class UrlElementAttribute : Attribute
    {
        public string Name { getprivate set; }

        public bool Required { getprivate set; }

        public UrlElementAttribute(string name)
        {
            Name = name;
            Required = true;
        }
    }

After that I will decorate this custom attribute on my web's entity as:

    public abstract class EntityBase : IEntity
    {
        [UrlElement("q")]
        public string Query { getset; }

        [UrlElement("v")]
        public string Version { getset; }

        public string UserIp { getset; }

        public int ResultSize { getset; }

        public string HostLanguage { getset; }

        public string Key { getset; }

        [UrlElement("start")]
        public int Start { getset; }

        public abstract string SearchWebUrl();
    }

Finally, I will write code for exploring this entity as:

    public interface IUrlBuilder<T> where T : IEntity
    {
        string BuildUrl();

        T Entity { getset; }
    }
    public abstract class UrlBuilderBase<T> : IUrlBuilder<T> where T : IEntity
    {
        public T Entity { getset; }

        public virtual string BuildUrl()
        {
            var builder = new StringBuilder();

            var propertyInfos = Entity.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var info in propertyInfos)
            {
                var attrs = info.GetCustomAttributes(typeof(UrlElementAttribute), true);

                if (attrs.Length == 0)
                {
                    continue;
                }

                var urlAttr = attrs[0] as UrlElementAttribute;

                builder.AppendFormat("{0}={1}&", urlAttr.Name, info.GetValue(Entity, null));
            }

            return builder.ToString().Substring(0, builder.ToString().Length - 1);
        }
    }
    public class WebUrlBuilder : UrlBuilderBase<Web>
    {
    } 

All thing is fine, and now we can convert from the entities to Url with a little bit code. Are you like that too?

+ Make Fluent Interface: As you knew, Gapi4net is written for easy used, so I implemented the Fluent Interface inside it and applied the Lambda Expression to association with Fluent Interface. It make the cleanly structure for invoked the APIs as:

    Gapi4NetFactory<T>
                .Init()
                .With(x => x.Version, "1.0")
                .With(x => x.Query, searchText)
                .Create();

I copied some of code from this link, and modified something to fixed with my solution. It is so cool! Below is full of this code:

    public interface IGenericFactory<T>
    {
        IGenericFactory<T> With(Expression<Func<T, object>> property, object value);

        T Create();
    }

    public class GenericFactory<T> : IGenericFactory<T>
    {
        private T _entity;

        public GenericFactory(T entity)
        {
            _entity = entity;
        }

        public IGenericFactory<T> With(Expression<Func<T, object>> property, object value)
        {
            PropertyInfo propertyInfo = null;

            if (property.Body is MemberExpression)
            {
                propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
            }
            else
            {
                propertyInfo = ((MemberExpression)((UnaryExpression)property.Body).Operand).Member as PropertyInfo;
            }

            propertyInfo.SetValue(_entity, value, null);

            return this;
        }

        public T Create()
        {
            return _entity;
        }
    }
 
    public static class Gapi4NetFactory<T> where T : IEntitynew()
    {
        public static IGenericFactory<T> Init()
        {
            return new GenericFactory<T>(new T());
        }
    }

That is the main techniques I used in Gapi4net. For more information please download my library and look it clearly. In next post, I will show you some of technical in ASP.NET MVC 3 Preview 1. Hope you will welcome it. Thanks for you read this post and see you next time.

Published Thursday, September 16, 2010 12:43 AM by thangchung

Comments

# re: Google API for .NET architecture (Part 2)

Wednesday, August 22, 2012 7:00 AM by Morris

I do not even know the way I ended up right here,

however I assumed this put up was good. I do not realize who you're but certainly you are going to a famous blogger when you are not already. Cheers!

# re: Google API for .NET architecture (Part 2)

Monday, September 3, 2012 8:25 AM by Hutchings

Do you mind if I quote a couple of your posts as long as I provide credit and sources back to

your webpage? My blog is in the very same niche as yours and my visitors

would really benefit from a lot of the information you present here.

Please let me know if this alright with you. Thanks!

# re: Google API for .NET architecture (Part 2)

Tuesday, September 25, 2012 11:20 AM by Carson

Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point.

You clearly know what youre talking about, why

waste your intelligence on just posting videos to your weblog when you could be giving us something enlightening

to read?

# re: Google API for .NET architecture (Part 2)

Saturday, September 29, 2012 1:22 AM by Schmitz

Great post. I used to be checking constantly this weblog and I am impressed!

Very helpful info particularly the remaining section :

) I maintain such information a lot. I was seeking this particular information for a very long time.

Thanks and best of luck.

# re: Google API for .NET architecture (Part 2)

Sunday, September 30, 2012 6:53 PM by Mckenna

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา

พระล้านนา พระล้านนา พระล้านนา พระล้านนา พระล้านนา

# re: Google API for .NET architecture (Part 2)

Tuesday, October 2, 2012 2:46 AM by Coffman

I was wondering if you ever considered changing the structure of your blog?

Its very well written; I love what youve got to say. But maybe you could a

little more in the way of content so people could connect with it better.

Youve got an awful lot of text for only having 1 or 2 images.

Maybe you could space it out better?

# re: Google API for .NET architecture (Part 2)

Wednesday, December 12, 2012 8:54 AM by Cornish

This page was really helpful. I actually really enjoyed

reading it. It makes me want to be gone play a

few more games than I normally would which isn't most likely the most productive thing I have ever done but regardless thanks!

# re: Google API for .NET architecture (Part 2)

Sunday, February 10, 2013 12:25 AM by Delgado

Remarkable issues here. I am very satisfied to see your article.

Thanks so much and I'm having a look forward to touch you. Will you kindly drop me a e-mail?

# re: Google API for .NET architecture (Part 2)

Thursday, February 14, 2013 5:54 AM by Stapleton

Wonderful beat ! I wish to apprentice while you amend your web site, how could i subscribe for a

blog site? The account aided me a acceptable deal.

I had been tiny bit acquainted of this your broadcast offered bright clear

concept

# re: Google API for .NET architecture (Part 2)

Thursday, March 7, 2013 6:51 PM by Schulz

I am extremely impressed along with your writing talents and also with the format

in your blog. Is this a paid subject or did you customize it your self?

Anyway keep up the nice quality writing, it's rare to peer a nice weblog like this one today..

# re: Google API for .NET architecture (Part 2)

Tuesday, April 2, 2013 8:51 PM by Arellano

I got this web page from my friend who shared with me regarding this website and at the moment this

time I am browsing this web site and reading very informative content at this time.

# re: Google API for .NET architecture (Part 2)

Tuesday, April 9, 2013 11:26 PM by Yancey

I'm extremely impressed with your writing skills and also with the layout on your blog. Is this a paid theme or did you customize it yourself? Anyway keep up the nice quality writing, it is rare to see a great blog like this one nowadays.

# re: Google API for .NET architecture (Part 2)

Wednesday, April 10, 2013 12:04 AM by Saucedo

If some one needs to be updated with newest technologies after that he must be visit this site and be up

to date daily.

# re: Google API for .NET architecture (Part 2)

Friday, April 12, 2013 9:40 PM by Collazo

I was curious if you ever considered changing the structure of your blog?

Its very well written; I love what youve got to say. But maybe

you could a little more in the way of content

so people could connect with it better. Youve got an awful

lot of text for only having 1 or two pictures.

Maybe you could space it out better?

# re: Google API for .NET architecture (Part 2)

Sunday, April 14, 2013 3:11 AM by Sommer

Hey I know this is off topic but I was wondering if you knew of any widgets I could add to my blog that automatically tweet my newest twitter updates.

I've been looking for a plug-in like this for quite some time and was hoping maybe you would have some experience with something like this. Please let me know if you run into anything. I truly enjoy reading your blog and I look forward to your new updates.