Exemplo n.º 1
0
        /// <summary>
        /// Rewrites the source file by replacing any type definitions using the old
        /// namespace with the new namespace.
        /// </summary>
        /// <param name="proxyInfo">The proxy information.</param>
        /// <param name="path">Path to the source file.</param>
        private static void MungeNamespace(VSProxyInfo proxyInfo, string path)
        {
            string source;
            string original;
            string replace;

            if (proxyInfo.OriginalProxyNamespace == proxyInfo.ProxyNamespace)
            {
                return;                                        // Namespaces are the same
            }
            original = proxyInfo.OriginalProxyNamespace + "."; // Add the period to replace only usage in types
            replace  = proxyInfo.ProxyNamespace + ".";

            using (var reader = new StreamReader(path, Helper.AnsiEncoding))
                source = reader.ReadToEnd();

            using (var writer = new StreamWriter(new FileStream(path, FileMode.Create), Helper.AnsiEncoding))
            {
                using (var reader = new StringReader(source))
                {
                    for (string line = reader.ReadLine(); line != null; line = reader.ReadLine())
                    {
                        if (line == null)
                        {
                            break;
                        }

                        line = line.Replace(original, replace);
                        writer.WriteLine(line);
                    }
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Generates the enhanced proxy source file.
        /// </summary>
        /// <param name="proxyInfo">The gathered proxy information.</param>
        /// <param name="enhancedProxyName">The generated proxy name.</param>
        /// <param name="outputPath">The output file path.</param>
        private static void GenerateEnhancedProxy(VSProxyInfo proxyInfo, string enhancedProxyName, string outputPath)
        {
            using (var writer = new StreamWriter(new FileStream(outputPath, FileMode.Create), Helper.AnsiEncoding))
            {
                writer.WriteLine(@"//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by 
//
//     LillTek Vegomatic
//     version {0}
//     {1}
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
", Helper.GetVersion(Assembly.GetExecutingAssembly()), Helper.GetCopyright(Assembly.GetExecutingAssembly()));

                writer.WriteLine("using System;");
                writer.WriteLine();
                writer.WriteLine("using LillTek.Common;");
                writer.WriteLine();
                writer.WriteLine("namespace {0} {{", proxyInfo.ProxyNamespace);

                // Generate the finished event classes (one for each distinct method name).

                var generatedMethods = new Dictionary <string, bool>();

                foreach (var method in proxyInfo.Methods)
                {
                    if (generatedMethods.ContainsKey(method.Name))
                    {
                        continue;
                    }

                    generatedMethods.Add(method.Name, true);

                    writer.Write(@"
    [System.Diagnostics.DebuggerStepThroughAttribute]
    public sealed class {0}FinishedEventArgs : EventArgs {{

        private {0}CompletedEventArgs baseArgs;
        private object userState;

        public {0}FinishedEventArgs({0}CompletedEventArgs baseArgs,object userState) {{

            this.baseArgs  = baseArgs;
            this.userState = userState;
        }}

        public {1} Result {{

            get {{ return baseArgs.Result; }}
        }}

        public object UserState {{

            get {{ return userState; }}
        }}
    }}
", method.Name, method.ResultType);
                }

                // Generate the enhanced proxy class, its constructor and any built-in methods

                writer.Write(@"
    [System.Diagnostics.DebuggerStepThroughAttribute]
    public class {1} : IDisposable {{

        private {0} baseProxy;

        public {1}() {{

            baseProxy = new {0}();
            Initialize();
        }}

        public {1}(string endpointConfigurationName) {{

            baseProxy = new {0}(endpointConfigurationName);
            Initialize();
        }}
        
        public {1}(string endpointConfigurationName,string remoteAddress) {{

            baseProxy = new {0}(endpointConfigurationName,remoteAddress);
            Initialize();
        }}
        
        public {1}(string endpointConfigurationName,System.ServiceModel.EndpointAddress remoteAddress) {{

            baseProxy = new {0}(endpointConfigurationName,remoteAddress);
            Initialize();
        }}
        
        public {1}(System.ServiceModel.Channels.Binding binding,System.ServiceModel.EndpointAddress remoteAddress) {{

            baseProxy = new {0}(binding,remoteAddress);
            Initialize();
        }}

        public void Close() {{

            if (baseProxy != null) {{

                baseProxy.CloseAsync();
                baseProxy = null;
            }}
        }}

        public void Dispose() {{

            Close();
        }}
", proxyInfo.ProxyClassName, enhancedProxyName);

                // Generate the Initialize() method that adds event handlers for
                // all of the base proxy's async methods

                writer.WriteLine("        private void Initialize() {");
                writer.WriteLine();

                foreach (var method in proxyInfo.Methods)
                {
                    writer.WriteLine("            baseProxy.{0}Completed += new EventHandler<{0}CompletedEventArgs>(On{0}Completed);", method.Name);
                }

                writer.WriteLine("        }");

                // Generate the completion event handler for each method

                generatedMethods.Clear();

                foreach (var method in proxyInfo.Methods)
                {
                    if (generatedMethods.ContainsKey(method.Name))
                    {
                        continue;
                    }

                    generatedMethods.Add(method.Name, true);

                    writer.Write(@"
        private void On{0}Completed(object sender,{0}CompletedEventArgs baseArgs) {{

            if (baseProxy == null)
                return;

            AsyncCallState  callState = (AsyncCallState) baseArgs.UserState;

            if (callState.Context != null && callState.Context.AsyncContextID != callState.OrgContextID)
                return;

            callState.Callback.DynamicInvoke(this,new {0}FinishedEventArgs(baseArgs,callState.UserState));
        }}
", method.Name);
                }

                // Generate two async method stubs for each proxy methods, one without a user state parameter
                // and one with one.

                foreach (var method in proxyInfo.Methods)
                {
                    string paramDef = string.Empty;
                    string paramVal = string.Empty;

                    foreach (var arg in method.Parameters)
                    {
                        if (paramDef.Length > 0)
                        {
                            paramDef += ',';
                            paramVal += ",";
                        }

                        paramDef += arg.Type + " " + arg.Name;
                        paramVal += arg.Name;
                    }

                    if (paramDef.Length > 0)
                    {
                        paramDef += ",";
                    }

                    if (paramVal.Length > 0)
                    {
                        paramVal += ",";
                    }

                    writer.WriteLine(@"
        public void {0}Async({1}EventHandler<{0}FinishedEventArgs> callback) {{

            {0}Async({2}callback,null);
        }}

        public void {0}Async({1}EventHandler<{0}FinishedEventArgs> callback,object userState) {{

            IAsyncContext   context      = callback.Target as IAsyncContext;
            int             orgContextID = 0;

            if (context != null)
                orgContextID = context.AsyncContextID;

            baseProxy.{0}Async({2}new AsyncCallState() {{ Context=context, OrgContextID=orgContextID, Callback=callback, UserState=userState}});
        }}", method.Name, paramDef, paramVal);
                }

                // Close out the proxy class and the namespace

                writer.WriteLine("    }");
                writer.WriteLine("}");
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Parses the proxy source file generated by Visual Studio for Silverlight
        /// applications and returns information necessary to generate the enhanced
        /// proxy.
        /// </summary>
        /// <param name="path">Path too the Visual Studio generated proxy source file.</param>
        /// <returns>The proxy information.</returns>
        private static VSProxyInfo ParseVSProxySource(string path)
        {
            const string BadSource = "Cannot parse Visual Studio generated proxy source file.";

            VSProxyInfo proxyInfo = new VSProxyInfo();
            string      line;
            int         p, pEnd;

            using (var reader = new StreamReader(path, Helper.AnsiEncoding))
            {
                // Scan for the namespace

                line = reader.ReadLine();
                while (line != null && !line.StartsWith("namespace"))
                {
                    line = reader.ReadLine();
                }

                if (line == null)
                {
                    throw new FormatException(BadSource);
                }

                pEnd = line.IndexOf('{');
                if (pEnd == -1)
                {
                    throw new FormatException(BadSource);
                }

                proxyInfo.OriginalProxyNamespace =
                    proxyInfo.ProxyNamespace     = line.Substring(10, pEnd - 10).Trim();

                // Scan for the proxy class

                line = reader.ReadLine();
                while (line != null && line.IndexOf(" : System.ServiceModel.ClientBase<") == -1)
                {
                    line = reader.ReadLine();
                }

                if (line == null)
                {
                    throw new FormatException(BadSource);
                }

                p    = line.IndexOf("public partial class");
                p   += "public partial class".Length;
                pEnd = line.IndexOf(':');
                proxyInfo.ProxyClassName = line.Substring(p, pEnd - p).Trim();

                // Scan for the method definitions (except for the ResultType).

                for (; line != null; line = reader.ReadLine())
                {
                    p = line.IndexOf("public void");
                    if (p == -1)
                    {
                        continue;
                    }

                    if (line.IndexOf("object userState)") != -1)
                    {
                        continue;
                    }

                    pEnd = line.IndexOf('(');
                    if (pEnd == -1)
                    {
                        throw new FormatException(BadSource);
                    }

                    ProxyMethod method = new ProxyMethod();

                    p          += 11;
                    method.Name = line.Substring(p, pEnd - p).Trim();
                    method.Name = method.Name.Substring(0, method.Name.Length - "Async".Length);

                    if (method.Name == "Open" || method.Name == "Close")
                    {
                        continue;   // The "OpenAsync()" and "CloseAsync" methods are helpers generated
                    }
                    // for the application's local use and are not actually web service
                    // methods so we'll ignore them.

                    p    = pEnd;
                    pEnd = line.IndexOf(')');
                    if (pEnd == -1)
                    {
                        throw new FormatException(BadSource);
                    }

                    p++;
                    line = line.Substring(p, pEnd - p);

                    // Parse the parameters.  Note that I need to take care to parse generic
                    // type parameters properly.

                    string paramType;
                    string paramName;
                    char   ch;

                    p = 0;
                    while (true)
                    {
                        paramType = string.Empty;
                        paramName = string.Empty;

                        // Parse the parameter type

                        while (p < line.Length && line[p] == ' ')       // Skip whitespace
                        {
                            p++;
                        }

                        if (p == line.Length)
                        {
                            break;
                        }

                        while (p < line.Length)
                        {
                            ch = line[p++];
                            if (ch == ' ')
                            {
                                break;
                            }
                            else if (ch == '<')
                            {
                                // We have generic type parameters.  Continue parsing until
                                // we encounter the closing ">", taking any nesting into account.

                                int nesting = 1;

                                paramType += ch;
                                while (p < line.Length)
                                {
                                    ch         = line[p++];
                                    paramType += ch;

                                    if (ch == '<')
                                    {
                                        nesting++;
                                    }
                                    else if (ch == '>')
                                    {
                                        nesting--;
                                    }

                                    if (nesting == 0)
                                    {
                                        break;
                                    }
                                }

                                if (nesting > 0)
                                {
                                    throw new FormatException(BadSource);
                                }

                                break;
                            }
                            else
                            {
                                paramType += ch;
                            }
                        }

                        // Parse the parameter name

                        while (p < line.Length && line[p] == ' ')       // Skip whitespace
                        {
                            p++;
                        }

                        if (p == line.Length)
                        {
                            throw new FormatException(BadSource);
                        }

                        pEnd = line.IndexOf(',', p);
                        if (pEnd == -1)
                        {
                            paramName = line.Substring(p).Trim();
                        }
                        else
                        {
                            paramName = line.Substring(p, pEnd - p).Trim();
                        }

                        method.Parameters.Add(new Parameter()
                        {
                            Type = paramType, Name = paramName
                        });

                        if (pEnd == -1)
                        {
                            break;
                        }

                        p = pEnd + 1;
                    }

                    proxyInfo.Methods.Add(method);
                }
            }

            // Rescan the source file looking for the method result types.  I'm going to get this
            // from the Result property of the method's xxxCompletedEventArgs class definition.

            using (var reader = new StreamReader(path, Helper.AnsiEncoding))
            {
                for (line = reader.ReadLine(); line != null; line = reader.ReadLine())
                {
                    string methodName;
                    string resultType;

                    line = line.Trim();
                    if (!line.StartsWith("public partial class ") || !line.EndsWith(" : System.ComponentModel.AsyncCompletedEventArgs {"))
                    {
                        continue;
                    }

                    // We have an event arguments declaration.  Extract the method name
                    // from the class name by trimming "CompletedEventArgs" from the end.

                    p          = "public partial class ".Length;
                    pEnd       = line.IndexOf(" : System.ComponentModel.AsyncCompletedEventArgs {");
                    methodName = line.Substring(p, pEnd - p).Trim();

                    if (!methodName.EndsWith("CompletedEventArgs"))
                    {
                        throw new FormatException(BadSource);
                    }

                    methodName = methodName.Substring(0, methodName.Length - "CompletedEventArgs".Length);

                    // Scan forward until we get to the "Result" property.

                    for (line = reader.ReadLine(); line != null; line = reader.ReadLine())
                    {
                        line = line.Trim();
                        if (line.StartsWith("public ") && line.EndsWith(" Result {"))
                        {
                            break;
                        }
                    }

                    if (line == null)
                    {
                        throw new FormatException(BadSource);
                    }

                    p          = "public ".Length;
                    pEnd       = line.Length - " Result {".Length;
                    resultType = line.Substring(p, pEnd - p).Trim();

                    // Update any records for methods with this name.  Note that there
                    // will be more than one method entry if methods have overrides.

                    foreach (var method in proxyInfo.Methods)
                    {
                        if (method.Name == methodName)
                        {
                            method.ResultType = resultType;
                        }
                    }
                }
            }

            // Verify that we found result types for all methods.

            foreach (var method in proxyInfo.Methods)
            {
                if (method.ResultType == null)
                {
                    throw new FormatException(BadSource);
                }
            }

            return(proxyInfo);
        }