ComPlusTypeLoader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ComIntegration / ComPlusTypeLoader.cs / 2 / ComPlusTypeLoader.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.ComIntegration
{ 
    using System;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Dispatcher; 
    using System.ServiceModel.Description;
    using System.Collections.Generic; 
    using System.EnterpriseServices;
    using System.Globalization;
    using System.Reflection;
    using System.Security.Principal; 
    using System.ServiceModel;
    using System.Transactions; 
    using System.Xml; 
    using System.Diagnostics;
    using System.Runtime.InteropServices; 
    using System.ServiceModel.Configuration;
    using SR=System.ServiceModel.SR;
    using System.Runtime.Serialization;
    using System.ServiceModel.Diagnostics; 
 	
    class ComPlusTypeLoader : IContractResolver 
    { 
        ServiceInfo info;
        bool transactionFlow; 
        ITypeCacheManager interfaceResolver;
        Dictionary contracts;

        public ComPlusTypeLoader(ServiceInfo info) 
        {
            this.info = info; 
            this.transactionFlow = info.TransactionOption == TransactionOption.Required || 
                                    info.TransactionOption == TransactionOption.Supported;
            this.interfaceResolver = new TypeCacheManager(); 
            this.contracts = new Dictionary();
        }

        void ValidateInterface(Guid iid) 
        {
            // Filter known invalid IIDs 
            if (!ComPlusTypeValidator.IsValidInterface(iid)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.InvalidWebServiceInterface, iid))); 
            }

            // Filter out interfaces with no configured methods
            bool configuredInterface = false; 
            foreach (ContractInfo contractInfo in this.info.Contracts)
            { 
                if (contractInfo.IID == iid) 
                {
                    if (contractInfo.Operations.Count == 0) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.RequireConfiguredMethods, iid)));
                    }
 
                    configuredInterface = true;
                    break; 
                } 
            }
 
            // Filter out interfaces that aren't configured at all
            if (!configuredInterface)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.RequireConfiguredInterfaces, iid))); 
            }
        } 
 
        ContractDescription CreateContractDescriptionInternal(Guid iid, Type type)
        { 
            ComContractElement contractConfigElement = ConfigLoader.LookupComContract (iid);

            if (contractConfigElement == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.InterfaceNotFoundInConfig, iid))); 
            if (String.IsNullOrEmpty (contractConfigElement.Name) || String.IsNullOrEmpty (contractConfigElement.Namespace))
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.CannotHaveNullOrEmptyNameOrNamespaceForIID, iid))); 
 
            ContractDescription contract = new ContractDescription(contractConfigElement.Name, contractConfigElement.Namespace);
            contract.ContractType = type; 
            contract.SessionMode = contractConfigElement.RequiresSession ? SessionMode.Required : SessionMode.Allowed;

            bool methodFound = false;
 
            List guidList = new List ();
 
            foreach (ComPersistableTypeElement typeElement in contractConfigElement.PersistableTypes) 
            {
                Guid typeGuid = new Guid(typeElement.ID); 

                guidList.Add(typeGuid);
            }
 
            IDataContractSurrogate contractSurrogate = null;
 
            // We create a surrogate when the persistable types config section is there 
            // even if we have no types that we allow.
            // That way we have control over the error when the client tries to make a call 
            // persistable type.
            if (guidList.Count > 0 || contractConfigElement.PersistableTypes.EmitClear)
            {
                contractSurrogate = new DataContractSurrogateForPersistWrapper(guidList.ToArray()); 
            }
 
            foreach (ComMethodElement configMethod in contractConfigElement.ExposedMethods) 
            {
                methodFound = false; 
                foreach (MethodInfo method in type.GetMethods())
                {
                    if (method.Name == configMethod.ExposedMethod)
                    { 
                        OperationDescription operation = CreateOperationDescription(contract, method, contractConfigElement, (null != contractSurrogate));
                        ConfigureOperationDescriptionBehaviors(operation, contractSurrogate); 
                        contract.Operations.Add(operation); 
                        methodFound = true;
                        break; 
                    }
                 }
                 if (!methodFound)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.MethodGivenInConfigNotFoundOnInterface, configMethod.ExposedMethod, iid))); 
            }
 
            if (contract.Operations.Count == 0) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.NoneOfTheMethodsForInterfaceFoundInConfig, iid)));
 
            ConfigureContractDescriptionBehaviors(contract);
            return contract;
        }
 
        void ConfigureContractDescriptionBehaviors(ContractDescription contract)
        { 
            // OperationSelectorBehavior 
            contract.Behaviors.Add(new OperationSelectorBehavior());
 
            // ComPlusContractBehavior
            ComPlusContractBehavior comPlusContractBehavior = new ComPlusContractBehavior(this.info);
            contract.Behaviors.Add(comPlusContractBehavior);
        } 

        void ConfigureOperationDescriptionBehaviors(OperationDescription operation, IDataContractSurrogate contractSurrogate) 
        { 
            // DataContractSerializerOperationBehavior
            DataContractSerializerOperationBehavior contractSerializer = new DataContractSerializerOperationBehavior(operation, TypeLoader.DefaultDataContractFormatAttribute); 

            if (null != contractSurrogate)
            {
                contractSerializer.DataContractSurrogate = contractSurrogate; 
            }
 
            operation.Behaviors.Add(contractSerializer); 

            // OperationInvokerBehavior 
            operation.Behaviors.Add(new OperationInvokerBehavior());

            if(info.TransactionOption == TransactionOption.Supported || info.TransactionOption == TransactionOption.Required)
            { 
                operation.Behaviors.Add(new TransactionFlowAttribute(TransactionFlowOption.Allowed));
            } 
 
            // OperationBehaviorAttribute
            OperationBehaviorAttribute operationBehaviorAttribute = new OperationBehaviorAttribute(); 
            operationBehaviorAttribute.TransactionAutoComplete = true;
            operationBehaviorAttribute.TransactionScopeRequired = false;
            operation.Behaviors.Add(operationBehaviorAttribute);
        } 

        // 
        // Note - the code below this line a paraphrase of the SM reflection code in TypeLoader.cs 
        // Ideally we would be re-using their code, but our assumptions are too disjoint
        // for that to be realistic at the time of writing (12/2004). 
        //

        OperationDescription CreateOperationDescription(ContractDescription contract, MethodInfo methodInfo, ComContractElement config, bool allowReferences)
        { 
            XmlName operationName = new XmlName(ServiceReflector.GetLogicalName(methodInfo));
            XmlName returnValueName = TypeLoader.GetReturnValueName(operationName); 
 
            if (ServiceReflector.IsBegin(methodInfo))
            { 
                DiagnosticUtility.DebugAssert("No async operations allowed");

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.NoAsyncOperationsAllowed());
            } 
            if (contract.Operations.FindAll(operationName.EncodedName).Count != 0)
            { 
                DiagnosticUtility.DebugAssert("Duplicate operation name"); 

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.DuplicateOperation()); 
            }

            OperationDescription operationDescription = new OperationDescription(operationName.EncodedName, contract);
            operationDescription.SyncMethod = methodInfo; 
            operationDescription.IsInitiating = true;
            operationDescription.IsTerminating = false; 
 
            operationDescription.KnownTypes.Add(typeof(Array));
            operationDescription.KnownTypes.Add(typeof(DBNull)); 
            operationDescription.KnownTypes.Add(typeof(CurrencyWrapper));
            operationDescription.KnownTypes.Add(typeof(ErrorWrapper));

            if (allowReferences) 
                operationDescription.KnownTypes.Add(typeof(PersistStreamTypeWrapper));
 
            foreach (ComUdtElement udt in config.UserDefinedTypes) 
            {
                Type knownType; 

                Guid typeLibID = new Guid(udt.TypeLibID);

                TypeCacheManager.Provider.FindOrCreateType(typeLibID, udt.TypeLibVersion, new Guid(udt.TypeDefID), out knownType, false); 

                this.info.AddUdt(knownType, typeLibID); 
                operationDescription.KnownTypes.Add(knownType); 
            }
 

            string ns = contract.Namespace;
            XmlQualifiedName contractQName = new XmlQualifiedName(contract.Name, ns);
 
            string requestAction = NamingHelper.GetMessageAction(contractQName,
                                                                 operationName.DecodedName, 
                                                                 null, 
                                                                 false);
 
            string responseAction = NamingHelper.GetMessageAction(contractQName,
                                                                  operationName.DecodedName,
                                                                  null,
                                                                  true); 

            MessageDescription inMessage = CreateIncomingMessageDescription(contract, 
                                                                            methodInfo, 
                                                                            ns,
                                                                            requestAction, 
                                                                            allowReferences);

            MessageDescription outMessage = CreateOutgoingMessageDescription(contract,
                                                                             methodInfo, 
                                                                             returnValueName,
                                                                             ns, 
                                                                             responseAction, 
                                                                             allowReferences);
 
            operationDescription.Messages.Add(inMessage);
            operationDescription.Messages.Add(outMessage);

            return operationDescription; 
        }
 
        MessageDescription CreateIncomingMessageDescription(ContractDescription contract, 
                                                            MethodInfo methodInfo,
                                                            string ns, 
                                                            string action,
                                                            bool allowReferences)
        {
            ParameterInfo[] parameters = ServiceReflector.GetInputParameters(methodInfo, false); 
            return CreateParameterMessageDescription(contract,
                                                     parameters, 
                                                     null, 
                                                     null,
                                                     null, 
                                                     methodInfo.Name,
                                                     ns,
                                                     action,
                                                     MessageDirection.Input, 
                                                     allowReferences);
        } 
 
        MessageDescription CreateOutgoingMessageDescription(ContractDescription contract,
                                                            MethodInfo methodInfo, 
                                                            XmlName returnValueName,
                                                            string ns,
                                                            string action,
                                                            bool allowReferences) 
        {
            ParameterInfo[] parameters = ServiceReflector.GetOutputParameters(methodInfo, false); 
            return CreateParameterMessageDescription(contract, 
                                                     parameters,
                                                     methodInfo.ReturnType, 
                                                     methodInfo.ReturnTypeCustomAttributes,
                                                     returnValueName,
                                                     methodInfo.Name,
                                                     ns, 
                                                     action,
                                                     MessageDirection.Output, 
                                                     allowReferences); 
        }
 
        MessageDescription CreateParameterMessageDescription(ContractDescription contract,
                                                             ParameterInfo[] parameters,
                                                             Type returnType,
                                                             ICustomAttributeProvider returnCustomAttributes, 
                                                             XmlName returnValueName,
                                                             string methodName, 
                                                             string ns, 
                                                             string action,
                                                             MessageDirection direction, 
                                                             bool allowReferences)
        {
            MessageDescription messageDescription = new MessageDescription(action, direction);
            messageDescription.Body.WrapperNamespace = ns; 

            for (int index = 0; index < parameters.Length; index++) 
            { 
                ParameterInfo parameter = parameters[index];
                Type parameterType = TypeLoader.GetParameterType(parameter); 

                if (!ComPlusTypeValidator.IsValidParameter(parameterType, parameter, allowReferences))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.InvalidWebServiceParameter, 
                                                                parameter.Name,
                                                                parameterType.Name, 
                                                                methodName, 
                                                                contract.Name)));
                } 

                MessagePartDescription messagePart = CreateMessagePartDescription(parameterType,
                                                                                  new XmlName(parameter.Name),
                                                                                  ns, 
                                                                                  index);
                messageDescription.Body.Parts.Add(messagePart); 
            } 

            XmlName xmlName = new XmlName(methodName); 
            if (returnType == null)
            {
                messageDescription.Body.WrapperName = xmlName.EncodedName;
            } 
            else
            { 
                messageDescription.Body.WrapperName = TypeLoader.GetBodyWrapperResponseName(xmlName).EncodedName; 

                if (!ComPlusTypeValidator.IsValidParameter(returnType, returnCustomAttributes, allowReferences)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.InvalidWebServiceReturnValue,
                                                                returnType.Name,
                                                                methodName, 
                                                                contract.Name)));
                } 
 
                MessagePartDescription messagePart = CreateMessagePartDescription(returnType,
                                                                                  returnValueName, 
                                                                                  ns,
                                                                                  0);
                messageDescription.Body.ReturnValue = messagePart;
            } 

            return messageDescription; 
        } 

        MessagePartDescription CreateMessagePartDescription(Type bodyType, 
                                                            XmlName name,
                                                            string ns,
                                                            int index)
        { 
            MessagePartDescription partDescription = new MessagePartDescription(name.EncodedName, ns);
            partDescription.SerializationPosition = index; 
            partDescription.MemberInfo = null; 
            partDescription.Type = bodyType;
            partDescription.Index = index; 
            return partDescription;
        }

        ContractDescription ResolveIMetadataExchangeToContract () 
        {
            // Use ServiceModel's TypeLoader to load the IMetadataExchange contract 
            TypeLoader typeLoader = new TypeLoader (); 
            return typeLoader.LoadContractDescription(typeof(IMetadataExchange));
        } 

        public ContractDescription ResolveContract(string contractTypeString)
        {
            Guid iid; 
            if (ServiceMetadataBehavior.MexContractName == contractTypeString)
                iid = typeof(IMetadataExchange).GUID; 
            else 
            {
                if ( !DiagnosticUtility.Utility.TryCreateGuid(contractTypeString, out iid)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(SR.GetString(SR.ContractTypeNotAnIID, contractTypeString)));
                }
		 
                ValidateInterface(iid);
            } 
 
            // Check our cache to see if we already have one
            ContractDescription contract; 
            if (this.contracts.TryGetValue(iid, out contract))
            {
                return contract;
            } 

            // If this is not IMetadataExchange continue 
            if (iid != typeof(IMetadataExchange).GUID) 
            {
                Type type; 
                // Generate a managed type corresponding to the interface in question
                try
                {
                    this.interfaceResolver.FindOrCreateType(this.info.ServiceType, iid, out type, false, true); 
                }
                catch (InvalidOperationException e) 
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ListenerInitFailed(e.Message));
                } 

                contract = CreateContractDescriptionInternal(iid, type);
            }
            else 
                contract = ResolveIMetadataExchangeToContract();
            contracts.Add(iid, contract); 
 
            ComPlusServiceHostTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationServiceHostCreatedServiceContract,
                                SR.TraceCodeComIntegrationServiceHostCreatedServiceContract, this.info, contract); 

            return contract;
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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