You've already forked linux-packaging-mono
Imported Upstream version 4.0.0~alpha1
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
381
external/referencesource/System.Workflow.Activities/LocalService/ExternalDataExchangeService.cs
vendored
Normal file
381
external/referencesource/System.Workflow.Activities/LocalService/ExternalDataExchangeService.cs
vendored
Normal file
@ -0,0 +1,381 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Reflection;
|
||||
using System.Workflow.ComponentModel;
|
||||
using System.Workflow.Runtime;
|
||||
using System.Workflow.Runtime.Configuration;
|
||||
using System.Workflow.Runtime.Hosting;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Configuration;
|
||||
|
||||
namespace System.Workflow.Activities
|
||||
{
|
||||
internal interface IDeliverMessage
|
||||
{
|
||||
object[] PrepareEventArgsArray(object sender, ExternalDataEventArgs eventArgs, out object workItem, out IPendingWork workHandler);
|
||||
void DeliverMessage(ExternalDataEventArgs eventArgs, IComparable queueName, object message, object workItem, IPendingWork workHandler);
|
||||
}
|
||||
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class ExternalDataExchangeServiceSection : ConfigurationSection
|
||||
{
|
||||
private const string _services = "Services";
|
||||
|
||||
/// <summary> The providers to be instantiated by the service container. </summary>
|
||||
[ConfigurationProperty(_services, DefaultValue = null)]
|
||||
public WorkflowRuntimeServiceElementCollection Services
|
||||
{
|
||||
get
|
||||
{
|
||||
return (WorkflowRuntimeServiceElementCollection)base[_services];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
||||
public class ExternalDataExchangeService : WorkflowRuntimeService
|
||||
{
|
||||
Dictionary<int, WorkflowMessageEventHandler> eventHandlers = null;
|
||||
object handlersLock = new object();
|
||||
private const string configurationSectionAttributeName = "ConfigurationSection";
|
||||
ExternalDataExchangeServiceSection settings = null;
|
||||
IDeliverMessage enqueueMessageWrapper = null;
|
||||
List<object> services;
|
||||
object servicesLock = new object();
|
||||
|
||||
public ExternalDataExchangeService()
|
||||
{
|
||||
this.eventHandlers = new Dictionary<int, WorkflowMessageEventHandler>();
|
||||
this.services = new List<object>();
|
||||
this.enqueueMessageWrapper = new EnqueueMessageWrapper(this);
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(string configSectionName)
|
||||
: this()
|
||||
{
|
||||
if (configSectionName == null)
|
||||
throw new ArgumentNullException("configSectionName");
|
||||
|
||||
settings = ConfigurationManager.GetSection(configSectionName) as ExternalDataExchangeServiceSection;
|
||||
if (settings == null)
|
||||
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
|
||||
SR.GetString(SR.Error_ConfigurationSectionNotFound), configSectionName));
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(NameValueCollection parameters)
|
||||
: this()
|
||||
{
|
||||
if (parameters == null)
|
||||
throw new ArgumentNullException("parameters");
|
||||
string configurationSectionName = null;
|
||||
|
||||
foreach (string key in parameters.Keys)
|
||||
{
|
||||
if (key.Equals(configurationSectionAttributeName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
configurationSectionName = parameters[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(
|
||||
String.Format(Thread.CurrentThread.CurrentCulture, SR.GetString(SR.Error_UnknownConfigurationParameter), key), "parameters");
|
||||
}
|
||||
}
|
||||
if (configurationSectionName != null)
|
||||
{
|
||||
settings = ConfigurationManager.GetSection(configurationSectionName) as ExternalDataExchangeServiceSection;
|
||||
if (settings == null)
|
||||
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
|
||||
SR.GetString(SR.Error_ConfigurationSectionNotFound), configurationSectionName));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ExternalDataExchangeService(ExternalDataExchangeServiceSection settings)
|
||||
: this()
|
||||
{
|
||||
if (settings == null)
|
||||
throw new ArgumentNullException("settings");
|
||||
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
internal ReadOnlyCollection<object> GetAllServices()
|
||||
{
|
||||
ReadOnlyCollection<object> collection;
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
collection = this.services.AsReadOnly();
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
if (settings != null)
|
||||
{
|
||||
foreach (WorkflowRuntimeServiceElement service in settings.Services)
|
||||
{
|
||||
AddService(ServiceFromSettings(service));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
base.Start();
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetEnqueueMessageWrapper(IDeliverMessage wrapper)
|
||||
{
|
||||
this.enqueueMessageWrapper = wrapper;
|
||||
foreach (WorkflowMessageEventHandler eventHandler in this.eventHandlers.Values)
|
||||
{
|
||||
eventHandler.EnqueueWrapper = wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
// Todo: This is duplicate of code in WorkflowRuntime
|
||||
internal object ServiceFromSettings(WorkflowRuntimeServiceElement serviceSettings)
|
||||
{
|
||||
object service = null;
|
||||
|
||||
Type t = Type.GetType(serviceSettings.Type, true);
|
||||
|
||||
ConstructorInfo serviceProviderAndSettingsConstructor = null;
|
||||
ConstructorInfo serviceProviderConstructor = null;
|
||||
ConstructorInfo settingsConstructor = null;
|
||||
|
||||
foreach (ConstructorInfo ci in t.GetConstructors())
|
||||
{
|
||||
ParameterInfo[] pi = ci.GetParameters();
|
||||
if (pi.Length == 1)
|
||||
{
|
||||
if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType))
|
||||
{
|
||||
serviceProviderConstructor = ci;
|
||||
}
|
||||
else if (typeof(NameValueCollection).IsAssignableFrom(pi[0].ParameterType))
|
||||
{
|
||||
settingsConstructor = ci;
|
||||
}
|
||||
}
|
||||
else if (pi.Length == 2)
|
||||
{
|
||||
if (typeof(IServiceProvider).IsAssignableFrom(pi[0].ParameterType)
|
||||
&& typeof(NameValueCollection).IsAssignableFrom(pi[1].ParameterType))
|
||||
{
|
||||
serviceProviderAndSettingsConstructor = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceProviderAndSettingsConstructor != null)
|
||||
{
|
||||
service = serviceProviderAndSettingsConstructor.Invoke(
|
||||
new object[] { Runtime, serviceSettings.Parameters });
|
||||
}
|
||||
else if (serviceProviderConstructor != null)
|
||||
{
|
||||
service = serviceProviderConstructor.Invoke(new object[] { Runtime });
|
||||
}
|
||||
else if (settingsConstructor != null)
|
||||
{
|
||||
service = settingsConstructor.Invoke(new object[] { serviceSettings.Parameters });
|
||||
}
|
||||
else
|
||||
{
|
||||
service = Activator.CreateInstance(t);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
public virtual void AddService(object service)
|
||||
{
|
||||
if (service == null)
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
InterceptService(service, true);
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
this.Runtime.AddService(service);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
this.services.Add(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveService(object service)
|
||||
{
|
||||
if (service == null)
|
||||
throw new ArgumentNullException("service");
|
||||
|
||||
InterceptService(service, false);
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
this.Runtime.RemoveService(service);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
this.services.Remove(service);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object GetService(Type serviceType)
|
||||
{
|
||||
if (serviceType == null)
|
||||
throw new ArgumentNullException("serviceType");
|
||||
|
||||
if (this.Runtime != null)
|
||||
{
|
||||
return this.Runtime.GetService(serviceType);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (this.servicesLock)
|
||||
{
|
||||
foreach (object service in this.services)
|
||||
{
|
||||
if (serviceType.IsAssignableFrom(service.GetType()))
|
||||
{
|
||||
return service;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void InterceptService(object service, bool add)
|
||||
{
|
||||
bool isDataExchangeService = false;
|
||||
Type[] interfaceTypes = service.GetType().GetInterfaces();
|
||||
foreach (Type type in interfaceTypes)
|
||||
{
|
||||
object[] attributes = type.GetCustomAttributes(typeof(ExternalDataExchangeAttribute), false);
|
||||
if (attributes.Length == 0)
|
||||
continue;
|
||||
|
||||
if (this.Runtime != null && this.Runtime.GetService(type) != null && add)
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ExternalDataExchangeServiceExists), type));
|
||||
|
||||
isDataExchangeService = true;
|
||||
EventInfo[] events = type.GetEvents();
|
||||
if (events == null)
|
||||
continue;
|
||||
|
||||
foreach (EventInfo e in events)
|
||||
{
|
||||
WorkflowMessageEventHandler handler = null;
|
||||
int hash = type.GetHashCode() ^ e.Name.GetHashCode();
|
||||
lock (handlersLock)
|
||||
{
|
||||
if (!this.eventHandlers.ContainsKey(hash))
|
||||
{
|
||||
handler = new WorkflowMessageEventHandler(type, e, this.enqueueMessageWrapper);
|
||||
this.eventHandlers.Add(hash, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler = this.eventHandlers[hash];
|
||||
}
|
||||
}
|
||||
AddRemove(service, handler.Delegate, add, e.Name);
|
||||
}
|
||||
}
|
||||
if (!isDataExchangeService)
|
||||
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Error_ServiceMissingExternalDataExchangeInterface)));
|
||||
}
|
||||
|
||||
private void AddRemove(object addedservice, Delegate delg, bool add, string eventName)
|
||||
{
|
||||
try
|
||||
{
|
||||
string eventAction;
|
||||
if (add)
|
||||
eventAction = "add_" + eventName;
|
||||
else
|
||||
eventAction = "remove_" + eventName;
|
||||
|
||||
Type serviceType = addedservice.GetType();
|
||||
if (delg != null)
|
||||
{
|
||||
// add or remove interception handler
|
||||
object[] del = { delg };
|
||||
serviceType.InvokeMember(eventAction, BindingFlags.InvokeMethod, null, addedservice, del, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (IsIrrecoverableException(e))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
// cannot intercept this event
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsIrrecoverableException(Exception e)
|
||||
{
|
||||
return ((e is OutOfMemoryException) ||
|
||||
(e is StackOverflowException) ||
|
||||
(e is ThreadInterruptedException) ||
|
||||
(e is ThreadAbortException));
|
||||
}
|
||||
|
||||
class EnqueueMessageWrapper : IDeliverMessage
|
||||
{
|
||||
ExternalDataExchangeService eds;
|
||||
|
||||
public EnqueueMessageWrapper(ExternalDataExchangeService eds)
|
||||
{
|
||||
this.eds = eds;
|
||||
}
|
||||
|
||||
public object[] PrepareEventArgsArray(object sender, ExternalDataEventArgs eventArgs, out object workItem, out IPendingWork workHandler)
|
||||
{
|
||||
// remove the batch items from the event args, only the runtime needs this data
|
||||
// and it is not necessarily serializable.
|
||||
workItem = eventArgs.WorkItem;
|
||||
eventArgs.WorkItem = null;
|
||||
workHandler = eventArgs.WorkHandler;
|
||||
eventArgs.WorkHandler = null;
|
||||
|
||||
return new object[] { sender, eventArgs };
|
||||
}
|
||||
public void DeliverMessage(ExternalDataEventArgs eventArgs, IComparable queueName, object message, object workItem, IPendingWork workHandler)
|
||||
{
|
||||
WorkflowInstance workflowInstance = this.eds.Runtime.GetWorkflow(eventArgs.InstanceId);
|
||||
if (eventArgs.WaitForIdle)
|
||||
{
|
||||
workflowInstance.EnqueueItemOnIdle(queueName, message, workHandler, workItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
workflowInstance.EnqueueItem(queueName, message, workHandler, workItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user