⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 membercreationservice.cs

📁 workflow foundaction 工作流设计器
💻 CS
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------
//  This file is part of the WindowsWorkflow.NET web site samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//---------------------------------------------------------------------

namespace WorkflowDesignerControl
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Workflow.ComponentModel.Design;
    using System.CodeDom;
    using System.Reflection;
    using System.CodeDom.Compiler;
    using System.Workflow.ComponentModel.Compiler;
    using System.ComponentModel.Design;
    using System.Workflow.ComponentModel;
    using Microsoft.CSharp;

    #endregion

    #region MemberCreationService

    internal class MemberCreationService : IMemberCreationService
    {
        private const string DependencyPropertyInit_CS = "DependencyProperty.Register(\"{0}\", typeof({1}), typeof({2}){3})";
        private const string DependencyPropertyOption = ", new PropertyMetadata({0})";

        private WorkflowLoader loader = null;
        private IServiceProvider serviceProvider = null;
        private CodeDomProvider provider = null;
        protected const BindingFlags baseMemberBindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy;

        internal MemberCreationService(IServiceProvider serviceProvider, WorkflowLoader loader)
        {
            this.serviceProvider = serviceProvider;
            this.loader = loader;
            this.provider = new CSharpCodeProvider();
        }

        #region IMemberCreationService Members

        public void CreateField(string className, string fieldName, Type fieldType, Type[] genericParameterTypes, MemberAttributes attributes, CodeSnippetExpression initializationExpression, bool overwriteExisting)
        {
            if (string.IsNullOrEmpty(className))
                throw new ArgumentNullException("className");
            if (string.IsNullOrEmpty(fieldName))
                throw new ArgumentNullException("fieldName");
            if (fieldType == null)
                throw new ArgumentNullException("fieldType");
            if (fieldName == null)
                throw new ArgumentNullException("fieldName");

            if (!this.CodeProvider.IsValidIdentifier(fieldName))
                throw new ArgumentException();

            //If the classname is null then check if we can emit in the class being designed
            if (DoesFieldExist(className, fieldName))
            {
                if (overwriteExisting == true)
                    RemoveField(className, fieldName);
                else
                    throw new Exception("Error_DifferentTypeFieldExists");
            }

            Type type = null;
            if ((genericParameterTypes != null) && (fieldType.IsGenericTypeDefinition))
                type = fieldType.MakeGenericType(genericParameterTypes);
            else
                type = fieldType;

            // prepare field
            CodeMemberField field = new CodeMemberField();
            field.Name = fieldName;
            field.Type = GetCodeTypeReference(className, type);
            field.UserData["UserVisible"] = true;
            field.Attributes = attributes;

            if (initializationExpression == null)
            {
                string formattedType = FormatType(type);
                if (type.GetConstructor(Type.EmptyTypes) != null)
                    field.InitExpression = new CodeSnippetExpression("new " + formattedType + "()");
                else
                    field.InitExpression = new CodeSnippetExpression("default(" + formattedType + ")");
            }
            else
            {
                field.InitExpression = initializationExpression;
            }

            string nsName = null;
            Helpers.GetNamespaceAndClassName(className, out nsName, out className);

            // Get the type declaration from code compile unit
            CodeTypeDeclaration typeDeclaration = GetCodeTypeDeclFromCodeCompileUnit(nsName, className);

            int index = 0;
            foreach (CodeTypeMember member in typeDeclaration.Members)
            {
                if (member is CodeMemberField)
                    index++;
                else
                    break;
            }

            //push the field into the code compile unit
            typeDeclaration.Members.Insert(index, field);
            field.Type.UserData[typeof(Type)] = fieldType;

            // refresh the code compile unit
            TypeProvider typeProvider = (TypeProvider)this.serviceProvider.GetService(typeof(ITypeProvider));
            typeProvider.RefreshCodeCompileUnit(this.loader.CodeBesideCCU, new EventHandler(RefreshCCU));
        }

        public void RemoveField(string className, string fieldName)
        {
            if (string.IsNullOrEmpty(className))
                throw new ArgumentNullException("className");
            if (string.IsNullOrEmpty(fieldName))
                throw new ArgumentNullException("fieldName");

            string nsName = null;
            Helpers.GetNamespaceAndClassName(className, out nsName, out className);

            CodeTypeDeclaration typeDeclaration = GetCodeTypeDeclFromCodeCompileUnit(nsName, className);
            CodeTypeMemberCollection fields = typeDeclaration.Members;

            CodeMemberField fieldToRemove = null;
            if (fields != null)
            {
                foreach (CodeTypeMember member in fields)
                {
                    if (member is CodeMemberField)
                    {
                        CodeMemberField field = (CodeMemberField)member;
                        if (field.Name == fieldName)
                        {
                            fieldToRemove = field;
                        }
                        else if (String.Compare(field.Name, fieldName, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            fieldToRemove = field;
                        }
                    }
                }

                if (fieldToRemove != null)
                    fields.Remove(fieldToRemove);
            }
            if (fieldToRemove == null)
                throw new Exception(fieldName);

            ITypeProvider typeProvider = this.ServiceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider;
            if (typeProvider == null)
                throw new InvalidOperationException(typeof(ITypeProvider).FullName);
            ((TypeProvider)typeProvider).RefreshCodeCompileUnit(this.loader.CodeBesideCCU, new EventHandler(RefreshCCU));

        }

        public void CreateProperty(string className, string propertyName, Type propertyType, AttributeInfo[] attributes, bool emitDependencyProperty, bool isMetaProperty, bool isAttached, Type ownerType, bool isReadOnly)
        {
            if (string.IsNullOrEmpty(className))
                throw new ArgumentNullException("className");
            if (string.IsNullOrEmpty(propertyName))
                throw new ArgumentNullException("propertyName");
            if (propertyType == null)
                throw new ArgumentNullException("propertyType");

            if (!this.CodeProvider.IsValidIdentifier(propertyName))
                throw new ArgumentException("Invalid Identifier");

            if (!this.DoesPropertyExist(className, propertyName, propertyType))
            {
                // create property
                CodeMemberProperty property = new CodeMemberProperty();
                property.Name = propertyName;
                property.Type = GetCodeTypeReference(className, propertyType);
                property.Attributes = MemberAttributes.Public | MemberAttributes.Final;

                // add property attributes
                if (attributes != null)
                {
                    foreach (AttributeInfo attribute in attributes)
                    {
                        CodeTypeReference attributeTypeRef = GetCodeTypeReference(className, attribute.AttributeType);
                        CodeAttributeDeclaration attribDecl = new CodeAttributeDeclaration(attributeTypeRef);
                        foreach (object param in attribute.ArgumentValues)
                        {
                            if (param is CodeExpression)
                                attribDecl.Arguments.Add(new CodeAttributeArgument(param as CodeExpression));
                        }
                        property.CustomAttributes.Add(attribDecl);
                    }
                }

                // Create private field to hold the property's data
                IDesignerHost host = this.ServiceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host == null)
                    throw new InvalidOperationException(typeof(IDesignerHost).FullName);

                ITypeProvider typeProvider = this.ServiceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider;
                if (typeProvider == null)
                    throw new InvalidOperationException(typeof(ITypeProvider).FullName);

                string fieldName = null;
                if (emitDependencyProperty)
                {
                    fieldName = propertyName + "Property";
                    property.UserData["_vsDependencyPropertyFieldKey"] = fieldName;
                    if (!isAttached)
                        CreateStaticFieldForDependencyProperty(className, propertyName, propertyType, fieldName, isMetaProperty, false);
                }
                else
                {
                    bool existingField = false;
                    //We recreate the field everytime, this is done for the dynamic properties
                    fieldName = GeneratePropertyAssociatedFieldName(className, propertyName, propertyType, out existingField);
                    if (!existingField)
                        CreateField(className, fieldName, propertyType, null, MemberAttributes.Private, null, true);
                }

                // Add getter and setter logic to retrieve and assign the value to the new private field
                if (emitDependencyProperty)
                {
                    CodeFieldReferenceExpression fieldRef = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(isAttached ? ownerType.FullName : className), fieldName);

                    property.HasGet = true;
                    CodeTypeReference typeRef = new CodeTypeReference(propertyType);

                    property.GetStatements.Add(new CodeMethodReturnStatement(new CodeCastExpression(typeRef, new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), "GetValue", fieldRef))));

                    if (!isReadOnly)
                    {
                        property.HasSet = true;
                        property.SetStatements.Add(new CodeMethodInvokeExpression(new CodeBaseReferenceExpression(), "SetValue", fieldRef, new CodeSnippetExpression("value")));
                    }
                }
                else
                {
                    property.HasGet = true;
                    property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName)));

                    if (!isReadOnly)
                    {
                        property.HasSet = true;
                        CodeExpression ifNOTDesignModeExpression = new CodeBinaryOperatorExpression(new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "DesignMode"), CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(false));
                        property.SetStatements.Add(new CodeConditionStatement(ifNOTDesignModeExpression, new CodeThrowExceptionStatement(new CodeObjectCreateExpression(typeof(InvalidOperationException), new CodeExpression[] { }))));
                        property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName), new CodeSnippetExpression("value")));
                    }
                }

                string nsName = null;
                Helpers.GetNamespaceAndClassName(className, out nsName, out className);

                CodeTypeDeclaration typeDeclaration = GetCodeTypeDeclFromCodeCompileUnit(nsName, className);

                int index = 0;
                foreach (CodeTypeMember member in typeDeclaration.Members)
                {
                    if (member is CodeMemberProperty)
                        index++;
                    else
                        break;
                }

                typeDeclaration.Members.Insert(index, property);
                ((TypeProvider)typeProvider).RefreshCodeCompileUnit(this.loader.CodeBesideCCU, new EventHandler(RefreshCCU));
            }
        }

        public void UpdateProperty(string className, string oldPropertyName, Type oldPropertyType, string newPropertyName, Type newPropertyType, AttributeInfo[] attributes, bool emitDependencyProperty, bool isMetaProperty)
        {
            throw new NotImplementedException();
        }

        public void RemoveProperty(string className, string propertyName, Type propertyType)
        {
            throw new NotImplementedException();
        }

        public void CreateEvent(string className, string eventName, Type eventType, AttributeInfo[] attributes, bool emitDependencyProperty)
        {
            if (string.IsNullOrEmpty(className))
                throw new ArgumentNullException("className");
            if (string.IsNullOrEmpty(eventName))
                throw new ArgumentNullException("eventName");
            if (eventType == null)
                throw new ArgumentNullException("eventType");
            if (!this.CodeProvider.IsValidIdentifier(eventName))
                throw new ArgumentException();

            if (!this.DoesEventExist(className, eventName, eventType))
            {
                // create event
                CodeMemberEvent eventInfo = new CodeMemberEvent();
                eventInfo.Name = eventName;
                eventInfo.Type = new CodeTypeReference(eventType);
                eventInfo.Type.UserData["_vsEventHandlerTypeKey"] = eventType;
                eventInfo.Attributes = MemberAttributes.Public | MemberAttributes.Final;

                // add custom attributes
                if (attributes != null)
                {
                    foreach (AttributeInfo attribute in attributes)
                    {
                        CodeTypeReference attributeTypeRef = GetCodeTypeReference(className, attribute.AttributeType);
                        CodeAttributeDeclaration attribDecl = new CodeAttributeDeclaration(attributeTypeRef);
                        foreach (object param in attribute.ArgumentValues)
                        {
                            if (param is CodeExpression)
                                attribDecl.Arguments.Add(new CodeAttributeArgument(param as CodeExpression));
                        }
                        eventInfo.CustomAttributes.Add(attribDecl);
                    }
                }

                // Add getter and setter logic to retrieve and assign the value to the new private field
                if (emitDependencyProperty)
                {
                    // Create static field for the dependency property.
                    string fieldName = eventName + "Event";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -