Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@@ -0,0 +1,79 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime
{
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.ServiceModel;
using System.ServiceModel.Description;
class CompiledWorkflowDefinitionContext : WorkflowDefinitionContext
{
static Type activityType = typeof(Activity);
Activity rootActivity;
Type workflowType;
internal CompiledWorkflowDefinitionContext(Type workflowType)
{
if (workflowType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowType");
}
if (!activityType.IsAssignableFrom(workflowType))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowType", SR2.GetString(SR2.NotAnActivityType));
}
this.workflowType = workflowType;
}
public override string ConfigurationName
{
get
{
return this.workflowType.FullName;
}
}
public override string WorkflowName
{
get
{
return NamingHelper.XmlName(this.workflowType.Name);
}
}
public override WorkflowInstance CreateWorkflow()
{
return this.CreateWorkflow(Guid.NewGuid());
}
public override WorkflowInstance CreateWorkflow(Guid instanceId)
{
return base.WorkflowRuntime.CreateWorkflow(this.workflowType, null, instanceId);
}
public override Activity GetWorkflowDefinition()
{
if (rootActivity == null)
{
rootActivity = (Activity) Activator.CreateInstance(workflowType);
}
return rootActivity;
}
protected override void OnRegister()
{
}
protected override void OnValidate(ValidationErrorCollection errors)
{
}
}
}

View File

@@ -0,0 +1,450 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime.Hosting
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.Workflow.Activities;
using System.Diagnostics;
using System.Workflow.ComponentModel;
class ChannelManager
{
static Uri defaultViaUri = new Uri("channelCache://default_address");
PooledChannelPool channelPool;
bool closed;
Hashtable endpointMappings;
Dictionary<EndpointAddress, ServiceEndpoint> endpoints;
Dictionary<EndpointAddress, ChannelFactoryReference> factoryCache;
List<PooledChannel> newChannels;
public ChannelManager(ChannelPoolSettings settings, IList<ServiceEndpoint> endpoints)
{
this.channelPool = new PooledChannelPool(settings);
this.factoryCache = new Dictionary<EndpointAddress, ChannelFactoryReference>();
this.newChannels = new List<PooledChannel>();
this.endpoints = new Dictionary<EndpointAddress, ServiceEndpoint>();
this.endpointMappings = Hashtable.Synchronized(new Hashtable());
if (endpoints != null)
{
foreach (ServiceEndpoint endpoint in endpoints)
{
if (endpoint != null)
{
EndpointAddress cacheAddress = null;
if (endpoint.Contract.ContractType != null)
{
cacheAddress = ChannelManagerHelpers.BuildCacheAddress(endpoint.Name, endpoint.Contract.ContractType);
}
else
{
cacheAddress = ChannelManagerHelpers.BuildCacheAddress(endpoint.Name, endpoint.Contract.Name);
}
this.endpoints.Add(cacheAddress, endpoint);
}
}
}
}
object ThisLock
{
get
{
return this.channelPool;
}
}
public void Close()
{
lock (this.ThisLock)
{
if (this.closed)
{
return;
}
this.closed = true;
this.newChannels.Clear();
this.channelPool.Close(ServiceDefaults.CloseTimeout);
foreach (ChannelFactoryReference factory in this.factoryCache.Values)
{
factory.Close(ServiceDefaults.CloseTimeout);
}
this.factoryCache.Clear();
this.endpointMappings.Clear();
this.endpoints.Clear();
}
}
public void ReturnChannel(ChannelPoolKey key, PooledChannel channel)
{
bool connectionIsStillGood = (channel.State == CommunicationState.Opened);
bool newConnection = false;
lock (this.ThisLock)
{
newConnection = this.newChannels.Remove(channel);
}
if (newConnection)
{
if (connectionIsStillGood)
{
this.channelPool.AddConnection(key, channel, ServiceDefaults.OpenTimeout);
}
else
{
channel.Abort();
}
}
else
{
this.channelPool.ReturnConnection(key, channel, connectionIsStillGood, ServiceDefaults.CloseTimeout);
}
}
public PooledChannel TakeChannel(string endpointName, Type contractType, string customAddress, out ChannelPoolKey key)
{
EndpointAddress cacheAddress = ChannelManagerHelpers.BuildCacheAddress(endpointName, contractType);
Uri via = (customAddress != null) ? new Uri(customAddress) : defaultViaUri;
if (this.closed)
{
key = null;
return null;
}
this.endpointMappings[cacheAddress] = new KeyValuePair<string, Type>(endpointName, contractType);
return this.TakeChannel(cacheAddress, via, out key);
}
public PooledChannel TakeChannel(EndpointAddress address, Uri via, out ChannelPoolKey key)
{
PooledChannel channel = null;
key = null;
if (!this.closed)
{
ChannelFactoryReference factory = this.TakeChannelFactory(address);
if (factory != null)
{
bool channelCreated = false;
try
{
EndpointAddress cacheAddress = address;
if (factory.SupportsClientAuthentication)
{
cacheAddress = ChannelManagerHelpers.BuildCacheAddressWithIdentity(address);
}
channel = this.channelPool.TakeConnection(cacheAddress, via, ServiceDefaults.OpenTimeout, out key);
while (channel != null && channel.State != CommunicationState.Opened)
{
// Loop will exit because non-opened channels are returned with 'connectionStillGood=false'
this.channelPool.ReturnConnection(key, channel, false, ServiceDefaults.CloseTimeout);
channel = this.channelPool.TakeConnection(cacheAddress, via, ServiceDefaults.OpenTimeout, out key);
}
if (channel == null)
{
channel = this.CreateChannel(factory, address, via, out channelCreated);
}
}
finally
{
if (!channelCreated)
{
this.ReturnChannelFactory(address, factory);
}
}
}
}
return channel;
}
PooledChannel CreateChannel(ChannelFactoryReference factory, EndpointAddress address, Uri via, out bool channelCreated)
{
PooledChannel pooledChannel = null;
channelCreated = false;
IChannel channel = ChannelManagerHelpers.CreateChannel(factory.ContractType, factory.ChannelFactory, (via == defaultViaUri) ? null : via.ToString());
if (channel != null)
{
pooledChannel = new PooledChannel(this, factory, address, channel);
lock (this.ThisLock)
{
this.newChannels.Add(pooledChannel);
}
channelCreated = true;
}
return pooledChannel;
}
ChannelFactoryReference CreateChannelFactory(EndpointAddress address)
{
KeyValuePair<string, Type> endpointData;
if (this.endpointMappings.ContainsKey(address))
{
endpointData = (KeyValuePair<string, Type>) this.endpointMappings[address];
if (endpointMappings != null)
{
return new ChannelFactoryReference(
ChannelManagerHelpers.CreateChannelFactory(endpointData.Key, endpointData.Value, this.endpoints),
endpointData.Value);
}
}
return null;
}
void ReturnChannelFactory(EndpointAddress key, ChannelFactoryReference channelFactory)
{
if (channelFactory == null)
{
return;
}
lock (this.ThisLock)
{
bool closeFactory = channelFactory.Release();
bool invalidFactory = (channelFactory.ChannelFactory.State != CommunicationState.Opened);
if (closeFactory || invalidFactory)
{
ChannelFactoryReference currentFactory = null;
this.factoryCache.TryGetValue(key, out currentFactory);
if (currentFactory == channelFactory)
{
this.factoryCache.Remove(key);
}
if (closeFactory)
{
channelFactory.Close(ServiceDefaults.CloseTimeout);
}
}
}
}
ChannelFactoryReference TakeChannelFactory(EndpointAddress address)
{
ChannelFactoryReference factory;
lock (ThisLock)
{
if (this.factoryCache.TryGetValue(address, out factory))
{
if (factory == null || factory.ChannelFactory.State != CommunicationState.Opened)
{
this.factoryCache.Remove(address);
factory = null;
}
}
if (factory == null)
{
factory = this.CreateChannelFactory(address);
if (factory != null)
{
this.factoryCache[address] = factory;
}
}
else
{
factory.AddRef();
}
}
return factory;
}
internal class ChannelFactoryReference
{
ChannelFactory channelFactory;
Type contractType;
int refCount;
bool supportsClientAuthentication;
public ChannelFactoryReference(ChannelFactory channelFactory, Type contractType)
{
this.refCount = 1;
this.channelFactory = channelFactory;
this.contractType = contractType;
ISecurityCapabilities securityCapabilities = channelFactory.Endpoint.Binding.GetProperty<ISecurityCapabilities>(new BindingParameterCollection());
if (securityCapabilities != null)
{
this.supportsClientAuthentication = securityCapabilities.SupportsClientAuthentication;
}
}
public ChannelFactory ChannelFactory
{
get
{
return this.channelFactory;
}
}
public Type ContractType
{
get
{
return this.contractType;
}
}
public bool SupportsClientAuthentication
{
get
{
return this.supportsClientAuthentication;
}
}
public void Abort()
{
ChannelManagerHelpers.CloseCommunicationObject(this.channelFactory);
}
public void Close(TimeSpan timeout)
{
ChannelManagerHelpers.CloseCommunicationObject(this.channelFactory, timeout);
}
internal void AddRef()
{
this.refCount++;
}
internal bool Release()
{
this.refCount--;
return (this.refCount == 0);
}
}
internal class PooledChannel
{
IChannel channel;
bool closed;
EndpointAddress factoryKey;
ChannelFactoryReference factoryReference;
ChannelManager owner;
internal PooledChannel(ChannelManager owner, ChannelFactoryReference factoryReference, EndpointAddress factoryKey, IChannel channel)
{
this.owner = owner;
this.factoryReference = factoryReference;
this.factoryKey = factoryKey;
this.channel = channel;
}
public IChannel InnerChannel
{
get
{
return this.channel;
}
}
public CommunicationState State
{
get
{
return this.channel.State;
}
}
public void Abort()
{
this.Close(ServiceDefaults.CloseTimeout);
}
public void Close(TimeSpan timeout)
{
if (this.closed)
{
return;
}
bool flag = true;
try
{
if (this.channel.State == CommunicationState.Opened)
{
this.channel.Close(timeout);
flag = false;
}
}
catch (CommunicationException communicationException)
{
DiagnosticUtility.TraceHandledException(communicationException, TraceEventType.Information);
}
catch (TimeoutException timeoutException)
{
DiagnosticUtility.TraceHandledException(timeoutException, TraceEventType.Information);
}
finally
{
if (flag)
{
this.channel.Abort();
}
this.owner.ReturnChannelFactory(this.factoryKey, this.factoryReference);
this.closed = true;
}
}
}
class PooledChannelPool : IdlingCommunicationPool<ChannelPoolKey, PooledChannel>
{
public PooledChannelPool(ChannelPoolSettings settings)
: base(settings.MaxOutboundChannelsPerEndpoint, settings.IdleTimeout, settings.LeaseTimeout)
{
}
protected override void AbortItem(PooledChannel item)
{
item.Abort();
}
protected override void CloseItem(PooledChannel item, TimeSpan timeout)
{
item.Close(timeout);
}
protected override ChannelPoolKey GetPoolKey(EndpointAddress address, Uri via)
{
return new ChannelPoolKey(address, via);
}
}
}
}

View File

@@ -0,0 +1,328 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime.Hosting
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Claims;
using System.Reflection;
using System.Runtime;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
static class ChannelManagerHelpers
{
static Hashtable contractInfoCollection = Hashtable.Synchronized(new Hashtable());
static object thisLock = new object();
public static EndpointAddress BuildCacheAddress(string endpointName, Type contractType)
{
Fx.Assert(!string.IsNullOrEmpty(endpointName), "endpointName should not be null");
Fx.Assert(contractType != null, "contractType should not be null");
return BuildCacheAddress(endpointName, contractType.AssemblyQualifiedName);
}
public static EndpointAddress BuildCacheAddress(string endpointName, string contractName)
{
Fx.Assert(!string.IsNullOrEmpty(endpointName), "endpointName should not be null");
Fx.Assert(!string.IsNullOrEmpty(contractName), "contractName should not be null");
return new EndpointAddress("channelCache://" + endpointName + "/" + contractName);
}
public static EndpointAddress BuildCacheAddressWithIdentity(EndpointAddress address)
{
Fx.Assert(address != null, "address should not be null");
WindowsIdentity identity = WindowsIdentity.GetCurrent();
try
{
Claim claim = Claim.CreateWindowsSidClaim(identity.User);
EndpointIdentity endpointIdentity = EndpointIdentity.CreateIdentity(claim);
return new EndpointAddress(address.Uri, endpointIdentity);
}
finally
{
identity.Dispose();
}
}
public static void CloseCommunicationObject(ICommunicationObject communicationObject)
{
CloseCommunicationObject(communicationObject, ServiceDefaults.CloseTimeout);
}
public static void CloseCommunicationObject(ICommunicationObject communicationObject, TimeSpan timeout)
{
if (communicationObject == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("communicationObject");
}
bool flag = true;
try
{
if (communicationObject.State == CommunicationState.Opened)
{
communicationObject.Close(timeout);
flag = false;
}
}
catch (CommunicationException communicatioException)
{
DiagnosticUtility.TraceHandledException(communicatioException, TraceEventType.Information);
}
catch (TimeoutException timeoutException)
{
DiagnosticUtility.TraceHandledException(timeoutException, TraceEventType.Information);
}
finally
{
if (flag)
{
communicationObject.Abort();
}
}
}
public static IChannel CreateChannel(Type contractType, ChannelFactory factory, string customAddress)
{
if (contractType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
}
if (factory == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("factory");
}
IChannel channel = null;
bool channelFailed = true;
try
{
ContractInfo contractInfo = GetContractInfo(contractType);
if (string.IsNullOrEmpty(customAddress))
{
channel = contractInfo.CreateChannelMethodInfo.Invoke(factory, null) as IChannel;
}
else
{
channel = contractInfo.CreateChannelWithCustomAddressMethodInfo.Invoke(factory,
new object[1] { new EndpointAddress(customAddress) }) as IChannel;
}
if (!contractInfo.IsSessionless)
{
IContextManager contextManager = channel.GetProperty<IContextManager>();
if (contextManager != null)
{
contextManager.Enabled = false;
}
}
channel.Open();
channelFailed = false;
}
catch (TargetInvocationException exception)
{
if (exception.InnerException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception.InnerException);
}
throw;
}
finally
{
if (channel != null && channelFailed)
{
channel.Abort();
channel = null;
}
}
return channel;
}
public static ChannelFactory CreateChannelFactory(string endpointName, Type contractType)
{
return CreateChannelFactory(endpointName, contractType, null);
}
public static ChannelFactory CreateChannelFactory(string endpointName, Type contractType, IDictionary<EndpointAddress, ServiceEndpoint> codeEndpoints)
{
if (string.IsNullOrEmpty(endpointName))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointName");
}
if (contractType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
}
ChannelFactory factory = null;
bool factoryFailed = true;
try
{
ContractInfo contractInfo = GetContractInfo(contractType);
Type channelFactoryType = contractInfo.ChannelFactoryType;
object[] args = null;
EndpointAddress key = BuildCacheAddress(endpointName, contractType);
ServiceEndpoint endpoint = null;
if (codeEndpoints != null &&
codeEndpoints.TryGetValue(key, out endpoint) &&
!IsEndpointDefinedInConfiguration(endpointName, contractType))
{
args = new object[] { endpoint };
}
else
{
args = new object[] { endpointName ?? string.Empty };
}
factory = Activator.CreateInstance(channelFactoryType, args) as ChannelFactory;
factory.Open();
factoryFailed = false;
}
catch (TargetInvocationException exception)
{
if (exception.InnerException != null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception.InnerException);
}
throw;
}
finally
{
if (factory != null && factoryFailed)
{
factory.Abort();
}
}
return factory;
}
public static bool IsEndpointDefinedInConfiguration(string endpointName, Type contractType)
{
if (string.IsNullOrEmpty(endpointName))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointName");
}
if (contractType == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contractType");
}
bool wildcard = string.Equals(endpointName, "*", StringComparison.Ordinal);
ClientSection section = ClientSection.GetSection();
foreach (ChannelEndpointElement element in section.Endpoints)
{
if ((!wildcard && (element.Name != endpointName)) || (element.Contract != contractType.FullName))
{
continue;
}
return true;
}
return false;
}
public static bool IsSessionlessContract(Type contractType)
{
return GetContractInfo(contractType).IsSessionless;
}
static ContractInfo GetContractInfo(Type contractType)
{
ContractInfo contractInfo = contractInfoCollection[contractType] as ContractInfo;
if (contractInfo == null)
{
lock (thisLock)
{
contractInfo = contractInfoCollection[contractType] as ContractInfo;
if (contractInfo == null)
{
contractInfo = new ContractInfo(contractType);
contractInfoCollection.Add(contractType, contractInfo);
}
}
}
return contractInfo;
}
class ContractInfo
{
Type channelFactoryType;
Type contractType;
MethodInfo createChannelMethodInfo;
MethodInfo createChannelWithCustomAddressMethodInfo;
bool isSessionless;
public ContractInfo(Type contractType)
{
this.contractType = contractType;
Type[] typeArguments = new Type[] { contractType };
this.channelFactoryType = typeof(ChannelFactory<>).MakeGenericType(typeArguments);
this.createChannelMethodInfo = this.channelFactoryType.GetMethod("CreateChannel", new Type[0] { });
this.createChannelWithCustomAddressMethodInfo = this.channelFactoryType.GetMethod("CreateChannel", new Type[1] { typeof(EndpointAddress) });
this.isSessionless = (ContractDescription.GetContract(contractType).SessionMode == SessionMode.NotAllowed);
}
public Type ChannelFactoryType
{
get
{
return this.channelFactoryType;
}
}
public MethodInfo CreateChannelMethodInfo
{
get
{
return this.createChannelMethodInfo;
}
}
public MethodInfo CreateChannelWithCustomAddressMethodInfo
{
get
{
return this.createChannelWithCustomAddressMethodInfo;
}
}
public bool IsSessionless
{
get
{
return this.isSessionless;
}
}
}
}
}

View File

@@ -0,0 +1,453 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime.Hosting
{
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Workflow.Activities;
using System.Workflow.ComponentModel;
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
public sealed class ChannelManagerService : WorkflowRuntimeService
{
const string IdleTimeoutSetting = "idleTimeout";
const string InfiniteTimeSpanValue = "infinite";
const string LeaseTimeoutSetting = "leaseTimeout";
const string MaxIdleChannelsPerEndpointSetting = "maxIdleChannelsPerEndpoint";
ChannelManager channelManager;
bool closed;
IList<ServiceEndpoint> codeEndpoints;
ChannelPoolSettings settings;
public ChannelManagerService()
: this(new ChannelPoolSettings(), new List<ServiceEndpoint>())
{
}
public ChannelManagerService(ChannelPoolSettings settings)
: this(settings, new List<ServiceEndpoint>())
{
}
public ChannelManagerService(IList<ServiceEndpoint> endpoints)
: this(new ChannelPoolSettings(), endpoints)
{
}
public ChannelManagerService(ChannelPoolSettings settings, IList<ServiceEndpoint> endpoints)
{
if (settings == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("settings");
}
if (endpoints == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoints");
}
this.settings = settings;
this.codeEndpoints = endpoints;
}
public ChannelManagerService(NameValueCollection parameters)
{
if (parameters == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters");
}
ChannelPoolSettings channelPoolSettings = new ChannelPoolSettings();
foreach (string key in parameters.Keys)
{
if (string.IsNullOrEmpty(key))
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
SR2.GetString(SR2.Error_UnknownConfigurationParameter, key), "parameters");
}
else if (key.Equals(ChannelManagerService.IdleTimeoutSetting, StringComparison.OrdinalIgnoreCase))
{
try
{
channelPoolSettings.IdleTimeout =
ConvertToTimeSpan(parameters[ChannelManagerService.IdleTimeoutSetting]);
}
catch (FormatException ex)
{
ArgumentException exception = new ArgumentException(
SR2.GetString(SR2.Error_InvalidIdleTimeout, parameters[ChannelManagerService.IdleTimeoutSetting]),
"parameters",
ex);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
}
}
else if (key.Equals(ChannelManagerService.LeaseTimeoutSetting, StringComparison.OrdinalIgnoreCase))
{
try
{
channelPoolSettings.LeaseTimeout =
ConvertToTimeSpan(parameters[ChannelManagerService.LeaseTimeoutSetting]);
}
catch (FormatException ex)
{
ArgumentException exception = new ArgumentException(
SR2.GetString(SR2.Error_InvalidLeaseTimeout, parameters[ChannelManagerService.LeaseTimeoutSetting]),
"parameters",
ex);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
}
}
else if (key.Equals(ChannelManagerService.MaxIdleChannelsPerEndpointSetting, StringComparison.OrdinalIgnoreCase))
{
try
{
channelPoolSettings.MaxOutboundChannelsPerEndpoint =
Convert.ToInt32(parameters[ChannelManagerService.MaxIdleChannelsPerEndpointSetting], System.Globalization.CultureInfo.CurrentCulture);
}
catch (FormatException ex)
{
ArgumentException exception = new ArgumentException(
SR2.GetString(SR2.Error_InvalidMaxIdleChannelsPerEndpoint, parameters[ChannelManagerService.MaxIdleChannelsPerEndpointSetting]),
"parameters",
ex);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(exception);
}
}
else
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(
SR2.GetString(SR2.Error_UnknownConfigurationParameter, key), "parameters");
}
}
this.settings = channelPoolSettings;
this.codeEndpoints = new List<ServiceEndpoint>();
}
protected internal override void Start()
{
base.Start();
this.channelManager = new ChannelManager(this.settings, this.codeEndpoints);
this.closed = false;
}
protected internal override void Stop()
{
base.Stop();
if (!this.closed && this.channelManager != null)
{
this.channelManager.Close();
}
this.closed = true;
}
internal static void ApplyLogicalChannelContext(LogicalChannel logicalChannel)
{
Fx.Assert(OperationContext.Current != null, "Can be called within a valid OperationContext Scope");
WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0,
"ChannelManagerService: updating context associated with logical channel {0}",
logicalChannel.InstanceId);
if (logicalChannel.Context != null)
{
new ContextMessageProperty(logicalChannel.Context).AddOrReplaceInMessageProperties(OperationContext.Current.OutgoingMessageProperties);
}
}
internal static TransientChannelTicket CreateTransientChannel(LogicalChannel logicalChannel)
{
DiagnosticUtility.DebugAssert(logicalChannel != null, "logical channel cannot be null");
ChannelFactory factory = null;
IChannel channel = null;
bool channelOpened = false;
try
{
factory = ChannelManagerHelpers.CreateChannelFactory(logicalChannel.ConfigurationName, logicalChannel.ContractType);
channel = ChannelManagerHelpers.CreateChannel(logicalChannel.ContractType, factory, logicalChannel.CustomAddress);
channelOpened = true;
}
finally
{
if (!channelOpened)
{
if (channel != null)
{
ChannelManagerHelpers.CloseCommunicationObject(channel);
}
if (factory != null)
{
ChannelManagerHelpers.CloseCommunicationObject(factory);
}
}
}
return new TransientChannelTicket(channel, factory);
}
internal static ChannelTicket Take(ActivityExecutionContext executionContext, Guid workflowId, LogicalChannel logicalChannel)
{
if (executionContext == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("executionContext");
}
if (workflowId == Guid.Empty)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
SR2.GetString(SR2.Error_Cache_InvalidWorkflowId));
}
if (logicalChannel == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel");
}
ChannelManagerService channelManager = executionContext.GetService<ChannelManagerService>();
ChannelTicket channel;
if (channelManager != null)
{
channel = channelManager.TakeChannel(workflowId, logicalChannel);
}
else
{
channel = ChannelManagerService.CreateTransientChannel(logicalChannel);
}
return channel;
}
internal static void UpdateLogicalChannelContext(LogicalChannel logicalChannel)
{
Fx.Assert(OperationContext.Current != null, "Can be called from valid OperationContextScope");
WorkflowTrace.Host.TraceEvent(TraceEventType.Verbose, 0,
"ChannelManagerService: updating context associated with logical channel {0}",
logicalChannel.InstanceId);
ContextMessageProperty contextMessageProperty;
MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
if (properties != null && ContextMessageProperty.TryGet(properties, out contextMessageProperty))
{
logicalChannel.Context = contextMessageProperty.Context;
}
}
internal void ReturnChannel(PooledChannelTicket pooledChannel)
{
DiagnosticUtility.DebugAssert(pooledChannel != null, "pooled channel cannot be null");
if (pooledChannel == null)
{
return;
}
WorkflowTrace.Host.TraceEvent(
TraceEventType.Information, 0,
"ChannelManagerService: return channel for workflow instance {0}, logical channel {1}",
new object[] { pooledChannel.WorkflowId, pooledChannel.LogicalChannelId });
this.channelManager.ReturnChannel(pooledChannel.ChannelPoolKey, pooledChannel.PooledChannel);
}
internal PooledChannelTicket TakeChannel(Guid workflowId, LogicalChannel logicalChannel)
{
if (this.closed)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel_ServiceStopped, logicalChannel.ConfigurationName, logicalChannel.CustomAddress)));
}
if (workflowId == Guid.Empty)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("workflowId",
SR2.GetString(SR2.Error_Cache_InvalidWorkflowId));
}
if (logicalChannel == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("logicalChannel");
}
WorkflowTrace.Host.TraceEvent(TraceEventType.Information, 0, "ChannelManagerService: get channel for workflow instance {0}, logical channel {1}", new object[] { workflowId, logicalChannel.InstanceId });
string endpointName = logicalChannel.ConfigurationName;
Type contractType = logicalChannel.ContractType;
string customAddress = logicalChannel.CustomAddress;
ChannelPoolKey channelKey;
ChannelManager.PooledChannel channel = this.channelManager.TakeChannel(endpointName, contractType, customAddress, out channelKey);
if (channel == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
new InvalidOperationException(SR2.GetString(SR2.Error_CannotProvideChannel, logicalChannel.ConfigurationName, logicalChannel.CustomAddress)));
}
PooledChannelTicket pooledChannel = new PooledChannelTicket(this, channel, channelKey, workflowId, logicalChannel.InstanceId);
return pooledChannel;
}
TimeSpan ConvertToTimeSpan(string value)
{
if (string.Equals(value, ChannelManagerService.InfiniteTimeSpanValue, StringComparison.OrdinalIgnoreCase))
{
return TimeSpan.MaxValue;
}
return TimeSpan.Parse(value, CultureInfo.InvariantCulture);
}
internal abstract class ChannelTicket : IDisposable
{
bool disposed;
protected ChannelTicket()
{
}
public abstract IChannel Channel
{
get;
}
public void Dispose()
{
if (!this.disposed)
{
this.disposed = true;
this.Close();
}
}
protected virtual void Close()
{
}
}
internal class PooledChannelTicket : ChannelTicket
{
ChannelManager.PooledChannel channel;
ChannelPoolKey channelPoolKey;
Guid logicalChannelId;
ChannelManagerService service;
Guid workflowId;
public PooledChannelTicket(ChannelManagerService service, ChannelManager.PooledChannel channel, ChannelPoolKey channelPoolKey, Guid workflowId, Guid logicalChannelId)
: base()
{
this.service = service;
this.channel = channel;
this.channelPoolKey = channelPoolKey;
this.workflowId = workflowId;
this.logicalChannelId = logicalChannelId;
}
public override IChannel Channel
{
get
{
return this.channel.InnerChannel;
}
}
internal ChannelPoolKey ChannelPoolKey
{
get
{
return this.channelPoolKey;
}
}
internal Guid LogicalChannelId
{
get
{
return this.logicalChannelId;
}
}
internal ChannelManager.PooledChannel PooledChannel
{
get
{
return this.channel;
}
}
internal Guid WorkflowId
{
get
{
return this.workflowId;
}
}
protected override void Close()
{
DiagnosticUtility.DebugAssert(this.channel != null, "channel has been closed already.");
if (this.channel != null)
{
this.service.ReturnChannel(this);
this.channel = null;
}
}
}
internal class TransientChannelTicket : ChannelTicket
{
IChannel channel;
ChannelFactory factory;
public TransientChannelTicket(IChannel channel, ChannelFactory factory)
: base()
{
this.channel = channel;
this.factory = factory;
}
public override IChannel Channel
{
get
{
return this.channel;
}
}
protected override void Close()
{
if (this.channel != null)
{
ChannelManagerHelpers.CloseCommunicationObject(this.channel);
this.channel = null;
}
if (this.factory != null)
{
ChannelManagerHelpers.CloseCommunicationObject(this.factory);
this.factory = null;
}
}
}
}
}

View File

@@ -0,0 +1,152 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime.Hosting
{
using System.Runtime;
using System.Runtime.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Threading;
using System.Diagnostics;
class SynchronizationContextWorkflowSchedulerService : DefaultWorkflowSchedulerService
{
SynchronizationContext syncContext;
public SynchronizationContextWorkflowSchedulerService()
{
}
protected internal override void Cancel(Guid timerId)
{
base.Cancel(timerId);
if (DiagnosticUtility.ShouldTraceInformation)
{
string traceText = SR.GetString(SR.TraceCodeSyncContextSchedulerServiceTimerCancelled, timerId);
TraceUtility.TraceEvent(TraceEventType.Information,
TraceCode.SyncContextSchedulerServiceTimerCancelled, traceText,
new StringTraceRecord("TimerDetail", traceText),
this, null);
}
}
protected internal override void Schedule(WaitCallback callback, Guid workflowInstanceId, DateTime whenUtc, Guid timerId)
{
base.Schedule(callback, workflowInstanceId, whenUtc, timerId);
if (DiagnosticUtility.ShouldTraceInformation)
{
string traceText = SR.GetString(SR.TraceCodeSyncContextSchedulerServiceTimerCreated, timerId, workflowInstanceId);
TraceUtility.TraceEvent(TraceEventType.Information,
TraceCode.SyncContextSchedulerServiceTimerCreated, traceText,
new StringTraceRecord("TimerDetail", traceText),
this, null);
}
}
protected internal override void Schedule(WaitCallback callback, Guid workflowInstanceId)
{
if (callback == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callback");
}
WorkflowDispatchContext currentDispatchContext = WorkflowDispatchContext.Current;
if (currentDispatchContext != null && currentDispatchContext.IsSynchronous)
{
callback(workflowInstanceId);
}
else
{
if (this.syncContext != null)
{
SynchronizationContextPostHelper.Post(this.syncContext, Fx.ThunkCallback(new SendOrPostCallback(callback)), workflowInstanceId);
}
else
{
base.Schedule(callback, workflowInstanceId);
}
}
}
internal void SetSynchronizationContext(SynchronizationContext synchronizationContext)
{
this.syncContext = synchronizationContext;
}
internal static class SynchronizationContextPostHelper
{
static SendOrPostCallback wrapperCallback =
Fx.ThunkCallback(new SendOrPostCallback(SynchronizationContextPostHelper.Callback));
public static void Post(SynchronizationContext synchronizationContext, SendOrPostCallback callback, object state)
{
Fx.Assert(synchronizationContext != null, "Null [....] Context");
Fx.Assert(callback != null, "Null Callback");
synchronizationContext.OperationStarted();
synchronizationContext.Post(wrapperCallback, new PostCallbackState(synchronizationContext, callback, state));
}
static void Callback(object state)
{
if (state == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("state");
}
PostCallbackState postCallbackState = state as PostCallbackState;
Fx.Assert(postCallbackState != null, "Invalid state object passed to callback function");
try
{
postCallbackState.Callback(postCallbackState.State);
}
finally
{
postCallbackState.SynchronizationContext.OperationCompleted();
}
}
class PostCallbackState
{
SendOrPostCallback callback;
object callbackState;
SynchronizationContext synchronizationContext;
public PostCallbackState(SynchronizationContext synchronizationContext, SendOrPostCallback callback, object callbackState)
{
this.synchronizationContext = synchronizationContext;
this.callback = callback;
this.callbackState = callbackState;
}
public SendOrPostCallback Callback
{
get
{
return this.callback;
}
}
public object State
{
get
{
return this.callbackState;
}
}
public SynchronizationContext SynchronizationContext
{
get
{
return this.synchronizationContext;
}
}
}
}
}
}

View File

@@ -0,0 +1,334 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime
{
using System.Collections;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.IO;
using System.Runtime;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
class StreamedWorkflowDefinitionContext : WorkflowDefinitionContext
{
object lockObject = new object();
// Double-checked locking pattern requires volatile for read/write synchronization
volatile System.Workflow.ComponentModel.Activity rootActivity = null;
byte[] ruleDefinition = null;
ITypeProvider typeProvider = null;
byte[] workflowDefinition = null;
internal StreamedWorkflowDefinitionContext(Stream workflowDefinition, Stream ruleDefinition, ITypeProvider typeProvider)
{
if (workflowDefinition == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowDefinition");
}
this.workflowDefinition = new byte[workflowDefinition.Length];
workflowDefinition.Read(this.workflowDefinition, 0, (int) workflowDefinition.Length);
if (ruleDefinition != null)
{
this.ruleDefinition = new byte[ruleDefinition.Length];
ruleDefinition.Read(this.ruleDefinition, 0, (int) ruleDefinition.Length);
}
this.typeProvider = typeProvider;
}
internal StreamedWorkflowDefinitionContext(string workflowDefinitionPath, string ruleDefinitionPath, ITypeProvider typeProvider)
{
FileStream workflowDefStream = null;
FileStream ruleDefStream = null;
if (workflowDefinitionPath == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowDefinitionPath");
}
try
{
workflowDefStream = new FileStream(workflowDefinitionPath, FileMode.Open, FileAccess.Read);
if (ruleDefinitionPath != null)
{
ruleDefStream = new FileStream(ruleDefinitionPath, FileMode.Open, FileAccess.Read);
}
this.workflowDefinition = new byte[workflowDefStream.Length];
workflowDefStream.Read(workflowDefinition, 0, (int) workflowDefStream.Length);
if (ruleDefStream != null)
{
this.ruleDefinition = new byte[ruleDefStream.Length];
ruleDefStream.Read(this.ruleDefinition, 0, (int) ruleDefStream.Length);
}
this.typeProvider = typeProvider;
}
finally
{
if (workflowDefStream != null)
{
workflowDefStream.Close();
}
if (ruleDefStream != null)
{
ruleDefStream.Close();
}
}
}
// This is a valid catch of all exceptions
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
// We don't have tracing in Silver as of M2
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "Reliability104:CaughtAndHandledExceptionsRule")]
public override string ConfigurationName
{
get
{
if (rootActivity == null)
{
try
{
GetWorkflowDefinition();
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
#if !_PRESHARP_
// this throw in a getter is valid
throw;
#endif
}
}
}
return rootActivity != null ? rootActivity.QualifiedName : null;
}
}
// This is a valid catch of all exceptions
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
// We don't have tracing in Silver as of M2
[System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "Reliability104:CaughtAndHandledExceptionsRule")]
public override string WorkflowName
{
get
{
if (rootActivity == null)
{
try
{
GetWorkflowDefinition();
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
#if !_PRESHARP_
// this throw in a getter is valid
throw;
#endif
}
}
}
return rootActivity != null ? NamingHelper.XmlName(rootActivity.QualifiedName) : null;
}
}
public override WorkflowInstance CreateWorkflow()
{
return this.CreateWorkflow(Guid.NewGuid());
}
public override WorkflowInstance CreateWorkflow(Guid instanceId)
{
System.IO.Stream definitionStream = null;
System.IO.Stream ruleStream = null;
System.Xml.XmlReader definitionReader = null;
System.Xml.XmlReader ruleReader = null;
try
{
definitionStream = new System.IO.MemoryStream(workflowDefinition);
definitionStream.Position = 0;
definitionReader = System.Xml.XmlReader.Create(definitionStream);
if (ruleDefinition != null)
{
ruleStream = new System.IO.MemoryStream(ruleDefinition);
ruleStream.Position = 0;
ruleReader = System.Xml.XmlReader.Create(ruleStream);
}
return this.WorkflowRuntime.CreateWorkflow(definitionReader, ruleReader, null, instanceId);
}
finally
{
if (definitionStream != null)
{
definitionStream.Dispose();
}
if (ruleStream != null)
{
ruleStream.Dispose();
}
}
}
public override System.Workflow.ComponentModel.Activity GetWorkflowDefinition()
{
if (rootActivity == null)
{
lock (lockObject)
{
if (rootActivity == null)
{
rootActivity = DeSerizalizeDefinition(workflowDefinition, ruleDefinition);
}
}
}
return rootActivity;
}
protected override void OnRegister()
{
if (this.typeProvider != null)
{
if (this.WorkflowRuntime.IsStarted)
{
this.WorkflowRuntime.StopRuntime();
}
this.WorkflowRuntime.AddService(this.typeProvider);
}
}
protected override void OnValidate(ValidationErrorCollection errors)
{
if (!string.IsNullOrEmpty(this.rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string))
{
errors.Add(new ValidationError(SR2.XomlWorkflowHasClassName, ErrorNumbers.Error_XomlWorkflowHasClassName));
}
Queue compositeActivities = new Queue();
compositeActivities.Enqueue(this.rootActivity);
while (compositeActivities.Count > 0)
{
System.Workflow.ComponentModel.Activity activity = compositeActivities.Dequeue() as System.Workflow.ComponentModel.Activity;
if (activity.GetValue(WorkflowMarkupSerializer.XCodeProperty) != null)
{
errors.Add(new ValidationError(SR2.XomlWorkflowHasCode, ErrorNumbers.Error_XomlWorkflowHasCode));
}
CompositeActivity compositeActivity = activity as CompositeActivity;
if (compositeActivity != null)
{
foreach (System.Workflow.ComponentModel.Activity childActivity in compositeActivity.EnabledActivities)
{
compositeActivities.Enqueue(childActivity);
}
}
}
}
System.Workflow.ComponentModel.Activity DeSerizalizeDefinition(byte[] workflowDefinition, byte[] ruleDefinition)
{
System.IO.Stream definitionStream = null;
System.IO.Stream ruleStream = null;
System.Xml.XmlReader definitionReader = null;
System.Xml.XmlReader ruleReader = null;
try
{
definitionStream = new System.IO.MemoryStream(workflowDefinition);
definitionStream.Position = 0;
definitionReader = System.Xml.XmlReader.Create(definitionStream);
if (ruleDefinition != null)
{
ruleStream = new System.IO.MemoryStream(ruleDefinition);
ruleStream.Position = 0;
ruleReader = System.Xml.XmlReader.Create(ruleStream);
}
System.Workflow.ComponentModel.Activity root = null;
ValidationErrorCollection errors = new ValidationErrorCollection();
ServiceContainer serviceContainer = new ServiceContainer();
if (this.typeProvider != null)
{
serviceContainer.AddService(typeof(ITypeProvider), this.typeProvider);
}
DesignerSerializationManager manager = new DesignerSerializationManager(serviceContainer);
try
{
using (manager.CreateSession())
{
WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
root = new WorkflowMarkupSerializer().Deserialize(xomlSerializationManager, definitionReader) as System.Workflow.ComponentModel.Activity;
if (root != null && ruleReader != null)
{
object rules = new WorkflowMarkupSerializer().Deserialize(xomlSerializationManager, ruleReader);
root.SetValue(System.Workflow.Activities.Rules.RuleDefinitions.RuleDefinitionsProperty, rules);
}
foreach (object error in manager.Errors)
{
if (error is WorkflowMarkupSerializationException)
{
errors.Add(new ValidationError(((WorkflowMarkupSerializationException) error).Message, 1));
}
else
{
errors.Add(new ValidationError(error.ToString(), 1));
}
}
}
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
errors.Add(new ValidationError(e.Message, 1));
}
if (errors.HasErrors)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WorkflowValidationFailedException(SR2.GetString(SR2.WorkflowValidationFailed), errors));
}
return root;
}
finally
{
if (definitionStream != null)
{
definitionStream.Dispose();
}
if (ruleStream != null)
{
ruleStream.Dispose();
}
}
}
}
}

View File

@@ -0,0 +1,133 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.Workflow.Runtime
{
using System.ComponentModel.Design;
using System.Reflection;
using System.Runtime;
using System.ServiceModel;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
abstract class WorkflowDefinitionContext
{
WorkflowRuntime workflowRuntime;
public abstract string ConfigurationName
{
get;
}
public abstract string WorkflowName
{
get;
}
internal protected WorkflowRuntime WorkflowRuntime
{
get
{
Fx.Assert(this.workflowRuntime != null, "Attempt to call WorkflowRuntime before Register");
return this.workflowRuntime;
}
}
public abstract WorkflowInstance CreateWorkflow();
public abstract WorkflowInstance CreateWorkflow(Guid instanceId);
public abstract Activity GetWorkflowDefinition();
internal void Register(WorkflowRuntime workflowRuntime, bool validate)
{
if (workflowRuntime == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("workflowRuntime");
}
this.workflowRuntime = workflowRuntime;
OnRegister();
if (!this.workflowRuntime.IsStarted)
{
this.workflowRuntime.StartRuntime();
}
if (validate)
{
ValidateDefinition();
}
}
protected static TypeProvider CreateTypeProvider(Activity rootActivity)
{
TypeProvider typeProvider = new TypeProvider(null);
Type companionType = rootActivity.GetType();
typeProvider.SetLocalAssembly(companionType.Assembly);
typeProvider.AddAssembly(companionType.Assembly);
foreach (AssemblyName assemblyName in companionType.Assembly.GetReferencedAssemblies())
{
Assembly referencedAssembly = null;
try
{
referencedAssembly = Assembly.Load(assemblyName);
if (referencedAssembly != null)
{
typeProvider.AddAssembly(referencedAssembly);
}
}
catch (Exception e)
{
if (Fx.IsFatal(e))
{
throw;
}
}
if (referencedAssembly == null && assemblyName.CodeBase != null)
{
typeProvider.AddAssemblyReference(assemblyName.CodeBase);
}
}
return typeProvider;
}
protected abstract void OnRegister();
protected abstract void OnValidate(ValidationErrorCollection errors);
void ValidateDefinition()
{
ValidationErrorCollection errors = new ValidationErrorCollection();
Activity rootActivity = GetWorkflowDefinition();
ITypeProvider typeProvider = CreateTypeProvider(rootActivity);
ServiceContainer serviceContainer = new ServiceContainer();
serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
ValidationManager validationManager = new ValidationManager(serviceContainer);
foreach (Validator validator in validationManager.GetValidators(rootActivity.GetType()))
{
foreach (ValidationError error in validator.Validate(validationManager, rootActivity))
{
if (!error.UserData.Contains(typeof(Activity)))
{
error.UserData[typeof(Activity)] = rootActivity;
}
errors.Add(error);
}
}
OnValidate(errors);
if (errors.HasErrors)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WorkflowValidationFailedException(SR2.WorkflowValidationFailed, errors));
}
}
}
}