ProtocolImporter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Web / System / Web / Services / Description / ProtocolImporter.cs / 1305376 / ProtocolImporter.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

namespace System.Web.Services.Description { 
 
    using System.Web.Services;
    using System.Web.Services.Protocols; 
    using System.Xml.Serialization;
    using System.Xml.Schema;
    using System.Collections;
    using System; 
    using System.Reflection;
    using System.CodeDom; 
    using System.CodeDom.Compiler; 
    using System.Text;
    using System.Xml; 
    using System.Web.Services.Configuration;
    using System.Configuration;
    using System.Security.Permissions;
    using System.Threading; 
    using System.Diagnostics;
 
    ///  
    /// 
    ///    [To be supplied.] 
    /// 
    [PermissionSet(SecurityAction.InheritanceDemand, Name="FullTrust")]
    [PermissionSet(SecurityAction.LinkDemand, Name="FullTrust")]
    public abstract class ProtocolImporter { 
        ServiceDescriptionImporter importer;
        CodeNamespace codeNamespace; 
        CodeIdentifiers methodNames; 
        CodeTypeDeclaration codeClass;
        CodeTypeDeclarationCollection classes; 
        ServiceDescriptionImportWarnings warnings;
        Port port;
        PortType portType;
        Binding binding; 
        Operation operation;
        OperationBinding operationBinding; 
        bool encodedBinding; 
        ImportContext importContext;
        Hashtable exportContext; 
        Service service;
        Message inputMessage;
        Message outputMessage;
        string className; 
        int bindingCount;
        bool anyPorts; 
 
        internal void Initialize(ServiceDescriptionImporter importer) {
            this.importer = importer; 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        public ServiceDescriptionCollection ServiceDescriptions { 
            get { return importer.ServiceDescriptions; }
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        public XmlSchemas Schemas { 
            get { return importer.AllSchemas; } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        public XmlSchemas AbstractSchemas {
            get { return importer.AbstractSchemas; } 
        } 

        ///  
        /// 
        ///    [To be supplied.]
        /// 
        public XmlSchemas ConcreteSchemas { 
            get { return importer.ConcreteSchemas; }
        } 
 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        public CodeNamespace CodeNamespace {
            get { return codeNamespace; } 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        public CodeTypeDeclaration CodeTypeDeclaration {
            get { return codeClass; }
        } 

        internal CodeTypeDeclarationCollection ExtraCodeClasses { 
            get { 
                if (classes == null)
                    classes = new CodeTypeDeclarationCollection(); 
                return classes;
            }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        public ServiceDescriptionImportStyle Style { 
            get { return importer.Style; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public ServiceDescriptionImportWarnings Warnings {
            get { return warnings; } 
            set { warnings = value; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public CodeIdentifiers ClassNames {
            get { return importContext.TypeIdentifiers; } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        public string MethodName { 
            get {
                // We don't attempt to make this unique because of method overloading 
                return CodeIdentifier.MakeValid(XmlConvert.DecodeName(Operation.Name));
            }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        public string ClassName { 
            get { return className; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public Port Port {
            get { return port; } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        public PortType PortType { 
            get { return portType; }
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        public Binding Binding { 
            get { return binding; } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        public Service Service {
            get { return service; } 
        } 

        internal ServiceDescriptionImporter ServiceImporter { 
            get { return importer; }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public Operation Operation {
            get { return operation; } 
        }

        /// 
        ///  
        ///    [To be supplied.]
        ///  
        public OperationBinding OperationBinding { 
            get { return operationBinding; }
        } 

        /// 
        /// 
        ///    [To be supplied.] 
        /// 
        public Message InputMessage { 
            get { return inputMessage; } 
        }
 
        /// 
        /// 
        ///    [To be supplied.]
        ///  
        public Message OutputMessage {
            get { return outputMessage; } 
        } 

        internal ImportContext ImportContext { 
            get { return importContext; }
        }

        internal bool IsEncodedBinding { 
            get { return encodedBinding; }
            set { encodedBinding = value; } 
        } 

        internal Hashtable ExportContext { 
            get {
                if (exportContext == null)
                    exportContext = new Hashtable();
                return exportContext; 
            }
        } 
 
        internal CodeIdentifiers MethodNames {
            get { 
                if (methodNames == null)
                    methodNames = new CodeIdentifiers();
                return methodNames;
            } 
        }
 
        internal bool GenerateCode(CodeNamespace codeNamespace, ImportContext importContext, Hashtable exportContext) { 
            bindingCount = 0;
            anyPorts = false; 

            this.codeNamespace = codeNamespace;

            Hashtable supportedBindings = new Hashtable(); 
            Hashtable unsupportedBindings = new Hashtable();
 
            // look for ports with bindings 
            foreach (ServiceDescription serviceDescription in ServiceDescriptions) {
                foreach (Service service in serviceDescription.Services) { 
                    foreach (Port port in service.Ports) {
                        Binding binding = ServiceDescriptions.GetBinding(port.Binding);
                        if (supportedBindings.Contains(binding))
                            continue; 
                        PortType portType = ServiceDescriptions.GetPortType(binding.Type);
                        MoveToBinding(service, port, binding, portType); 
                        if (IsBindingSupported()) { 
                            bindingCount++;
                            anyPorts = true; 
                            supportedBindings.Add(binding, binding);
                        }
                        else if (binding != null) unsupportedBindings[binding] = binding;
                    } 
                }
            } 
 
            // no ports, look for bindings
            if (bindingCount == 0) { 
                foreach (ServiceDescription serviceDescription in ServiceDescriptions) {
                    foreach (Binding binding in serviceDescription.Bindings) {
                        if (unsupportedBindings.Contains(binding)) continue;
                        PortType portType = ServiceDescriptions.GetPortType(binding.Type); 
                        MoveToBinding(binding, portType);
                        if (IsBindingSupported()) { 
                            bindingCount++; 
                        }
                    } 
                }
            }

            // give up if no bindings 
            if (bindingCount == 0) {
                // if we generated comments return true so that the comments get written 
                return codeNamespace.Comments.Count > 0; 
            }
 
            this.importContext = importContext;
            this.exportContext = exportContext;
            BeginNamespace();
 
            supportedBindings.Clear();
            foreach (ServiceDescription serviceDescription in ServiceDescriptions) { 
                if (anyPorts) { 
                    foreach (Service service in serviceDescription.Services) {
                        foreach (Port port in service.Ports) { 
                            Binding binding = ServiceDescriptions.GetBinding(port.Binding);
                            PortType portType = ServiceDescriptions.GetPortType(binding.Type);
                            MoveToBinding(service, port, binding, portType);
                            if (IsBindingSupported() && !supportedBindings.Contains(binding)) { 
                                GenerateClassForBinding();
                                supportedBindings.Add(binding, binding); 
                            } 
                        }
                    } 
                }
                else {
                    foreach (Binding binding in serviceDescription.Bindings) {
                        PortType portType = ServiceDescriptions.GetPortType(binding.Type); 
                        MoveToBinding(binding, portType);
                        if (IsBindingSupported()) { 
                            GenerateClassForBinding(); 
                        }
                    } 
                }
            }

            EndNamespace(); 
            return true;
        } 
 
        void MoveToBinding(Binding binding, PortType portType) {
            MoveToBinding(null, null, binding, portType); 
        }

        void MoveToBinding(Service service, Port port, Binding binding, PortType portType) {
            this.service = service; 
            this.port = port;
            this.portType = portType; 
            this.binding = binding; 
            this.encodedBinding = false;
        } 

        void MoveToOperation(Operation operation) {
            this.operation = operation;
 
            operationBinding = null;
            foreach (OperationBinding b in binding.Operations) { 
                if (operation.IsBoundBy(b)) { 
                    if (operationBinding != null) throw OperationSyntaxException(Res.GetString(Res.DuplicateInputOutputNames0));
                    operationBinding = b; 
                }
            }
            if (operationBinding == null) {
                throw OperationSyntaxException(Res.GetString(Res.MissingBinding0)); 
            }
            //NOTE: The following two excepions would never happen since IsBoundBy checks these conditions already. 
            if (operation.Messages.Input != null && operationBinding.Input == null) { 
                throw OperationSyntaxException(Res.GetString(Res.MissingInputBinding0));
            } 
            if (operation.Messages.Output != null && operationBinding.Output == null) {
                throw OperationSyntaxException(Res.GetString(Res.MissingOutputBinding0));
            }
 
            this.inputMessage = operation.Messages.Input == null ? null : ServiceDescriptions.GetMessage(operation.Messages.Input.Message);
            this.outputMessage = operation.Messages.Output == null ? null : ServiceDescriptions.GetMessage(operation.Messages.Output.Message); 
        } 

        void GenerateClassForBinding() { 
            try {
                if (bindingCount == 1 && service != null && Style != ServiceDescriptionImportStyle.ServerInterface) {
                    // If there is only one binding, then use the name of the service
                    className = XmlConvert.DecodeName(service.Name); 
                }
                else { 
                    // If multiple bindings, then use the name of the binding 
                    className = binding.Name;
                    if (Style == ServiceDescriptionImportStyle.ServerInterface) 
                    {
                        // append "I" if we are generating interfaces
                        className = "I" + CodeIdentifier.MakePascal(className);
                    } 
                }
                className = XmlConvert.DecodeName(className); 
                className = ClassNames.AddUnique(CodeIdentifier.MakeValid(className), null); 
                this.codeClass = BeginClass();
                int methodCount = 0; 
                for (int i = 0; i < portType.Operations.Count; i++) {
                    MoveToOperation(portType.Operations[i]);

                    if (!IsOperationFlowSupported(operation.Messages.Flow)) { 
                        //
                        switch (operation.Messages.Flow) { 
                            case OperationFlow.SolicitResponse: 
                                UnsupportedOperationWarning(Res.GetString(Res.SolicitResponseIsNotSupported0));
                                continue; 
                            case OperationFlow.RequestResponse:
                                UnsupportedOperationWarning(Res.GetString(Res.RequestResponseIsNotSupported0));
                                continue;
                            case OperationFlow.OneWay: 
                                UnsupportedOperationWarning(Res.GetString(Res.OneWayIsNotSupported0));
                                continue; 
                            case OperationFlow.Notification: 
                                UnsupportedOperationWarning(Res.GetString(Res.NotificationIsNotSupported0));
                                continue; 
                        }
                    }

                    CodeMemberMethod method; 
                    try {
                        method = GenerateMethod(); 
                    } 
                    catch (Exception e) {
                        if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
 		                    throw;
	                    }
                        throw new InvalidOperationException(Res.GetString(Res.UnableToImportOperation1, operation.Name), e);
                    } 

                    if (method != null) { 
                        AddExtensionWarningComments(codeClass.Comments, operationBinding.Extensions); 
                        if (operationBinding.Input != null) AddExtensionWarningComments(codeClass.Comments, operationBinding.Input.Extensions);
                        if (operationBinding.Output != null) AddExtensionWarningComments(codeClass.Comments, operationBinding.Output.Extensions); 
                        methodCount++;
                    }
                }
                bool newAsync = (ServiceImporter.CodeGenerationOptions & CodeGenerationOptions.GenerateNewAsync) != 0 && 
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareEvents) &&
                    ServiceImporter.CodeGenerator.Supports(GeneratorSupport.DeclareDelegates); 
                if (newAsync && methodCount > 0 && Style == ServiceDescriptionImportStyle.Client) { 
                    CodeAttributeDeclarationCollection metadata = new CodeAttributeDeclarationCollection();
                    string cancelAsync = "CancelAsync"; 
                    string cancelMethodName = MethodNames.AddUnique(cancelAsync, cancelAsync);
                    CodeMemberMethod asyncCancelMethod = WebCodeGenerator.AddMethod(this.CodeTypeDeclaration, cancelMethodName,
                        new CodeFlags[1], new string[] {typeof(object).FullName}, new string[] {"userState"},
                        typeof(void).FullName, 
                        metadata,
                        CodeFlags.IsPublic | (cancelAsync != cancelMethodName ? 0 : CodeFlags.IsNew)); 
 
                    asyncCancelMethod.Comments.Add(new CodeCommentStatement(Res.GetString(Res.CodeRemarks), true));
                    CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), cancelAsync); 
                    invoke.Parameters.Add(new CodeArgumentReferenceExpression("userState"));
                    asyncCancelMethod.Statements.Add(invoke);
                }
 
                EndClass();
 
                if (portType.Operations.Count == 0) 
                    NoMethodsGeneratedWarning();
 
                AddExtensionWarningComments(codeClass.Comments, binding.Extensions);
                if (port != null) AddExtensionWarningComments(codeClass.Comments, port.Extensions);

                codeNamespace.Types.Add(codeClass); 
            }
            catch (Exception e) { 
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 
		            throw;
	            } 
                throw new InvalidOperationException(Res.GetString(Res.UnableToImportBindingFromNamespace2, binding.Name, binding.ServiceDescription.TargetNamespace), e);
            }
        }
 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        public void AddExtensionWarningComments(CodeCommentStatementCollection comments, ServiceDescriptionFormatExtensionCollection extensions) { 
            foreach (object item in extensions) {
                if (!extensions.IsHandled(item)) {
                    string name = null;
                    string ns = null; 
                    if (item is XmlElement) {
                        XmlElement element = (XmlElement)item; 
                        name = element.LocalName; 
                        ns = element.NamespaceURI;
                    } 
                    else if (item is ServiceDescriptionFormatExtension) {
                        XmlFormatExtensionAttribute[] attrs = (XmlFormatExtensionAttribute[])item.GetType().GetCustomAttributes(typeof(XmlFormatExtensionAttribute), false);
                        if (attrs.Length > 0) {
                            name = attrs[0].ElementName; 
                            ns = attrs[0].Namespace;
                        } 
                    } 
                    if (name != null) {
                        if (extensions.IsRequired(item)) { 
                            warnings |= ServiceDescriptionImportWarnings.RequiredExtensionsIgnored;
                            AddWarningComment(comments, Res.GetString(Res.WebServiceDescriptionIgnoredRequired, name, ns));
                        }
                        else { 
                            warnings |= ServiceDescriptionImportWarnings.OptionalExtensionsIgnored;
                            AddWarningComment(comments, Res.GetString(Res.WebServiceDescriptionIgnoredOptional, name, ns)); 
                        } 
                    }
                } 
            }
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public void UnsupportedBindingWarning(string text) {
            AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheBinding0FromNamespace1WasIgnored2, Binding.Name, Binding.ServiceDescription.TargetNamespace, text)); 
            warnings |= ServiceDescriptionImportWarnings.UnsupportedBindingsIgnored;
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public void UnsupportedOperationWarning(string text) {
            AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheOperation0FromNamespace1WasIgnored2, operation.Name, operation.PortType.ServiceDescription.TargetNamespace, text)); 
            warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public void UnsupportedOperationBindingWarning(string text) {
            AddWarningComment(codeClass == null ? codeNamespace.Comments : codeClass.Comments, Res.GetString(Res.TheOperationBinding0FromNamespace1WasIgnored, operationBinding.Name, operationBinding.Binding.ServiceDescription.TargetNamespace, text)); 
            warnings |= ServiceDescriptionImportWarnings.UnsupportedOperationsIgnored;
        }

        void NoMethodsGeneratedWarning() { 
            AddWarningComment(codeClass.Comments, Res.GetString(Res.NoMethodsWereFoundInTheWSDLForThisProtocol));
            warnings |= ServiceDescriptionImportWarnings.NoMethodsGenerated; 
        } 

        internal static void AddWarningComment(CodeCommentStatementCollection comments, string text) { 
            comments.Add(new CodeCommentStatement(Res.GetString(Res.CodegenWarningDetails, text)));
        }

        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        public Exception OperationSyntaxException(string text) {
            return new Exception(Res.GetString(Res.TheOperationFromNamespaceHadInvalidSyntax3, 
                                               operation.Name,
                                               operation.PortType.Name,
                                               operation.PortType.ServiceDescription.TargetNamespace,
                                               text)); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        public Exception OperationBindingSyntaxException(string text) {
            return new Exception(Res.GetString(Res.TheOperationBindingFromNamespaceHadInvalid3, operationBinding.Name, operationBinding.Binding.ServiceDescription.TargetNamespace, text));
        } 

        ///  
        ///  
        ///    [To be supplied.]
        ///  
        public abstract string ProtocolName { get; }

        // These overridable methods have no parameters.  The subclass uses properties on this
        // base object to obtain the information.  This allows us to grow the set of 
        // information passed to the methods over time w/o breaking anyone.   They are protected
        // instead of public because this object is passed to extensions and we don't want 
        // those calling these methods. 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected virtual void BeginNamespace() {
            MethodNames.Clear(); 
        }
 
        ///  
        /// 
        ///    [To be supplied.] 
        /// 
        protected abstract bool IsBindingSupported();
        /// 
        ///  
        ///    [To be supplied.]
        ///  
        protected abstract bool IsOperationFlowSupported(OperationFlow flow); 
        /// 
        ///  
        ///    [To be supplied.]
        /// 
        protected abstract CodeTypeDeclaration BeginClass();
        ///  
        /// 
        ///    [To be supplied.] 
        ///  
        protected abstract CodeMemberMethod GenerateMethod();
        ///  
        /// 
        ///    [To be supplied.]
        /// 
        protected virtual void EndClass() { } 
        /// 
        ///  
        ///    [To be supplied.] 
        /// 
        protected virtual void EndNamespace() { 
            if (classes != null) {
                foreach(CodeTypeDeclaration declaration in classes) {
                    codeNamespace.Types.Add(declaration);
                } 
            }
            CodeGenerator.ValidateIdentifiers(codeNamespace); 
        } 

        internal static string UniqueName(string baseName, string[] scope) { 
            CodeIdentifiers identifiers = new CodeIdentifiers();
            for (int i = 0; i < scope.Length; i++) {
                identifiers.AddUnique(scope[i], scope[i]);
            } 
            return identifiers.AddUnique(baseName, baseName);
        } 
        internal static string MethodSignature(string methodName, string returnType, CodeFlags[] parameterFlags, string[] parameterTypes) { 
            Debug.Assert(parameterFlags.Length == parameterTypes.Length, "parameterFlags.Length !=  parameterTypes.Length");
            StringBuilder sb = new StringBuilder(); 
            sb.Append(returnType);
            sb.Append(" ");
            sb.Append(methodName);
            sb.Append(" ("); 
            for (int i = 0; i < parameterTypes.Length; i++) {
                if ((parameterFlags[i] & CodeFlags.IsByRef) != 0) 
                    sb.Append("ref "); 
                else if ((parameterFlags[i] & CodeFlags.IsOut) != 0)
                    sb.Append("out "); 

                sb.Append(parameterTypes[i]);
                if (i > 0)
                    sb.Append(","); 
            }
            sb.Append(")"); 
            return sb.ToString(); 
        }
    } 

    internal class ProtocolImporterUtil {
        private ProtocolImporterUtil() {}
 
        internal static void GenerateConstructorStatements(CodeConstructor ctor, string url, string appSettingUrlKey, string appSettingBaseUrl, bool soap11) {
            CodeExpression value; 
            bool generateFixedUrlAssignment = (url != null && url.Length > 0); 
            bool generateConfigUrlAssignment = appSettingUrlKey != null && appSettingUrlKey.Length > 0;
            CodeAssignStatement assignUrlStatement = null; 

            if (!generateFixedUrlAssignment && !generateConfigUrlAssignment)
                return;
 
            // this.Url property
            CodePropertyReferenceExpression urlPropertyReference = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "Url"); 
 
            if (generateFixedUrlAssignment) {
                value = new CodePrimitiveExpression(url); 
                assignUrlStatement = new CodeAssignStatement(urlPropertyReference, value);
            }

            if (generateFixedUrlAssignment && !generateConfigUrlAssignment) { 
                ctor.Statements.Add(assignUrlStatement);
            } 
            else if (generateConfigUrlAssignment) { 
                // urlSetting local variable
                CodeVariableReferenceExpression urlSettingReference = new CodeVariableReferenceExpression("urlSetting"); 

                // Generate: string urlSetting = System.Configuration.ConfigurationManager.AppSettings[""];
                CodeTypeReferenceExpression codeTypeReference = new CodeTypeReferenceExpression(typeof(ConfigurationManager));
                CodePropertyReferenceExpression propertyReference = new CodePropertyReferenceExpression(codeTypeReference, "AppSettings"); 
                value = new CodeIndexerExpression(propertyReference, new CodeExpression[] { new CodePrimitiveExpression(appSettingUrlKey) });
                ctor.Statements.Add(new CodeVariableDeclarationStatement(typeof(string), "urlSetting", value)); 
 
                if (appSettingBaseUrl == null || appSettingBaseUrl.Length == 0) {
                    // Generate: this.Url = urlSetting; 
                    value = urlSettingReference;
                }
                else {
                    // Generate: this.Url = "http://localhost/mywebapplication/simple.asmx"; 
                    if (url == null || url.Length == 0)
                        throw new ArgumentException(Res.GetString(Res.IfAppSettingBaseUrlArgumentIsSpecifiedThen0)); 
                    string relativeUrl = new Uri(appSettingBaseUrl).MakeRelative(new Uri(url)); 
                    CodeExpression[] parameters = new CodeExpression[] { urlSettingReference, new CodePrimitiveExpression(relativeUrl) };
                    value = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(System.String)), "Concat", parameters); 
                }
                CodeStatement[] trueStatements = new CodeStatement[] { new CodeAssignStatement(urlPropertyReference, value) };

                // Generate: if (urlSetting != null) {  } else {  } 
                CodeBinaryOperatorExpression checkIfNull = new CodeBinaryOperatorExpression(urlSettingReference, CodeBinaryOperatorType.IdentityInequality, new CodePrimitiveExpression(null));
                if (generateFixedUrlAssignment) 
                    ctor.Statements.Add(new CodeConditionStatement(checkIfNull, trueStatements, new CodeStatement[] { assignUrlStatement })); 
                else
                    ctor.Statements.Add(new CodeConditionStatement(checkIfNull, trueStatements)); 
            }
        }
    }
 
    internal class DelegateInfo {
        internal string handlerType; 
        internal string handlerArgs; 

        internal DelegateInfo(string handlerType, string handlerArgs) { 
            this.handlerType = handlerType;
            this.handlerArgs = handlerArgs;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK