e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
220 lines
9.3 KiB
C#
220 lines
9.3 KiB
C#
namespace System.Workflow.ComponentModel.Design
|
|
{
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.CodeDom;
|
|
using System.CodeDom.Compiler;
|
|
using System.Reflection;
|
|
using Microsoft.CSharp;
|
|
using Microsoft.VisualBasic;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.ComponentModel;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel.Design;
|
|
using System.ComponentModel.Design.Serialization;
|
|
using System.Workflow;
|
|
using System.Workflow.ComponentModel.Compiler;
|
|
using System.Workflow.ComponentModel;
|
|
using System.Workflow.ComponentModel.Design;
|
|
using System.Workflow.ComponentModel.Serialization;
|
|
using System.Collections.Specialized;
|
|
|
|
internal sealed class IdentifierCreationService : IIdentifierCreationService
|
|
{
|
|
private IServiceProvider serviceProvider = null;
|
|
private WorkflowDesignerLoader loader = null;
|
|
private CodeDomProvider provider = null;
|
|
|
|
internal IdentifierCreationService(IServiceProvider serviceProvider, WorkflowDesignerLoader loader)
|
|
{
|
|
this.serviceProvider = serviceProvider;
|
|
this.loader = loader;
|
|
}
|
|
|
|
internal CodeDomProvider Provider
|
|
{
|
|
get
|
|
{
|
|
if (this.provider == null)
|
|
{
|
|
SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(this.serviceProvider);
|
|
if (language == SupportedLanguages.CSharp)
|
|
this.provider = CompilerHelpers.CreateCodeProviderInstance(typeof(CSharpCodeProvider));
|
|
else
|
|
this.provider = CompilerHelpers.CreateCodeProviderInstance(typeof(VBCodeProvider));
|
|
}
|
|
return this.provider;
|
|
}
|
|
}
|
|
|
|
#region IIdentifierCreationService
|
|
void IIdentifierCreationService.ValidateIdentifier(Activity activity, string identifier)
|
|
{
|
|
if (identifier == null)
|
|
throw new ArgumentNullException("identifier");
|
|
if (activity == null)
|
|
throw new ArgumentNullException("activity");
|
|
|
|
if (activity.Name.ToLowerInvariant().Equals(identifier.ToLowerInvariant()))
|
|
return;
|
|
|
|
if (this.Provider != null)
|
|
{
|
|
SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(this.serviceProvider);
|
|
if (language == SupportedLanguages.CSharp && identifier.StartsWith("@", StringComparison.Ordinal) ||
|
|
language == SupportedLanguages.VB && identifier.StartsWith("[", StringComparison.Ordinal) && identifier.EndsWith("]", StringComparison.Ordinal) ||
|
|
!this.Provider.IsValidIdentifier(identifier))
|
|
{
|
|
throw new Exception(SR.GetString(SR.Error_InvalidLanguageIdentifier, identifier));
|
|
}
|
|
}
|
|
|
|
StringDictionary identifiers = new StringDictionary();
|
|
CompositeActivity rootActivity = Helpers.GetRootActivity(activity) as CompositeActivity;
|
|
if (rootActivity != null)
|
|
{
|
|
foreach (string existingIdentifier in Helpers.GetIdentifiersInCompositeActivity(rootActivity))
|
|
identifiers[existingIdentifier] = existingIdentifier;
|
|
}
|
|
|
|
Type customActivityType = GetRootActivityType(this.serviceProvider);
|
|
if (customActivityType != null)
|
|
{
|
|
foreach (MemberInfo member in customActivityType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
|
|
{
|
|
Type memberType = null;
|
|
if (member is FieldInfo)
|
|
memberType = ((FieldInfo)member).FieldType;
|
|
|
|
if (memberType == null || !typeof(Activity).IsAssignableFrom(memberType))
|
|
identifiers[member.Name] = member.Name;
|
|
}
|
|
}
|
|
|
|
if (identifiers.ContainsKey(identifier))
|
|
throw new ArgumentException(SR.GetString(SR.DuplicateActivityIdentifier, identifier));
|
|
}
|
|
|
|
/// <summary>
|
|
/// This method will ensure that the identifiers of the activities to be added to the parent activity
|
|
/// are unique within the scope of the parent activity.
|
|
/// </summary>
|
|
/// <param name="parentActivity">THis activity is the parent activity which the child activities are being added</param>
|
|
/// <param name="childActivities"></param>
|
|
void IIdentifierCreationService.EnsureUniqueIdentifiers(CompositeActivity parentActivity, ICollection childActivities)
|
|
{
|
|
if (parentActivity == null)
|
|
throw new ArgumentNullException("parentActivity");
|
|
if (childActivities == null)
|
|
throw new ArgumentNullException("childActivities");
|
|
|
|
ArrayList allActivities = new ArrayList();
|
|
|
|
Queue activities = new Queue(childActivities);
|
|
while (activities.Count > 0)
|
|
{
|
|
Activity activity = (Activity)activities.Dequeue();
|
|
if (activity is CompositeActivity)
|
|
{
|
|
foreach (Activity child in ((CompositeActivity)activity).Activities)
|
|
activities.Enqueue(child);
|
|
}
|
|
|
|
//If we are moving activities, we need not regenerate their identifiers
|
|
if (((IComponent)activity).Site != null)
|
|
continue;
|
|
|
|
//If the activity is built-in, we won't generate a new ID.
|
|
if (IsPreBuiltActivity(activity))
|
|
continue;
|
|
|
|
allActivities.Add(activity);
|
|
}
|
|
|
|
// get the root activity
|
|
CompositeActivity rootActivity = Helpers.GetRootActivity(parentActivity) as CompositeActivity;
|
|
StringDictionary identifiers = new StringDictionary(); // all the identifiers in the workflow
|
|
|
|
Type customActivityType = GetRootActivityType(this.serviceProvider);
|
|
|
|
if (rootActivity != null)
|
|
{
|
|
foreach (string identifier in Helpers.GetIdentifiersInCompositeActivity(rootActivity))
|
|
identifiers[identifier] = identifier;
|
|
}
|
|
|
|
if (customActivityType != null)
|
|
{
|
|
foreach (MemberInfo member in customActivityType.GetMembers(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
|
|
{
|
|
Type memberType = null;
|
|
if (member is FieldInfo)
|
|
memberType = ((FieldInfo)member).FieldType;
|
|
|
|
if (memberType == null || !typeof(Activity).IsAssignableFrom(memberType))
|
|
identifiers[member.Name] = member.Name;
|
|
}
|
|
}
|
|
|
|
// now loop until we find a identifier that hasn't been used
|
|
foreach (Activity activity in allActivities)
|
|
{
|
|
int index = 0;
|
|
string baseIdentifier = Helpers.GetBaseIdentifier(activity);
|
|
string finalIdentifier = null;
|
|
|
|
if (string.IsNullOrEmpty(activity.Name) || string.Equals(activity.Name, activity.GetType().Name, StringComparison.Ordinal))
|
|
finalIdentifier = string.Format(CultureInfo.InvariantCulture, "{0}{1}", new object[] { baseIdentifier, ++index });
|
|
else
|
|
finalIdentifier = activity.Name;
|
|
|
|
while (identifiers.ContainsKey(finalIdentifier))
|
|
{
|
|
finalIdentifier = string.Format(CultureInfo.InvariantCulture, "{0}{1}", new object[] { baseIdentifier, ++index });
|
|
if (this.Provider != null)
|
|
finalIdentifier = this.Provider.CreateValidIdentifier(finalIdentifier);
|
|
}
|
|
|
|
// add new identifier to collection
|
|
identifiers[finalIdentifier] = finalIdentifier;
|
|
activity.Name = finalIdentifier;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
private Type GetRootActivityType(IServiceProvider serviceProvider)
|
|
{
|
|
IDesignerHost host = serviceProvider.GetService(typeof(IDesignerHost)) as IDesignerHost;
|
|
if (host == null)
|
|
throw new Exception(SR.GetString(SR.General_MissingService, typeof(IDesignerHost).FullName));
|
|
|
|
string className = host.RootComponentClassName;
|
|
if (string.IsNullOrEmpty(className))
|
|
return null;
|
|
|
|
ITypeProvider typeProvider = serviceProvider.GetService(typeof(ITypeProvider)) as ITypeProvider;
|
|
if (typeProvider == null)
|
|
throw new Exception(SR.GetString(SR.General_MissingService, typeof(ITypeProvider).FullName));
|
|
|
|
return typeProvider.GetType(className, false);
|
|
}
|
|
|
|
private static bool IsPreBuiltActivity(Activity activity)
|
|
{
|
|
CompositeActivity parent = activity.Parent;
|
|
while (parent != null)
|
|
{
|
|
// Any custom activity found, then locked
|
|
if (Helpers.IsCustomActivity(parent))
|
|
return true;
|
|
|
|
parent = parent.Parent;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|