ClientApiGenerator.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 / DataWeb / Design / system / Data / EntityModel / Emitters / ClientApiGenerator.cs / 1625574 / ClientApiGenerator.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System.CodeDom; 
using System.CodeDom.Compiler;
using System.Collections;
using System.Collections.Generic;
using System.Data.EntityModel.Emitters; 
using System.Data.Metadata.Edm;
using System.Data.Services.Design; 
using System.Diagnostics; 
using System.IO;
using System.Linq; 

namespace System.Data.Metadata.Edm
{
    internal static partial class Helper 
    {
        internal static bool IsCollectionType(GlobalItem item) 
        { 
            return (BuiltInTypeKind.CollectionType == item.BuiltInTypeKind);
        } 
        internal static bool IsComplexType(EdmType type)
        {
            return (BuiltInTypeKind.ComplexType == type.BuiltInTypeKind);
        } 
        internal static bool IsEntitySet(EntitySetBase entitySetBase)
        { 
            return BuiltInTypeKind.EntitySet == entitySetBase.BuiltInTypeKind; 
        }
        internal static bool IsPrimitiveType(EdmType type) 
        {
            return (BuiltInTypeKind.PrimitiveType == type.BuiltInTypeKind);
        }
    } 

    internal static class TypeSemantics 
    { 
        internal static bool IsComplexType(TypeUsage type)
        { 
            return Helper.IsComplexType(type.EdmType);
        }
    }
 
    internal static class EdmProviderManifest
    { 
        // System Facet Info 
        /// 
        /// Name of the MaxLength Facet 
        /// 
        internal const string MaxLengthFacetName = "MaxLength";

        ///  
        /// Name of the Unicode Facet
        ///  
        internal const string UnicodeFacetName = "Unicode"; 

        ///  
        /// Name of the FixedLength Facet
        /// 
        internal const string FixedLengthFacetName = "FixedLength";
 
        /// 
        /// Name of the DateTimeKind Facet 
        ///  
        internal const string DateTimeKindFacetName = "DateTimeKind";
 
        /// 
        /// Name of the PreserveSeconds Facet
        /// 
        internal const string PreserveSecondsFacetName = "PreserveSeconds"; 

        ///  
        /// Name of the Precision Facet 
        /// 
        internal const string PrecisionFacetName = "Precision"; 

        /// 
        /// Name of the Scale Facet
        ///  
        internal const string ScaleFacetName = "Scale";
 
        ///  
        /// Name of the Nullable Facet
        ///  
        internal const string NullableFacetName = "Nullable";

        /// 
        /// Name of the DefaultValue Facet 
        /// 
        internal const string DefaultValueFacetName = "DefaultValue"; 
 
        ///// 
        ///// Name of the DefaultType metadata property 
        ///// 
        //internal const string DefaultTypeMetadataPropertyName = "DefaultType";

        ///  
        /// Name of the Collation Facet
        ///  
        internal const string CollationFacetName = "Collation"; 
    }
 
    internal static class TypeSystem
    {
        private static readonly System.Reflection.MethodInfo s_getDefaultMethod = typeof(TypeSystem).GetMethod("GetDefault", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
        private static T GetDefault() { return default(T); } 

        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining | System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)] 
        internal static object GetDefaultValue(Type type) 
        {
            // null is always the default for non value types and Nullable<> 
            if (!type.IsValueType ||
                (type.IsGenericType &&
                 typeof(Nullable<>) == type.GetGenericTypeDefinition()))
            { 
                return null;
            } 
            System.Reflection.MethodInfo getDefaultMethod = s_getDefaultMethod.MakeGenericMethod(type); 
            object defaultValue = getDefaultMethod.Invoke(null, new object[] { });
            return defaultValue; 
        }
    }

    internal static class Schema 
    {
        public const string CodeGenerationSchemaNamespace = "http://schemas.microsoft.com/ado/2006/04/codegeneration"; 
    } 
}
 
namespace System.Data.EntityModel
{
    /// 
    /// Summary description for ClientApiGenerator. 
    /// 
    internal sealed class ClientApiGenerator : IDisposable 
    { 
        #region Instance Fields
        private CodeCompileUnit _compileUnit; 
        private bool _isLanguageCaseSensitive = true;

        private EdmItemCollection _edmItemCollection;
        private FixUpCollection _fixUps; 
        private AttributeEmitter _attributeEmitter;
        private EntityClassGenerator _generator; 
        private List _errors; 
        private TypeReference _typeReference = new TypeReference();
        private string _sourceEdmNamespaceName; 
        private string _defaultContainerNamespace;
        private string _namespacePrefix;
        private Dictionary _namespaceMap;
        private EventHandler _onTypeGenerated; 
        private EventHandler _onPropertyGenerated;
        #endregion 
 
        #region Public Methods
        public ClientApiGenerator(object sourceSchema, EdmItemCollection edmItemCollection, EntityClassGenerator generator, List errors, string namespacePrefix) 
        {
            Debug.Assert(edmItemCollection != null, "edmItemCollection is null");
            Debug.Assert(generator != null, "generator is null");
            Debug.Assert(errors != null, "errors is null"); 

            _edmItemCollection = edmItemCollection; 
            _generator = generator; 
            _errors = errors;
            _attributeEmitter = new AttributeEmitter(_typeReference); 
            _namespacePrefix = namespacePrefix;

            // generate map for inherited types and prefixed types
            _namespaceMap = new Dictionary(); 

            _onTypeGenerated = new EventHandler(TypeGeneratedEventHandler); 
            _onPropertyGenerated = new EventHandler(PropertyGeneratedEventHandler); 

            //// This constructor can be called multiple times with the same EntityClassGenerator. That is, many instances 
            //// of the ClientApiGenerator can add handlers to one instance of the EntityClassGenerator.
            //// Make sure the handlers are not left on the EntityClassGenerator after the ClientApiGenerator is no longer in use.
            //// See the Dispose method
 
            _generator.OnTypeGenerated += _onTypeGenerated;
            _generator.OnPropertyGenerated += _onPropertyGenerated; 
        } 

        public void Dispose() 
        {
            //// Make sure the handlers are not left on the EntityClassGenerator after the ClientApiGenerator is no longer in use.

            _generator.OnTypeGenerated -= _onTypeGenerated; 
            _generator.OnPropertyGenerated -= _onPropertyGenerated;
        } 
 
        internal EdmItemCollection EdmItemCollection
        { 
            get { return this._edmItemCollection; }
        }

        public string NamespacePrefix 
        {
            get { return this._namespacePrefix; } 
        } 

        public Dictionary NamespaceMap 
        {
            get { return this._namespaceMap; }
        }
 
        /// 
        /// Does code generation emits collections inherited from DataServiceCollection 
        ///  
        internal bool UseDataServiceCollection
        { 
            get { return _generator.UseDataServiceCollection; }
        }

        /// Version for which to generate code. 
        internal DataServiceCodeVersion Version
        { 
            get { return _generator.Version; } 
        }
 
        /// 
        /// Parses a source Schema and outputs client-side generated code to
        /// the output TextWriter.
        ///  
        /// The source Schema
        /// The TextWriter in which to write the output 
        /// The Uri for the output. Can be null. 
        /// A list of GeneratorErrors.
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification="Reviewed")] 
        internal void GenerateCode(LazyTextWriterCreator target)
        {
            Debug.Assert(target != null, "target parameter is null");
 
            IndentedTextWriter indentedTextWriter = null;
            System.IO.Stream tempFileStream = null; 
            System.IO.StreamReader reader = null; 
            System.IO.StreamWriter writer = null;
            TempFileCollection tempFiles = null; 
            try
            {
                CodeDomProvider provider = null;
                switch (Language) 
                {
                    case LanguageOption.GenerateCSharpCode: 
                        provider = new Microsoft.CSharp.CSharpCodeProvider(); 
                        break;
 
                    case LanguageOption.GenerateVBCode:
                        provider = new Microsoft.VisualBasic.VBCodeProvider();
                        break;
                } 

                _isLanguageCaseSensitive = (provider.LanguageOptions & LanguageOptions.CaseInsensitive) == 0; 
 
                new NamespaceEmitter(this, this.NamespacePrefix, target.TargetFilePath).Emit();
 
                // if there were errors we don't need the output file
                if (RealErrorsExist)
                {
                    return; 
                }
 
                if (FixUps.Count == 0 || !FixUpCollection.IsLanguageSupported(Language)) 
                {
                    indentedTextWriter = new IndentedTextWriter(target.GetOrCreateTextWriter(), "\t"); 
                }
                else
                {
                    // need to write to a temporary file so we can do fixups... 
                    tempFiles = new TempFileCollection(Path.GetTempPath());
                    string filename = Path.Combine(tempFiles.TempDir, "EdmCodeGenFixup-" + Guid.NewGuid().ToString() + ".tmp"); 
                    tempFiles.AddFile(filename, false); 
                    tempFileStream = new System.IO.FileStream(filename, System.IO.FileMode.CreateNew, System.IO.FileAccess.ReadWrite,
                        System.IO.FileShare.None); 
                    indentedTextWriter = new IndentedTextWriter(new System.IO.StreamWriter(tempFileStream), "\t");
                }

                CodeGeneratorOptions styleOptions = new CodeGeneratorOptions(); 
                styleOptions.BracingStyle = "C";
                styleOptions.BlankLinesBetweenMembers = false; 
                styleOptions.VerbatimOrder = true; 
                provider.GenerateCodeFromCompileUnit(CompileUnit, indentedTextWriter, styleOptions);
 
                // if we wrote to a temp file need to post process the file...
                if (tempFileStream != null)
                {
                    indentedTextWriter.Flush(); 
                    tempFileStream.Seek(0, System.IO.SeekOrigin.Begin);
                    reader = new System.IO.StreamReader(tempFileStream); 
                    FixUps.Do(reader, target.GetOrCreateTextWriter(), Language, !String.IsNullOrEmpty(SourceObjectNamespaceName)); 
                }
            } 
            catch (System.UnauthorizedAccessException ex)
            {
                AddError(ModelBuilderErrorCode.SecurityError, EdmSchemaErrorSeverity.Error, ex);
            } 
            catch (System.IO.FileNotFoundException ex)
            { 
                AddError(ModelBuilderErrorCode.FileNotFound, EdmSchemaErrorSeverity.Error, ex); 
            }
            catch (System.Security.SecurityException ex) 
            {
                AddError(ModelBuilderErrorCode.SecurityError, EdmSchemaErrorSeverity.Error, ex);
            }
            catch (System.IO.DirectoryNotFoundException ex) 
            {
                AddError(ModelBuilderErrorCode.DirectoryNotFound, EdmSchemaErrorSeverity.Error, ex); 
            } 
            catch (System.IO.IOException ex)
            { 
                AddError(ModelBuilderErrorCode.IOException, EdmSchemaErrorSeverity.Error, ex);
            }
            finally
            { 
                if (indentedTextWriter != null)
                { 
                    indentedTextWriter.Close(); 
                }
                if (tempFileStream != null) 
                {
                    tempFileStream.Close();
                }
                if (tempFiles != null) 
                {
                    tempFiles.Delete(); 
                    ((IDisposable)tempFiles).Dispose(); 
                }
                if (reader != null) 
                {
                    reader.Close();
                }
                if (writer != null) 
                {
                    writer.Close(); 
                } 
            }
        } 

        /// 
        /// Verification code invoked for types
        ///  
        /// The type being generated
        internal void VerifyLanguageCaseSensitiveCompatibilityForType(GlobalItem item) 
        { 
            if (_isLanguageCaseSensitive)
            { 
                return; // no validation necessary
            }

            try 
            {
                _edmItemCollection.GetItem( 
                                                        Identity(item), 
                                                        true   // ignore case
                                                    ); 
            }
            catch (InvalidOperationException ex)
            {
                AddError(ModelBuilderErrorCode.IncompatibleSettingForCaseSensitiveOption, EdmSchemaErrorSeverity.Error, ex); 
            }
        } 
 
        /// 
        /// Verification code invoked for properties 
        /// 
        /// The property or navigation property being generated
        internal void VerifyLanguageCaseSensitiveCompatibilityForProperty(EdmMember item)
        { 
            if (_isLanguageCaseSensitive)
            { 
                return; // no validation necessary 
            }
 
            Debug.Assert(item != null);

            ReadOnlyMetadataCollection members = item.DeclaringType.Members;
            HashSet set = new HashSet(StringComparer.OrdinalIgnoreCase); 

            foreach (EdmMember member in members) 
            { 
                if (set.Contains(Identity(member)) &&
                    String.Equals(Identity(item), Identity(member), StringComparison.OrdinalIgnoreCase)) 
                {
                    AddError(ModelBuilderErrorCode.IncompatibleSettingForCaseSensitiveOption, EdmSchemaErrorSeverity.Error,
                                new InvalidOperationException(Strings.PropertyExistsWithDifferentCase(Identity(item))));
                } 
                else
                { 
                    set.Add(Identity(member)); 
                }
            } 
        }

        /// 
        /// Verification code invoked for entity sets 
        /// 
        /// The entity container being generated 
        internal void VerifyLanguageCaseSensitiveCompatibilityForEntitySet(System.Data.Metadata.Edm.EntityContainer item) 
        {
            if (_isLanguageCaseSensitive) 
            {
                return; // no validation necessary
            }
 
            Debug.Assert(item != null);
 
            HashSet set = new HashSet(StringComparer.OrdinalIgnoreCase); 

            foreach (EntitySetBase entitySetBase in item.BaseEntitySets) 
            {
                if (Helper.IsEntitySet(entitySetBase))
                {
                    EntitySet entitySet = (EntitySet)entitySetBase; 
                    if (set.Contains(Identity(entitySet)))
                    { 
                        AddError(ModelBuilderErrorCode.IncompatibleSettingForCaseSensitiveOption, EdmSchemaErrorSeverity.Error, 
                                    new InvalidOperationException(Strings.EntitySetExistsWithDifferentCase(Identity(entitySet))));
                    } 
                    else
                    {
                        set.Add(Identity(entitySet));
                    } 
                }
            } 
        } 

        #endregion 

        #region Internal Properties

        internal LanguageOption Language 
        {
            get 
            { 
                return _generator.LanguageOption;
            } 
        }

        internal TypeReference TypeReference
        { 
            get { return _typeReference; }
        } 
 
        internal CodeCompileUnit CompileUnit
        { 
            get
            {
                if (_compileUnit == null)
                    _compileUnit = new CodeCompileUnit(); 

                return _compileUnit; 
            } 
        }
 
        public void AddError(string message, ModelBuilderErrorCode errorCode, EdmSchemaErrorSeverity severity)
        {
        }
 
        public void AddError(ModelBuilderErrorCode errorCode, EdmSchemaErrorSeverity severity, Exception ex)
        { 
        } 

        internal void AddError(string message, ModelBuilderErrorCode errorCode, EdmSchemaErrorSeverity severity, Exception ex) 
        {
        }

        ///  
        /// Check collection for any real errors (Severity != Warning)
        ///  
        public bool RealErrorsExist 
        {
            get 
            {
                foreach (EdmSchemaError error in _errors)
                {
                    if (error.Severity != EdmSchemaErrorSeverity.Warning) 
                        return true;
                } 
                return false; 
            }
        } 

        public IEnumerable GetSourceTypes()
        {
            foreach (EntityContainer container in _edmItemCollection.GetItems()) 
            {
                BuiltInTypeKind kind = container.BuiltInTypeKind; 
                yield return container; 
            }
 
            foreach (EdmType item in _edmItemCollection.GetItems())
            {
                switch (item.BuiltInTypeKind)
                { 
                    case BuiltInTypeKind.AssociationType:
                    case BuiltInTypeKind.ComplexType: 
                    case BuiltInTypeKind.EntityType: 
                        yield return item;
                        break; 
                    case BuiltInTypeKind.EdmFunction:
                    case BuiltInTypeKind.PrimitiveType:
                        break;
                    default: 
                        Debug.Assert(false, item.BuiltInTypeKind.ToString());
                        break; 
                } 
            }
        } 

        public string GetClientTypeNamespace(string serviceTypeNamespace)
        {
            if (string.IsNullOrEmpty(this.NamespacePrefix)) return serviceTypeNamespace; 

            if (string.IsNullOrEmpty(serviceTypeNamespace) || 
                ((this.DefaultContainerNamespace != null) && (this.DefaultContainerNamespace == serviceTypeNamespace))) 
            {
                return this.NamespacePrefix; 
            }
            else
            {
                return this.NamespacePrefix + "." + serviceTypeNamespace; 
            }
        } 
 
        public string GetContainerNamespace(EntityContainer container)
        { 
            if (container == null) return null;

            string namespaceName = null;
            EntitySetBase baseEntitySet = container.BaseEntitySets.FirstOrDefault(); 
            if (null != baseEntitySet)
            { 
                namespaceName = baseEntitySet.ElementType.NamespaceName; 
            }
 
            return namespaceName;
        }

        public CodeTypeReference GetLeastPossibleQualifiedTypeReference(EdmType type) 
        {
            string typeRef; 
            string clientNamespace = GetClientTypeNamespace(type.NamespaceName); 
            if (clientNamespace == SourceEdmNamespaceName)
            { 
                // we are already generating in this namespace, no need to qualify it
                typeRef = type.Name;
            }
            else 
            {
                typeRef = GetObjectNamespace(clientNamespace) + "." + type.Name; 
            } 

            return TypeReference.FromString(typeRef); 
        }

        public string SourceEdmNamespaceName
        { 
            get
            { 
                if (null != _sourceEdmNamespaceName) 
                {
                    return _sourceEdmNamespaceName; 
                }

                //
                foreach (GlobalItem item in GetSourceTypes()) 
                {
                    EdmType edm = item as EdmType; 
                    if (null != edm) 
                    {
                        return edm.NamespaceName; 
                    }
                }

                return null; 
            }
            set 
            { 
                _sourceEdmNamespaceName = value;
            } 
        }

        public string DefaultContainerNamespace
        { 
            get { return _defaultContainerNamespace; }
            set { _defaultContainerNamespace = value; } 
        } 

        public string SourceObjectNamespaceName 
        {
            get
            {
                string sourceEdmNamespaceName = SourceEdmNamespaceName; 
                if (!String.IsNullOrEmpty(sourceEdmNamespaceName))
                { 
                    return GetObjectNamespace(sourceEdmNamespaceName); 
                }
 
                return null;
            }
        }
 
        private string GetObjectNamespace(string csdlNamespaceName)
        { 
            Debug.Assert(csdlNamespaceName != null, "csdlNamespaceName is null"); 

            string objectNamespace; 
            if (_generator.EdmToObjectNamespaceMap.TryGetObjectNamespace(csdlNamespaceName, out objectNamespace))
            {
                return objectNamespace;
            } 

            return csdlNamespaceName; 
        } 

 
        /// 
        ///
        /// 
        ///  
        internal FixUpCollection FixUps
        { 
            get 
            {
                if (_fixUps == null) 
                    _fixUps = new FixUpCollection();

                return _fixUps;
            } 
        }
 
        internal AttributeEmitter AttributeEmitter 
        {
            get { return _attributeEmitter; } 
        }

        internal bool IsLanguageCaseSensitive
        { 
            get { return _isLanguageCaseSensitive; }
        } 
 
        internal StringComparison LanguageAppropriateStringComparer
        { 
            get
            {
                if (IsLanguageCaseSensitive)
                { 
                    return StringComparison.Ordinal;
                } 
                else 
                {
                    return StringComparison.OrdinalIgnoreCase; 
                }
            }
        }
 
        /// 
        /// Helper method that raises the TypeGenerated event 
        ///  
        /// The event arguments passed to the subscriber
        internal void RaiseTypeGeneratedEvent(TypeGeneratedEventArgs eventArgs) 
        {
            _generator.RaiseTypeGeneratedEvent(eventArgs);
        }
 
        /// 
        /// Helper method that raises the PropertyGenerated event 
        ///  
        /// The event arguments passed to the subscriber
        internal void RaisePropertyGeneratedEvent(PropertyGeneratedEventArgs eventArgs) 
        {
            _generator.RaisePropertyGeneratedEvent(eventArgs);
        }
 
        /// 
        /// Gets the collection type to be returned for a multi-valued navigation property. 
        ///  
        /// Type name which is decided based on UseDataServiceCollection setting.
        internal string GetRelationshipMultiplicityManyCollectionTypeName() 
        {
            return this.UseDataServiceCollection ? "System.Data.Services.Client.DataServiceCollection" : "System.Collections.ObjectModel.Collection";
        }
 
        #endregion
 
        private static string Identity(EdmMember member) 
        {
            return member.ToString(); 
        }
        private static string Identity(EntitySetBase entitySet)
        {
            return entitySet.ToString(); 
        }
        private static string Identity(MetadataItem item) 
        { 
            return item.ToString();
        } 

        private void TypeGeneratedEventHandler(object sender, TypeGeneratedEventArgs eventArgs)
        {
            if (!this.UseDataServiceCollection) 
            {
                return; 
            } 

            if (eventArgs.TypeSource.BuiltInTypeKind != BuiltInTypeKind.EntityType && 
                eventArgs.TypeSource.BuiltInTypeKind != BuiltInTypeKind.ComplexType)
            {
                return;
            } 

            if (eventArgs.TypeSource.BuiltInTypeKind == BuiltInTypeKind.EntityType) 
            { 
                // Generate EntitySetAttribute only if there is exactly one entity set associated
                // with the entity type. The DataServiceEntitySetAttribute is not generated for ComplexType(s). 
                EntitySetBase entitySet = this.GetUniqueEntitySetForType((EntityType)eventArgs.TypeSource);
                if (entitySet != null)
                {
                    List additionalAttributes = eventArgs.AdditionalAttributes; 
                    CodeAttributeDeclaration attribute = new CodeAttributeDeclaration(
                        new CodeTypeReference(typeof(System.Data.Services.Common.EntitySetAttribute), 
                            CodeTypeReferenceOptions.GlobalReference), new CodeAttributeArgument(new CodePrimitiveExpression(entitySet.Name))); 
                    additionalAttributes.Add(attribute);
                } 
            }

            //// Determine if type being generated has a base type
            if (eventArgs.BaseType != null && !String.IsNullOrEmpty(eventArgs.BaseType.BaseType)) 
            {
                if (this.GetSourceTypes().Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).Where(x => ((EntityType)x).Name == eventArgs.BaseType.BaseType).Count() != 0) 
                { 
                    //// Don't generate the PropertyChanged event and OnPropertyChanged method for derived type classes
                    return; 
                }
            }

            //// Add the INotifyPropertyChanged interface 

            List additionalInterfaces = eventArgs.AdditionalInterfaces; 
 
            additionalInterfaces.Add(typeof(System.ComponentModel.INotifyPropertyChanged));
 
            //// Add the implementation of the INotifyPropertyChanged interface

            //// Generate this code:
            //// 
            //// CSharp:
            //// 
            //// public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged; 
            ////
            //// protected virtual void OnPropertyChanged(string property) { 
            ////     if ((this.PropertyChanged != null)) {
            ////         this.PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(property));
            ////     }
            //// } 
            ////
            //// Visual Basic: 
            //// 
            //// Public Event PropertyChanged As Global.System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
            //// Protected Overridable Sub OnPropertyChanged(ByVal [property] As String) 
            ////     If (Not (Me.PropertyChangedEvent) Is Nothing) Then
            ////         RaiseEvent PropertyChanged(Me, New Global.System.ComponentModel.PropertyChangedEventArgs([property]))
            ////     End If
            //// End Sub 

 
            CodeMemberEvent propertyChangedEvent = new CodeMemberEvent(); 
            propertyChangedEvent.Type = new CodeTypeReference(typeof(System.ComponentModel.PropertyChangedEventHandler), CodeTypeReferenceOptions.GlobalReference);
            propertyChangedEvent.Name = "PropertyChanged"; 
            propertyChangedEvent.Attributes = MemberAttributes.Public;
            propertyChangedEvent.ImplementationTypes.Add(typeof(System.ComponentModel.INotifyPropertyChanged));

            AttributeEmitter.AddGeneratedCodeAttribute(propertyChangedEvent); 

            eventArgs.AdditionalMembers.Add(propertyChangedEvent); 
 
            CodeMemberMethod propertyChangedMethod = new CodeMemberMethod();
            propertyChangedMethod.Name = "OnPropertyChanged"; 
            propertyChangedMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(System.String), CodeTypeReferenceOptions.GlobalReference), "property"));
            propertyChangedMethod.ReturnType = new CodeTypeReference(typeof(void));

            AttributeEmitter.AddGeneratedCodeAttribute(propertyChangedMethod); 

            propertyChangedMethod.Statements.Add( 
                    new CodeConditionStatement( 
                        new CodeBinaryOperatorExpression(
                            new CodeEventReferenceExpression(new CodeThisReferenceExpression(), "PropertyChanged"), 
                                CodeBinaryOperatorType.IdentityInequality,
                                new CodePrimitiveExpression(null)),
                            new CodeExpressionStatement(
                            new CodeDelegateInvokeExpression( 
                                new CodeEventReferenceExpression(new CodeThisReferenceExpression(), "PropertyChanged"),
                                    new CodeExpression[] { 
                                    new CodeThisReferenceExpression(), 
                                    new CodeObjectCreateExpression(new CodeTypeReference(typeof(System.ComponentModel.PropertyChangedEventArgs), CodeTypeReferenceOptions.GlobalReference), new CodeArgumentReferenceExpression("property"))
                                })))); 
            propertyChangedMethod.Attributes = MemberAttributes.Family;
            eventArgs.AdditionalMembers.Add(propertyChangedMethod);
        }
 
        private void PropertyGeneratedEventHandler(object sender, PropertyGeneratedEventArgs eventArgs)
        { 
            if (!this.UseDataServiceCollection) 
            {
                return; 
            }

            if (eventArgs.PropertySource.BuiltInTypeKind != BuiltInTypeKind.EdmProperty &&
                eventArgs.PropertySource.BuiltInTypeKind != BuiltInTypeKind.NavigationProperty) 
            {
                return; 
            } 

            if (((EdmMember)eventArgs.PropertySource).DeclaringType.BuiltInTypeKind != BuiltInTypeKind.EntityType && 
                ((EdmMember)eventArgs.PropertySource).DeclaringType.BuiltInTypeKind != BuiltInTypeKind.ComplexType)
            {
                return;
            } 

            string name = eventArgs.PropertySource.BuiltInTypeKind == BuiltInTypeKind.EdmProperty ? ((EdmProperty)eventArgs.PropertySource).Name : ((NavigationProperty)eventArgs.PropertySource).Name; 
 
            // Add call to the OnPropertyChanged method
            eventArgs.AdditionalAfterSetStatements.Add(new CodeExpressionStatement(new CodeMethodInvokeExpression( 
                new CodeThisReferenceExpression(), "OnPropertyChanged",
                new CodeExpression[] { new CodePrimitiveExpression(name) }
                )));
        } 

        /// Given an entity type, returns the corresponding entity set if it's unique. 
        /// Given entity type. 
        /// Corresponding entity set if it's unique, null otherwise.
        private EntitySetBase GetUniqueEntitySetForType(EntityType entityType) 
        {
            HashSet entitySets = new HashSet(EqualityComparerEntitySet.Default);

            foreach (EntityContainer container in this.EdmItemCollection.GetItems()) 
            {
                bool alreadyAdded = false; 
                foreach (EntitySetBase es in container.BaseEntitySets 
                                                      .Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntitySet &&
                                                                  x.ElementType == entityType)) 
                {
                    if (alreadyAdded == true)
                    {
                        return null; 
                    }
 
                    alreadyAdded = true; 
                    entitySets.Add(es);
                } 
            }

            if (entitySets.Count == 1)
            { 
                return entitySets.Single();
            } 
            else 
            {
                return null; 
            }
        }

        /// Equality comparer used for deciding whether to add EntitySet attribute to an entity type. 
        public class EqualityComparerEntitySet : IEqualityComparer
        { 
            /// Cached singleton comparer. 
            private static EqualityComparerEntitySet _comparer = new EqualityComparerEntitySet();
 
            /// Gets the singleton comparer.
            public static EqualityComparerEntitySet Default
            {
                get 
                {
                    return _comparer; 
                } 
            }
 
            #region IEqualityComparer Members

            /// Equality check.
            /// Left. 
            /// Right.
            /// true if names are same, false otherwise. 
            public bool Equals(EntitySetBase x, EntitySetBase y) 
            {
                return (x == null && y == null) || 
                       (x != null && y != null && x.Name == y.Name);
            }

            /// Gets hash code for EntitySetBase. 
            /// Object for which to get hash code.
            /// Hash code for the name. 
            public int GetHashCode(EntitySetBase obj) 
            {
                return (null != obj) ? obj.Name.GetHashCode() : 0; 
            }

            #endregion
        } 
    }
} 

// 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