Generating EAP to TAP wrapper class

This sample describes about source code generation for an EAP-toTAP wrapper class.

C# (77.3 KB)
 
 
 
 
 
(0)
1,432 times
Add to favorites
5/28/2011
E-mail Twitter del.icio.us Digg Facebook
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace TaskAsyncClient
{
    /// <summary>
    /// Silverlight でサービス参照したときに生成される Reference.cs からクラス名とか OperationContract メソッドを抜き出す。
    /// 戻り値のないものは無視(Task 非同期にする意味あまりないので)。
    /// Silverlight 4 Tools でしか動かないかも。
    /// </summary>
    public class Extractor
    {
        /// <summary>
        /// ソースコードからクラス名とかの情報を抽出。
        /// </summary>
        /// <param name="source">ソースコード(Reference.cs の中身)</param>
        /// <returns>抽出結果。</returns>
        public static ServiceClient Extract(string source)
        {
            var namespaceName = ExtractNamespace(source);
            var className = ExtractClass(source);

            return new ServiceClient
            {
                Namespace = ExtractNamespace(source),
                Class = ExtractClass(source),
                Methods = ExtractMethods(source).ToList(),
            };
        }

        static readonly Regex regEndInvoke = new Regex(@"OnEnd(?<name>[^\(]*)\(System.IAsyncResult result\) \{(\n||r|\s)*(?<type>[^\s]*) retVal", RegexOptions.Compiled | RegexOptions.Multiline);
        static readonly Regex regBeginInvoke = new Regex(@"public void (?<name>[^\(]*)Async\((?<parameters>.*)(, )?object userState\)", RegexOptions.Compiled);

        private static IEnumerable<Method> ExtractMethods(string text)
        {
            foreach (Match m in regEndInvoke.Matches(text))
            {
                var name = m.Groups["name"].Value;

                var invoke = regBeginInvoke.Matches(text).OfType<Match>().FirstOrDefault(x => x.Groups["name"].Value == name);

                if (invoke == null) continue;

                var parameters = invoke.Groups["parameters"].Value;
                if (parameters.Length > 2)
                    parameters = parameters.Substring(0, parameters.Length - 2);

                yield return new Method
                {
                    Name = name,
                    ReturnType = m.Groups["type"].Value,
                    ParameterList = parameters,
                };
            }
        }

        static readonly Regex regClass = new Regex(@"partial class (?<name>[^\s]+)Client :", RegexOptions.Compiled);

        private static string ExtractClass(string text)
        {
            return regClass.Match(text).Groups["name"].Value;
        }

        static readonly Regex regNamespace = new Regex(@"namespace (?<name>[^\s]+) {", RegexOptions.Compiled);

        private static string ExtractNamespace(string text)
        {
            return regNamespace.Match(text).Groups["name"].Value;
        }
    }
}