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.

15 Comments

  • 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!

  • 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!

  • 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?

  • 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.

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

  • 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?

  • 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!

  • 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?

  • 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

  • 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..

  • 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.

  • 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.

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

  • 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?

  • 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.

Comments have been disabled for this content.