├── .gitignore ├── .vs ├── ProjectSettings.json └── slnx.sqlite ├── README.md └── src ├── .dockerignore ├── CoreFlow.Activities ├── Communication │ ├── QuestionAnswer │ │ ├── QuestionAnswerActivity.cs │ │ └── QuestionAnswerExtension.cs │ └── REST │ │ ├── CallRestApiActivity.cs │ │ └── RestExtension.cs ├── CoreFlow.Activities.csproj ├── InstanceStores │ ├── AsyncResult.cs │ ├── FileInstanceStore.cs │ ├── TypedAsyncResult.cs │ └── TypedCompletedAsyncResult.cs ├── RuntimeEngine.cs ├── Tracking │ ├── ConsoleLogger.cs │ ├── ILogWorkflowEvents.cs │ └── WfTracking.cs └── WorkflowModelCatalog │ ├── FileWorkflowModelCatalog.cs │ └── wf-Process1.xaml ├── CoreFlow.Designer ├── App.config ├── App.xaml ├── App.xaml.cs ├── CSharpExpressionEditor │ ├── CSharpExpressionHelper.cs │ ├── ExpressionHelper.cs │ ├── ExpressionSelection.cs │ ├── ExpressionValidationContext.cs │ ├── LICENSE │ ├── LineToHeightConverter.cs │ ├── ParserContext.cs │ ├── README.md │ ├── RoslynExpressionEditor.xaml │ ├── RoslynExpressionEditor.xaml.cs │ ├── RoslynExpressionEditorInstance.cs │ ├── RoslynExpressionEditorService.cs │ └── XamlUtilities.cs ├── CoreFlow.Designer.csproj ├── Helpers │ ├── CustomCommands.cs │ ├── CustomTrackingParticipant.cs │ ├── CustomWfDesigner.cs │ └── QueryCompletionData.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── ExpressionEditor │ │ ├── Event.png │ │ ├── Field.png │ │ ├── Method.png │ │ └── Property.png │ ├── Menu │ │ ├── exit.png │ │ ├── new.png │ │ ├── open.png │ │ ├── pause.png │ │ ├── run.png │ │ ├── save.png │ │ └── stop.png │ └── icon_app.ico ├── SampleWorkflow │ ├── AzureVmPowerOperations.xaml │ ├── LocalWinServicesCSV.xaml │ ├── SvcMonitoring.xaml │ └── meetup.xaml ├── VbExpressionEditor │ ├── VbExpressionEditorInstance.cs │ └── VbExpressionEditorService.cs ├── Views │ ├── MainWindow.xaml │ └── MainWindow.xaml.cs ├── defaultWorkflow.xaml ├── defaultWorkflowCSharp.xaml └── packages.config ├── CoreFlow.Engine ├── Controllers │ ├── WorkflowDefinitionController.cs │ └── WorkflowInstanceController.cs ├── CoreFlow.Engine.csproj ├── Dockerfile ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── appsettings.Development.json └── appsettings.json ├── CoreFlow.Shared ├── CoreFlow.Shared.csproj ├── IAddonRepository.cs ├── IInstanceDirectory.cs └── IWorkflowModelCatalog.cs ├── CoreForm.Activities ├── CoreForm.Activities.csproj ├── CoreFormActivity.cs └── CoreFormExtension.cs ├── Engine.sln ├── System.Activitites ├── System.Activities.dll ├── System.Activities.pdb ├── ar │ └── System.Activities.resources.dll ├── cs │ └── System.Activities.resources.dll ├── da │ └── System.Activities.resources.dll ├── de │ └── System.Activities.resources.dll ├── el │ └── System.Activities.resources.dll ├── es │ └── System.Activities.resources.dll ├── fi │ └── System.Activities.resources.dll ├── fr │ └── System.Activities.resources.dll ├── he │ └── System.Activities.resources.dll ├── hu │ └── System.Activities.resources.dll ├── it │ └── System.Activities.resources.dll ├── ja │ └── System.Activities.resources.dll ├── ko │ └── System.Activities.resources.dll ├── nb │ └── System.Activities.resources.dll ├── nl │ └── System.Activities.resources.dll ├── pl │ └── System.Activities.resources.dll ├── pt-br │ └── System.Activities.resources.dll ├── pt-pt │ └── System.Activities.resources.dll ├── ru │ └── System.Activities.resources.dll ├── sv │ └── System.Activities.resources.dll ├── tr │ └── System.Activities.resources.dll ├── zh-chs │ └── System.Activities.resources.dll └── zh-cht │ └── System.Activities.resources.dll ├── docker-compose.dcproj ├── docker-compose.override.yml └── docker-compose.yml /.gitignore: -------------------------------------------------------------------------------- 1 | #OS junk files 2 | [Tt]humbs.db 3 | *.DS_Store 4 | 5 | #Visual Studio files 6 | *.[Oo]bj 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *.vssscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.[Cc]ache 20 | *.ilk 21 | *.log 22 | *.lib 23 | *.sbr 24 | *.sdf 25 | *.opensdf 26 | *.unsuccessfulbuild 27 | ipch/ 28 | [Oo]bj/ 29 | [Bb]in 30 | [Dd]ebug*/ 31 | [Rr]elease*/ 32 | .vs/ 33 | Ankh.NoLoad 34 | 35 | #MonoDevelop 36 | *.pidb 37 | *.userprefs 38 | 39 | #Tooling 40 | _ReSharper*/ 41 | *.resharper 42 | [Tt]est[Rr]esult* 43 | *.sass-cache 44 | 45 | #Project files 46 | [Bb]uild/ 47 | 48 | #Subversion files 49 | .svn 50 | 51 | # Office Temp Files 52 | ~$* 53 | 54 | # vim Temp Files 55 | *~ 56 | 57 | #NuGet 58 | packages/ 59 | *.nupkg 60 | 61 | #ncrunch 62 | *ncrunch* 63 | *crunch*.local.xml 64 | 65 | # visual studio database projects 66 | *.dbmdl 67 | 68 | #Test files 69 | *.testsettings -------------------------------------------------------------------------------- /.vs/ProjectSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "CurrentProjectSetting": null 3 | } -------------------------------------------------------------------------------- /.vs/slnx.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/.vs/slnx.sqlite -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Under development] 2 | 3 | # CoreFlow 4 | 5 | ## Why CoreFlow? 6 | CoreFlow is an open-source platform based on CoreWF, a port of the Windows Workflow Foundation (WF) runtime to the .NET Standard sponsored by UIPath, to help you quickly build an integrated workflow engine for long-running persisted and tracked workflows. 7 | Aimed to be easily deployed with Docker, the platform is composed of the Workflow Engine and a set of API for the tracking and management of the instances. 8 | -------------------------------------------------------------------------------- /src/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Communication/QuestionAnswer/QuestionAnswerActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | 9 | namespace CoreFlow.Activities.Communication.QuestionAnswer 10 | { 11 | public class QuestionAnswerActivity : NativeActivity 12 | { 13 | public InArgument Question { get; set; } 14 | 15 | protected override void CacheMetadata(NativeActivityMetadata metadata) 16 | { 17 | metadata.AddDefaultExtensionProvider(() => 18 | new QuestionAnswerExtension()); 19 | base.CacheMetadata(metadata); 20 | } 21 | 22 | protected override void Execute(NativeActivityContext context) 23 | { 24 | Console.WriteLine("Activity Id: " + Id); 25 | // Create a Bookmark and wait for it to be resumed. 26 | context.CreateBookmark("QuestionAnswerBookmark"+Id, 27 | new BookmarkCallback(OnResumeBookmark)); 28 | context.GetExtension().Question(Id, Question.Get(context)); 29 | } 30 | 31 | // NativeActivity derived activities that do asynchronous operations by calling 32 | // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext 33 | // must override the CanInduceIdle property and return true. 34 | protected override bool CanInduceIdle 35 | { 36 | get { return true; } 37 | } 38 | 39 | private void OnResumeBookmark(NativeActivityContext context, Bookmark bookmark, object obj) 40 | { 41 | // When the Bookmark is resumed, assign its value to 42 | // the Result argument. 43 | Result.Set(context, (string)obj); 44 | } 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Communication/QuestionAnswer/QuestionAnswerExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Hosting; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace CoreFlow.Activities.Communication.QuestionAnswer 12 | { 13 | class QuestionAnswerExtension : IWorkflowInstanceExtension 14 | { 15 | WorkflowInstanceProxy _instance; 16 | public Dictionary Questions = new Dictionary(); 17 | 18 | public void Question(String ActivityId, String Question) 19 | { 20 | Task.Run(() => 21 | { 22 | Questions.Add(ActivityId, Question); 23 | Console.WriteLine("Question added: " + Question + " [Bookmark: QuestionAnswerBookmark" + ActivityId+"]"); 24 | Console.WriteLine("Now, navigate to https://localhost:5001/api/instance/{0}/QuestionAnswerBookmark{1}/John%20Smith", _instance.Id, ActivityId); 25 | 26 | //String answer = Console.ReadLine(); 27 | //_instance.BeginResumeBookmark(new Bookmark("QuestionAnswerBookmark" + ActivityId), answer, (o) => 28 | //{ 29 | // Console.WriteLine("End of ResumeBookmark"); 30 | //}, null); 31 | 32 | }); 33 | 34 | 35 | } 36 | 37 | public IEnumerable GetAdditionalExtensions() 38 | { 39 | return null; 40 | } 41 | 42 | public void SetInstance(WorkflowInstanceProxy instance) 43 | { 44 | _instance = instance; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Communication/REST/CallRestApiActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | 9 | namespace CoreFlow.Activities.Communication.REST 10 | { 11 | public class CallRestApiActivity : NativeActivity 12 | { 13 | public InArgument Url { get; set; } 14 | 15 | protected override void CacheMetadata(NativeActivityMetadata metadata) 16 | { 17 | metadata.AddDefaultExtensionProvider(() => 18 | new RestExtension()); 19 | base.CacheMetadata(metadata); 20 | } 21 | 22 | protected override void Execute(NativeActivityContext context) 23 | { 24 | Console.WriteLine("Activity Id: " + Id); 25 | // Create a Bookmark and wait for it to be resumed. 26 | Result.Set(context, context.GetExtension().CallApi(Url.Get(context))); 27 | } 28 | 29 | // NativeActivity derived activities that do asynchronous operations by calling 30 | // one of the CreateBookmark overloads defined on System.Activities.NativeActivityContext 31 | // must override the CanInduceIdle property and return true. 32 | protected override bool CanInduceIdle 33 | { 34 | get { return false; } 35 | } 36 | 37 | 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Communication/REST/RestExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Hosting; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace CoreFlow.Activities.Communication.REST 12 | { 13 | class RestExtension : IWorkflowInstanceExtension 14 | { 15 | private WorkflowInstanceProxy _instance; 16 | public RestExtension() 17 | { 18 | 19 | } 20 | public String CallApi(String Url) 21 | { 22 | WebProxy proxy = new WebProxy(WebRequest.GetSystemWebProxy().GetProxy(new Uri(Url))); //new WebProxy(); 23 | //proxy.Address = new Uri("http://webproxy-dr.erbhlux.lan:8080"); 24 | proxy.UseDefaultCredentials = true; 25 | proxy.BypassProxyOnLocal = true; 26 | 27 | 28 | WebClient wc = new WebClient(); 29 | wc.Proxy = proxy; 30 | // Let's simulate a slow call 31 | Console.WriteLine("Calling {0} ...", Url); 32 | 33 | 34 | return wc.DownloadString(new Uri(Url)); 35 | 36 | 37 | 38 | } 39 | 40 | 41 | 42 | public IEnumerable GetAdditionalExtensions() 43 | { 44 | return null; 45 | } 46 | 47 | public void SetInstance(WorkflowInstanceProxy instance) 48 | { 49 | _instance = instance; 50 | } 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/CoreFlow.Activities.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | Debug;Release;Debug-no-compose 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Always 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ..\System.Activitites\System.Activities.dll 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/InstanceStores/AsyncResult.cs: -------------------------------------------------------------------------------- 1 | // This file is part of Core WF which is licensed under the MIT license. 2 | // See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Diagnostics; 6 | using System.Threading; 7 | 8 | namespace CoreFlow.Activities.InstanceStores 9 | { 10 | /// 11 | /// A generic base class for IAsyncResult implementations 12 | /// that wraps a ManualResetEvent. 13 | /// 14 | internal abstract class FileStoreAsyncResult : IAsyncResult 15 | { 16 | private readonly AsyncCallback _callback; 17 | private readonly object _state; 18 | private bool _completedSynchronously; 19 | private bool _endCalled; 20 | private Exception _exception; 21 | private bool _isCompleted; 22 | private ManualResetEvent _manualResetEvent; 23 | private readonly object _thisLock; 24 | 25 | protected FileStoreAsyncResult(AsyncCallback callback, object state) 26 | { 27 | _callback = callback; 28 | _state = state; 29 | _thisLock = new object(); 30 | } 31 | 32 | public object AsyncState 33 | { 34 | get 35 | { 36 | return _state; 37 | } 38 | } 39 | 40 | public WaitHandle AsyncWaitHandle 41 | { 42 | get 43 | { 44 | if (_manualResetEvent != null) 45 | { 46 | return _manualResetEvent; 47 | } 48 | 49 | lock (ThisLock) 50 | { 51 | if (_manualResetEvent == null) 52 | { 53 | _manualResetEvent = new ManualResetEvent(_isCompleted); 54 | } 55 | } 56 | 57 | return _manualResetEvent; 58 | } 59 | } 60 | 61 | public bool CompletedSynchronously 62 | { 63 | get 64 | { 65 | return _completedSynchronously; 66 | } 67 | } 68 | 69 | public bool IsCompleted 70 | { 71 | get 72 | { 73 | return _isCompleted; 74 | } 75 | } 76 | 77 | private object ThisLock 78 | { 79 | get 80 | { 81 | return _thisLock; 82 | } 83 | } 84 | 85 | // Call this version of complete when your asynchronous operation is complete. This will update the state 86 | // of the operation and notify the callback. 87 | protected void Complete(bool completedSynchronously) 88 | { 89 | if (_isCompleted) 90 | { 91 | // It is incorrect to call Complete twice. 92 | // throw new InvalidOperationException(Resources.AsyncResultAlreadyCompleted); 93 | throw new InvalidOperationException("AsyncResultAlreadyCompleted"); 94 | } 95 | 96 | _completedSynchronously = completedSynchronously; 97 | 98 | if (completedSynchronously) 99 | { 100 | // If we completedSynchronously, then there is no chance that the manualResetEvent was created so 101 | // we do not need to worry about a race condition. 102 | Debug.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); 103 | _isCompleted = true; 104 | } 105 | else 106 | { 107 | lock (ThisLock) 108 | { 109 | _isCompleted = true; 110 | if (_manualResetEvent != null) 111 | { 112 | _manualResetEvent.Set(); 113 | } 114 | } 115 | } 116 | 117 | // If the callback throws, the callback implementation is incorrect 118 | if (_callback != null) 119 | { 120 | _callback(this); 121 | } 122 | } 123 | 124 | // Call this version of complete if you raise an exception during processing. In addition to notifying 125 | // the callback, it will capture the exception and store it to be thrown during AsyncResult.End. 126 | protected void Complete(bool completedSynchronously, Exception exception) 127 | { 128 | _exception = exception; 129 | Complete(completedSynchronously); 130 | } 131 | 132 | // End should be called when the End function for the asynchronous operation is complete. It 133 | // ensures the asynchronous operation is complete, and does some common validation. 134 | protected static TAsyncResult End(IAsyncResult result) 135 | where TAsyncResult : FileStoreAsyncResult 136 | { 137 | if (result == null) 138 | { 139 | throw new ArgumentNullException("result"); 140 | } 141 | 142 | 143 | if (!(result is TAsyncResult asyncResult)) 144 | { 145 | // throw new ArgumentException(Resources.InvalidAsyncResult); 146 | throw new ArgumentException("InvalidAsyncResult"); 147 | } 148 | 149 | if (asyncResult._endCalled) 150 | { 151 | // throw new InvalidOperationException(Resources.AsyncResultAlreadyEnded); 152 | throw new InvalidOperationException("AsyncResultAlreadyEnded"); 153 | } 154 | 155 | asyncResult._endCalled = true; 156 | 157 | if (!asyncResult._isCompleted) 158 | { 159 | asyncResult.AsyncWaitHandle.WaitOne(); 160 | } 161 | 162 | if (asyncResult._manualResetEvent != null) 163 | { 164 | // was manualResetEvent.Close(); 165 | asyncResult._manualResetEvent.Dispose(); 166 | } 167 | 168 | if (asyncResult._exception != null) 169 | { 170 | throw asyncResult._exception; 171 | } 172 | 173 | return asyncResult; 174 | } 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/InstanceStores/FileInstanceStore.cs: -------------------------------------------------------------------------------- 1 | // This file is part of Core WF which is licensed under the MIT license. 2 | // See LICENSE file in the project root for full license information. 3 | 4 | using System.Activities.DurableInstancing; 5 | using System.Activities.Runtime.DurableInstancing; 6 | using Newtonsoft.Json; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Xml.Linq; 11 | using CoreFlow.Shared; 12 | using System.Activities.Hosting; 13 | using System.Linq; 14 | 15 | namespace CoreFlow.Activities.InstanceStores 16 | { 17 | public class FileInstanceStore : InstanceStore, IInstanceDirectory 18 | { 19 | private readonly string _storeDirectoryPath; 20 | 21 | private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings 22 | { 23 | TypeNameHandling = TypeNameHandling.None, 24 | TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple, 25 | ConstructorHandling = ConstructorHandling.Default, 26 | ObjectCreationHandling = ObjectCreationHandling.Replace, 27 | PreserveReferencesHandling = PreserveReferencesHandling.All 28 | }; 29 | 30 | public FileInstanceStore(string storeDirectoryPath) 31 | { 32 | _storeDirectoryPath = storeDirectoryPath; 33 | Directory.CreateDirectory(storeDirectoryPath); 34 | } 35 | 36 | public bool KeepInstanceDataAfterCompletion 37 | { 38 | get; 39 | set; 40 | } 41 | 42 | private void DeleteFiles(Guid instanceId) 43 | { 44 | try 45 | { 46 | File.Delete(_storeDirectoryPath + "\\" + instanceId.ToString() + "-InstanceData"); 47 | File.Delete(_storeDirectoryPath + "\\" + instanceId.ToString() + "-InstanceMetadata"); 48 | } 49 | catch (Exception ex) 50 | { 51 | Console.WriteLine("Caught exception trying to delete files for {0}: {1} - {2}", instanceId.ToString(), ex.GetType().ToString(), ex.Message); 52 | } 53 | } 54 | 55 | protected override IAsyncResult BeginTryCommand(InstancePersistenceContext context, InstancePersistenceCommand command, TimeSpan timeout, AsyncCallback callback, object state) 56 | { 57 | try 58 | { 59 | if (command is SaveWorkflowCommand) 60 | { 61 | return new TypedCompletedAsyncResult(SaveWorkflow(context, (SaveWorkflowCommand)command), callback, state); 62 | } 63 | else if (command is LoadWorkflowCommand) 64 | { 65 | return new TypedCompletedAsyncResult(LoadWorkflow(context, (LoadWorkflowCommand)command), callback, state); 66 | } 67 | else if (command is CreateWorkflowOwnerCommand) 68 | { 69 | return new TypedCompletedAsyncResult(CreateWorkflowOwner(context, (CreateWorkflowOwnerCommand)command), callback, state); 70 | } 71 | else if (command is CreateWorkflowOwnerWithIdentityCommand) 72 | { 73 | return new TypedCompletedAsyncResult(CreateWorkflowOwnerWithIdentity(context, (CreateWorkflowOwnerWithIdentityCommand)command), callback, state); 74 | } 75 | else if (command is DeleteWorkflowOwnerCommand) 76 | { 77 | return new TypedCompletedAsyncResult(DeleteWorkflowOwner(context, (DeleteWorkflowOwnerCommand)command), callback, state); 78 | } 79 | return new TypedCompletedAsyncResult(false, callback, state); 80 | } 81 | catch (Exception e) 82 | { 83 | return new TypedCompletedAsyncResult(e, callback, state); 84 | } 85 | } 86 | 87 | protected override bool EndTryCommand(IAsyncResult result) 88 | { 89 | if (result is TypedCompletedAsyncResult exceptionResult) 90 | { 91 | throw exceptionResult.Data; 92 | } 93 | return TypedCompletedAsyncResult.End(result); 94 | } 95 | 96 | private bool SaveWorkflow(InstancePersistenceContext context, SaveWorkflowCommand command) 97 | { 98 | if (context.InstanceVersion == -1) 99 | { 100 | context.BindAcquiredLock(0); 101 | } 102 | 103 | if (command.CompleteInstance) 104 | { 105 | context.CompletedInstance(); 106 | if (!KeepInstanceDataAfterCompletion) 107 | { 108 | DeleteFiles(context.InstanceView.InstanceId); 109 | } 110 | } 111 | else 112 | { 113 | Dictionary instanceData = SerializeablePropertyBagConvertXNameInstanceValue(command.InstanceData); 114 | Dictionary instanceMetadata = SerializeInstanceMetadataConvertXNameInstanceValue(context, command); 115 | 116 | try 117 | { 118 | var serializedInstanceData = JsonConvert.SerializeObject(instanceData, Formatting.Indented, _jsonSerializerSettings); 119 | File.WriteAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceData", serializedInstanceData); 120 | 121 | var serializedInstanceMetadata = JsonConvert.SerializeObject(instanceMetadata, Formatting.Indented, _jsonSerializerSettings); 122 | File.WriteAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceMetadata", serializedInstanceMetadata); 123 | } 124 | catch (Exception) 125 | { 126 | throw; 127 | } 128 | 129 | foreach (KeyValuePair property in command.InstanceMetadataChanges) 130 | { 131 | context.WroteInstanceMetadataValue(property.Key, property.Value); 132 | } 133 | 134 | context.PersistedInstance(command.InstanceData); 135 | if (command.CompleteInstance) 136 | { 137 | context.CompletedInstance(); 138 | } 139 | 140 | if (command.UnlockInstance || command.CompleteInstance) 141 | { 142 | context.InstanceHandle.Free(); 143 | } 144 | } 145 | 146 | return true; 147 | } 148 | 149 | private bool LoadWorkflow(InstancePersistenceContext context, LoadWorkflowCommand command) 150 | { 151 | if (command.AcceptUninitializedInstance) 152 | { 153 | return false; 154 | } 155 | 156 | if (context.InstanceVersion == -1) 157 | { 158 | context.BindAcquiredLock(0); 159 | } 160 | 161 | IDictionary instanceData = null; 162 | IDictionary instanceMetadata = null; 163 | 164 | Dictionary serializableInstanceData; 165 | Dictionary serializableInstanceMetadata; 166 | 167 | try 168 | { 169 | var serializedInstanceData = File.ReadAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceData"); 170 | serializableInstanceData = JsonConvert.DeserializeObject>(serializedInstanceData, _jsonSerializerSettings); 171 | 172 | var serializedInstanceMetadata = File.ReadAllText(_storeDirectoryPath + "\\" + context.InstanceView.InstanceId + "-InstanceMetadata"); 173 | serializableInstanceMetadata = JsonConvert.DeserializeObject>(serializedInstanceMetadata, _jsonSerializerSettings); 174 | } 175 | catch (Exception) 176 | { 177 | throw; 178 | } 179 | 180 | instanceData = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceData); 181 | instanceMetadata = this.DeserializePropertyBagConvertXNameInstanceValue(serializableInstanceMetadata); 182 | 183 | context.LoadedInstance(InstanceState.Initialized, instanceData, instanceMetadata, null, null); 184 | 185 | return true; 186 | } 187 | 188 | private bool CreateWorkflowOwnerWithIdentity(InstancePersistenceContext context, CreateWorkflowOwnerWithIdentityCommand command) 189 | { 190 | Guid instanceOwnerId = Guid.NewGuid(); 191 | context.BindInstanceOwner(instanceOwnerId, instanceOwnerId); 192 | context.BindEvent(HasRunnableWorkflowEvent.Value); 193 | return true; 194 | } 195 | private bool CreateWorkflowOwner(InstancePersistenceContext context, CreateWorkflowOwnerCommand command) 196 | { 197 | Guid instanceOwnerId = Guid.NewGuid(); 198 | context.BindInstanceOwner(instanceOwnerId, instanceOwnerId); 199 | context.BindEvent(HasRunnableWorkflowEvent.Value); 200 | return true; 201 | } 202 | 203 | private bool DeleteWorkflowOwner(InstancePersistenceContext context, DeleteWorkflowOwnerCommand command) 204 | { 205 | return true; 206 | } 207 | 208 | private Dictionary SerializeablePropertyBagConvertXNameInstanceValue(IDictionary source) 209 | { 210 | Dictionary scratch = new Dictionary(); 211 | foreach (KeyValuePair property in source) 212 | { 213 | bool writeOnly = (property.Value.Options & InstanceValueOptions.WriteOnly) != 0; 214 | 215 | if (!writeOnly && !property.Value.IsDeletedValue) 216 | { 217 | scratch.Add(property.Key.ToString(), property.Value); 218 | } 219 | } 220 | 221 | return scratch; 222 | } 223 | 224 | private Dictionary SerializeInstanceMetadataConvertXNameInstanceValue(InstancePersistenceContext context, SaveWorkflowCommand command) 225 | { 226 | Dictionary metadata = null; 227 | 228 | foreach (var property in command.InstanceMetadataChanges) 229 | { 230 | if (!property.Value.Options.HasFlag(InstanceValueOptions.WriteOnly)) 231 | { 232 | if (metadata == null) 233 | { 234 | metadata = new Dictionary(); 235 | // copy current metadata. note that we must get rid of InstanceValue as it is not properly serializeable 236 | foreach (var m in context.InstanceView.InstanceMetadata) 237 | { 238 | metadata.Add(m.Key.ToString(), m.Value); 239 | } 240 | } 241 | 242 | if (metadata.ContainsKey(property.Key.ToString())) 243 | { 244 | if (property.Value.IsDeletedValue) metadata.Remove(property.Key.ToString()); 245 | else metadata[property.Key.ToString()] = property.Value; 246 | } 247 | else 248 | { 249 | if (!property.Value.IsDeletedValue) metadata.Add(property.Key.ToString(), property.Value); 250 | } 251 | } 252 | } 253 | 254 | if (metadata == null) 255 | metadata = new Dictionary(); 256 | 257 | return metadata; 258 | } 259 | 260 | private IDictionary DeserializePropertyBagConvertXNameInstanceValue(Dictionary source) 261 | { 262 | Dictionary destination = new Dictionary(); 263 | 264 | foreach (KeyValuePair property in source) 265 | { 266 | destination.Add(property.Key, property.Value); 267 | } 268 | 269 | return destination; 270 | } 271 | 272 | public IEnumerable GetInstances() 273 | { 274 | throw new NotImplementedException(); 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/InstanceStores/TypedAsyncResult.cs: -------------------------------------------------------------------------------- 1 | // This file is part of Core WF which is licensed under the MIT license. 2 | // See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace CoreFlow.Activities.InstanceStores 7 | { 8 | /// 9 | /// A strongly typed AsyncResult. 10 | /// 11 | /// 12 | internal abstract class TypedAsyncResult : FileStoreAsyncResult 13 | { 14 | private T _data; 15 | 16 | protected TypedAsyncResult(AsyncCallback callback, object state) 17 | : base(callback, state) 18 | { 19 | } 20 | 21 | public T Data 22 | { 23 | get { return _data; } 24 | } 25 | 26 | protected void Complete(T data, bool completedSynchronously) 27 | { 28 | _data = data; 29 | Complete(completedSynchronously); 30 | } 31 | 32 | public static T End(IAsyncResult result) 33 | { 34 | TypedAsyncResult typedResult = FileStoreAsyncResult.End>(result); 35 | return typedResult.Data; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/InstanceStores/TypedCompletedAsyncResult.cs: -------------------------------------------------------------------------------- 1 | // This file is part of Core WF which is licensed under the MIT license. 2 | // See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace CoreFlow.Activities.InstanceStores 7 | { 8 | /// 9 | /// A strongly typed AsyncResult that completes as soon as it is instantiated. 10 | /// 11 | /// 12 | internal class TypedCompletedAsyncResult : TypedAsyncResult 13 | { 14 | public TypedCompletedAsyncResult(T data, AsyncCallback callback, object state) 15 | : base(callback, state) 16 | { 17 | Complete(data, true); 18 | } 19 | 20 | public new static T End(IAsyncResult result) 21 | { 22 | 23 | if (!(result is TypedCompletedAsyncResult completedResult)) 24 | { 25 | throw new ArgumentException("InvalidAsyncResult"); 26 | } 27 | 28 | return TypedAsyncResult.End(completedResult); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/RuntimeEngine.cs: -------------------------------------------------------------------------------- 1 | using CoreFlow.Activities.Tracking; 2 | using System; 3 | using System.Xaml; 4 | using System.Activities; 5 | using System.Activities.Expressions; 6 | using System.Activities.Hosting; 7 | using System.Activities.Runtime.DurableInstancing; 8 | using System.Activities.Statements; 9 | using System.Activities.Tracking; 10 | using System.Collections.Generic; 11 | using System.Collections.ObjectModel; 12 | using System.Linq; 13 | using CoreFlow.Shared; 14 | 15 | namespace CoreFlow.Activities 16 | { 17 | public class RuntimeEngine 18 | { 19 | InstanceStore instanceStore; 20 | List extensions = new List(); 21 | Guid lastid; 22 | public RuntimeEngine() 23 | { 24 | } 25 | 26 | public RuntimeEngine WithInstanceStore(InstanceStore instanceStore) 27 | { 28 | this.instanceStore = instanceStore; 29 | return this; 30 | } 31 | 32 | public RuntimeEngine AddExtension(Object singletonExtension) 33 | { 34 | this.extensions.Add(singletonExtension); 35 | return this; 36 | } 37 | 38 | public T GetExtension() 39 | { 40 | return extensions.OfType().FirstOrDefault(); 41 | } 42 | 43 | public IEnumerable GetInstances() 44 | { 45 | return GetExtension()?.GetInstances(); 46 | } 47 | 48 | 49 | public void ResumeBookmark(Guid instanceId, String bookmark, Object input) 50 | { 51 | var ii = WorkflowApplication.GetInstance(instanceId, instanceStore); 52 | var WorkflowDefinition = this.GetExtension()?.GetActiveModel("Process1"); 53 | var app = new WorkflowApplication(WorkflowDefinition, ii.DefinitionIdentity); 54 | EnrichWorkflowApplication(app); 55 | app.Load(instanceId); 56 | app.ResumeBookmark(bookmark, input); 57 | } 58 | 59 | public Guid StartNewInstance(String modelName) 60 | { 61 | WorkflowIdentity workflowIdentity = new WorkflowIdentity("Process1", new Version(0, 1), "wf"); 62 | var wf = this.GetExtension()?.GetActiveModel("Process1"); 63 | var app = new WorkflowApplication(wf); 64 | EnrichWorkflowApplication(app); 65 | app.Run(); 66 | lastid = app.Id; 67 | Console.WriteLine(lastid); 68 | return app.Id; 69 | } 70 | 71 | 72 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "")] 73 | private WorkflowApplication EnrichWorkflowApplication(WorkflowApplication workflowApplication) 74 | { 75 | 76 | var consoleLogger = new ConsoleLogger(); 77 | WFTracking track = new WFTracking(consoleLogger); 78 | //Tracking Profile 79 | TrackingProfile prof = new TrackingProfile(); 80 | prof.Name = "CustomTrackingProfile"; 81 | prof.Queries.Add(new WorkflowInstanceQuery { States = { "*" } }); 82 | prof.Queries.Add(new ActivityStateQuery { States = { "*" }, Arguments = { "*" } }); 83 | prof.Queries.Add(new CustomTrackingQuery() { Name = "*", ActivityName = "*" }); 84 | prof.ImplementationVisibility = ImplementationVisibility.RootScope; 85 | track.TrackingProfile = prof; 86 | track.WorkflowName = "wf"; 87 | 88 | foreach (var extension in extensions) 89 | { 90 | workflowApplication.Extensions.Add(extension); 91 | } 92 | workflowApplication.Extensions.Add(track); 93 | workflowApplication.Extensions.Add(consoleLogger); 94 | 95 | workflowApplication.InstanceStore = instanceStore; 96 | 97 | workflowApplication.Completed = delegate (WorkflowApplicationCompletedEventArgs e) 98 | { 99 | if (e.CompletionState == ActivityInstanceState.Faulted) 100 | { 101 | Console.WriteLine(string.Format("Workflow Terminated. Exception: {0}\r\n{1}", 102 | e.TerminationException.GetType().FullName, 103 | e.TerminationException.Message)); 104 | } 105 | else if (e.CompletionState == ActivityInstanceState.Canceled) 106 | { 107 | Console.WriteLine("Workflow Canceled : " + workflowApplication.Id); 108 | } 109 | else 110 | { 111 | if (e.Outputs != null && e.Outputs.Count > 0) 112 | { 113 | foreach (var kvp in e.Outputs) 114 | Console.WriteLine("Output --> {0} : {1}", kvp.Key, kvp.Value.ToString()); 115 | } 116 | Console.WriteLine("Success : " + workflowApplication.Id); 117 | } 118 | }; 119 | 120 | workflowApplication.Aborted = delegate (WorkflowApplicationAbortedEventArgs e) 121 | { 122 | Console.WriteLine(string.Format("Workflow Aborted. Exception: {0}\r\n{1}", 123 | e.Reason.GetType().FullName, 124 | e.Reason.Message)); 125 | }; 126 | 127 | workflowApplication.OnUnhandledException = delegate (WorkflowApplicationUnhandledExceptionEventArgs e) 128 | { 129 | Console.WriteLine(string.Format("Unhandled Exception in {2}: {0}\r\n{1}", 130 | e.UnhandledException.GetType().FullName, 131 | e.UnhandledException.Message, e.ExceptionSource)); 132 | return UnhandledExceptionAction.Terminate; 133 | }; 134 | 135 | workflowApplication.PersistableIdle = delegate (WorkflowApplicationIdleEventArgs e) 136 | { 137 | Console.WriteLine("PersistableIdle : " + workflowApplication.Id); 138 | return PersistableIdleAction.Unload; 139 | }; 140 | 141 | workflowApplication.Idle = delegate (WorkflowApplicationIdleEventArgs e) 142 | { 143 | 144 | Console.WriteLine("Idle : " + workflowApplication.Id); 145 | 146 | }; 147 | 148 | return workflowApplication; 149 | } 150 | 151 | 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Tracking/ConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Linq; 5 | 6 | namespace CoreFlow.Activities.Tracking 7 | { 8 | public class ConsoleLogger : ILogWorkflowEvents 9 | { 10 | public void InsertEvent(WorkflowRecord EventRecord) 11 | { 12 | var currentColor = Console.ForegroundColor; 13 | Console.ForegroundColor = ConsoleColor.DarkGray; 14 | Console.WriteLine("Log : " + EventRecord.ToString('\t')); 15 | Console.ForegroundColor = currentColor; 16 | } 17 | 18 | public void UpdateEvent(WorkflowRecord EventRecord) 19 | { 20 | var currentColor = Console.ForegroundColor; 21 | Console.ForegroundColor = ConsoleColor.DarkGray; 22 | Console.WriteLine("Log : " + EventRecord.ToString('\t').TrimEnd('\n').Split('\n').Last()); 23 | Console.ForegroundColor = currentColor; 24 | } 25 | 26 | public void Dispose() 27 | { 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Tracking/ILogWorkflowEvents.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace CoreFlow.Activities.Tracking 6 | { 7 | public interface ILogWorkflowEvents : IDisposable 8 | { 9 | void InsertEvent(WorkflowRecord EventRecord); 10 | void UpdateEvent(WorkflowRecord EventRecord); 11 | } 12 | 13 | [Serializable] 14 | public class WorkflowRecord 15 | { 16 | public long JobId { get; set; } //IDSCHEDULE 17 | public Guid WFId { get; set; } //IDWORKFLOW 18 | public Guid RunId { get; set; } //IDINSTANCE 19 | public long EventId { get; set; } //EVENTINDEX 20 | public DateTime EventTime { get; set; } //EVENTTIME 21 | public string Name { get; set; } //EVENTSOURCE 22 | public string State { get; set; } //EVENTSTATUS 23 | public string Message { get; set; } //EVENTMESSAGE 24 | 25 | public WorkflowRecord() 26 | { 27 | JobId = -1; 28 | RunId = Guid.Empty; 29 | WFId = Guid.Empty; 30 | EventId = -1; 31 | EventTime = DateTime.MinValue; 32 | Name = string.Empty; 33 | State = string.Empty; 34 | } 35 | 36 | public void Print() 37 | { 38 | Console.WriteLine("-------------"); 39 | Console.WriteLine("{0}", EventTime); 40 | Console.WriteLine("{0}", Name); 41 | Console.WriteLine("{0}", State); 42 | if (Message.Length > 0) Console.WriteLine("{0}", Message); 43 | Console.WriteLine("-------------"); 44 | } 45 | 46 | public override string ToString() 47 | { 48 | return string.Format("SchedId: {0}\nWF ID: {1}\nRun ID: {2}\nEventTime: {3}\nEvent Source: {4}\nEvent Status: {5}\nEvent Message: {6}", JobId, WFId, RunId, EventTime, Name, State, Message); 49 | } 50 | 51 | public string ToString(char p) 52 | { 53 | return String.Format("{0}{4}{1}{4}{2}{4}{3}", EventTime, Name, State, Message, p); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/Tracking/WfTracking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities.Tracking; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Text; 6 | 7 | namespace CoreFlow.Activities.Tracking 8 | { 9 | 10 | 11 | public class WFTracking : TrackingParticipant 12 | { 13 | public string WorkflowName { get; set; } 14 | public long JobId { get; set; } 15 | public Guid WFIdentifier { get; set; } 16 | 17 | ILogWorkflowEvents logWorkflowEvents; 18 | 19 | public WFTracking(ILogWorkflowEvents logWorkflowEvents) 20 | { 21 | this.logWorkflowEvents = logWorkflowEvents; 22 | JobId = -1; 23 | } 24 | 25 | protected override void Track(TrackingRecord record, TimeSpan timeout) 26 | { 27 | WorkflowRecord message = new WorkflowRecord(); 28 | 29 | message.WFId = WFIdentifier; 30 | message.JobId = JobId; 31 | 32 | message.EventId = (int)record.RecordNumber; 33 | message.EventTime = record.EventTime.ToLocalTime(); 34 | message.RunId = record.InstanceId; 35 | 36 | WorkflowInstanceRecord wfRecord = record as WorkflowInstanceRecord; 37 | if (wfRecord != null) 38 | { 39 | message.State = wfRecord.State; 40 | message.Name = WorkflowName; 41 | 42 | if (wfRecord.State == WorkflowInstanceStates.Idle) return; //do not track idle status 43 | } 44 | 45 | ActivityStateRecord actRecord = record as ActivityStateRecord; 46 | if (actRecord != null) 47 | { 48 | message.State = actRecord.State; 49 | message.Name = actRecord.Activity.Name; 50 | if (actRecord.Activity.Name.Equals("DynamicActivity")) 51 | { 52 | return; 53 | } 54 | 55 | if (actRecord.State == ActivityStates.Executing && actRecord.Activity.TypeName == "System.Activities.Statements.WriteLine") 56 | { 57 | using (StringWriter writer = new StringWriter()) 58 | { 59 | writer.Write(actRecord.Arguments["Text"]); 60 | message.Message = writer.ToString(); 61 | writer.Close(); 62 | } 63 | } 64 | } 65 | 66 | WorkflowInstanceUnhandledExceptionRecord exRecord = record as WorkflowInstanceUnhandledExceptionRecord; 67 | if (exRecord != null) 68 | { 69 | message.State = exRecord.State; 70 | message.Name = WorkflowName; 71 | message.Message = exRecord.UnhandledException.Message; 72 | } 73 | 74 | CustomTrackingRecord cuRecord = record as CustomTrackingRecord; 75 | if (cuRecord != null) 76 | { 77 | message.Name = cuRecord.Activity.Name; 78 | message.State = cuRecord.Name; 79 | message.Message = cuRecord.Data.ContainsKey("Message") ? cuRecord.Data["Message"] as string : null; 80 | } 81 | 82 | logWorkflowEvents.InsertEvent(message); 83 | } 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/WorkflowModelCatalog/FileWorkflowModelCatalog.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using System; 3 | using System.Activities; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace CoreFlow.Activities.WorkflowModelCatalog 8 | { 9 | public class FileWorkflowModelCatalog : CoreFlow.Shared.IWorkflowModelCatalog 10 | { 11 | 12 | 13 | public Activity GetActiveModel(string name) 14 | { 15 | Activity root = System.Activities.XamlIntegration.ActivityXamlServices.Load(System.IO.Path.Combine(@"..\CoreFlow.Activities\WorkflowModelCatalog\", String.Format("wf-{0}.xaml", name))); 16 | return root; 17 | } 18 | 19 | public Activity GetModel(WorkflowIdentity workflowIdentity) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | 24 | public void Initialize(IConfiguration configuration) 25 | { 26 | 27 | } 28 | 29 | public WorkflowIdentity RegisterModel(string name, Activity workflowModel) 30 | { 31 | throw new NotImplementedException(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CoreFlow.Activities/WorkflowModelCatalog/wf-Process1.xaml: -------------------------------------------------------------------------------- 1 |  2 | 3 | __ReferenceID0 4 | __ReferenceID1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/App.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace RehostedWorkflowDesigner 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/CSharpExpressionHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CSharp.Activities; 2 | using System; 3 | using System.Activities; 4 | using System.Activities.Expressions; 5 | using System.Activities.Presentation.Model; 6 | using System.Collections.Generic; 7 | using System.Collections.ObjectModel; 8 | using System.ComponentModel; 9 | using System.Globalization; 10 | using System.Linq; 11 | 12 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 13 | { 14 | public static class CSharpExpressionHelper 15 | { 16 | private static readonly Type CSharpValueType = typeof(CSharpValue<>); 17 | private static readonly Type CSharpReferenceType = typeof(CSharpReference<>); 18 | private static readonly Type CodeActivityType = typeof(CodeActivity); 19 | private static readonly Type AsyncCodeActivityType = typeof(AsyncCodeActivity); 20 | private static readonly Type GenericAsyncCodeActivityType = typeof(AsyncCodeActivity<>); 21 | private static readonly Type VariablesCollectionType = typeof(Collection); 22 | 23 | internal static ActivityWithResult CreateCSharpExpression(string expressionText, bool isLocationExpression, Type returnType) 24 | { 25 | Type expressionType; 26 | if (isLocationExpression) 27 | { 28 | expressionType = CSharpReferenceType.MakeGenericType(returnType); 29 | } 30 | else 31 | { 32 | expressionType = CSharpValueType.MakeGenericType(returnType); 33 | } 34 | 35 | return Activator.CreateInstance(expressionType, expressionText) as ActivityWithResult; 36 | } 37 | 38 | public static ActivityWithResult CreateExpressionFromString(string expressionText, bool useLocationExpression, Type resultType) 39 | { 40 | ActivityWithResult expression; 41 | if (!useLocationExpression) 42 | { 43 | if (!CSharpExpressionHelper.TryCreateLiteral(resultType, expressionText, out expression)) 44 | { 45 | expression = CSharpExpressionHelper.CreateCSharpExpression(expressionText, useLocationExpression, resultType); 46 | } 47 | } 48 | else 49 | { 50 | expression = CSharpExpressionHelper.CreateCSharpExpression(expressionText, useLocationExpression, resultType); 51 | } 52 | 53 | return expression; 54 | } 55 | 56 | internal static bool TryCreateLiteral(Type type, string expressionText, out ActivityWithResult literalExpression) 57 | { 58 | literalExpression = null; 59 | 60 | // try easy way first - look if there is a type conversion which supports conversion between expression type and string 61 | TypeConverter literalValueConverter = null; 62 | bool isQuotedString = false; 63 | if (IsLiteralExpressionSupported(type)) 64 | { 65 | bool shouldBeQuoted; 66 | if (typeof(char) == type) 67 | { 68 | shouldBeQuoted = true; 69 | isQuotedString = expressionText.StartsWith("'", StringComparison.CurrentCulture) && 70 | expressionText.EndsWith("'", StringComparison.CurrentCulture) && 71 | expressionText.IndexOf("'", 1, StringComparison.CurrentCulture) == expressionText.Length - 1; 72 | } 73 | else 74 | { 75 | shouldBeQuoted = typeof(string) == type; 76 | 77 | // whether string begins and ends with quotes '"'. also, if there are 78 | // more quotes within than those begining and ending ones, do not bother with literal - assume this is an expression. 79 | isQuotedString = shouldBeQuoted && 80 | expressionText.StartsWith("\"", StringComparison.CurrentCulture) && 81 | expressionText.EndsWith("\"", StringComparison.CurrentCulture) && 82 | expressionText.IndexOf("\"", 1, StringComparison.CurrentCulture) == expressionText.Length - 1 && 83 | expressionText.IndexOf("\\", StringComparison.CurrentCulture) == -1; 84 | } 85 | 86 | // if expression is a string, we must ensure it is quoted, in case of other types - just get the converter 87 | if ((shouldBeQuoted && isQuotedString) || !shouldBeQuoted) 88 | { 89 | literalValueConverter = TypeDescriptor.GetConverter(type); 90 | } 91 | } 92 | 93 | // if there is converter - try to convert 94 | if (null != literalValueConverter && literalValueConverter.CanConvertFrom(null, typeof(string))) 95 | { 96 | try 97 | { 98 | var valueToConvert = isQuotedString ? expressionText.Substring(1, expressionText.Length - 2) : expressionText; 99 | var convertedValue = literalValueConverter.ConvertFrom(null, CultureInfo.CurrentCulture, valueToConvert); 100 | 101 | // ok, succeeded - create literal of given type 102 | Type concreteExpType = typeof(Literal<>).MakeGenericType(type); 103 | literalExpression = (ActivityWithResult)Activator.CreateInstance(concreteExpType, convertedValue); 104 | 105 | // C# expression is case sensitive, if it's not exactly "true"/"false" with case matching, we don't generate Literal 106 | if (type == typeof(bool) && (valueToConvert != "true") && (valueToConvert != "false")) 107 | { 108 | literalExpression = null; 109 | } 110 | } 111 | catch 112 | { 113 | // conversion failed - do nothing, let it continue to generate C# expression instead 114 | } 115 | } 116 | 117 | return literalExpression != null; 118 | } 119 | 120 | internal static bool IsLiteralExpressionSupported(Type type) 121 | { 122 | // type must be set and cannot be object 123 | if (null == type || typeof(object) == type) 124 | { 125 | return false; 126 | } 127 | 128 | return type.IsPrimitive || type == typeof(string) || type == typeof(TimeSpan) || type == typeof(DateTime); 129 | } 130 | 131 | internal static List GetVariablesInScope(ModelItem ownerActivity) 132 | { 133 | List variablesInScope = new List(); 134 | if (ownerActivity != null) 135 | { 136 | HashSet variableNames = new HashSet(); 137 | ModelItem currentItem = ownerActivity; 138 | Func filterDelegate = new Func((variable) => 139 | { 140 | string variableName = (string)variable.Properties["Name"].ComputedValue; 141 | if (!string.IsNullOrWhiteSpace(variableName)) 142 | { 143 | return !variableNames.Contains(variableName); 144 | } 145 | else 146 | { 147 | return false; 148 | } 149 | }); 150 | 151 | while (currentItem != null) 152 | { 153 | List variables = new List(); 154 | ModelItemCollection variablesCollection = GetVariableCollection(currentItem); 155 | if (variablesCollection != null) 156 | { 157 | variables.AddRange(variablesCollection); 158 | } 159 | 160 | variables.AddRange(FindActivityDelegateArguments(currentItem)); 161 | 162 | // For the variables defined at the same level, shadowing doesn't apply. If there're multiple variables defined at the same level 163 | // have duplicate names when case is ignored, all of these variables should bee added as variables in scope and let validation reports 164 | // ambiguous reference error. So that we need to scan all variables defined at the same level first and then add names to the HashSet. 165 | IEnumerable filteredVariables = variables.Where(filterDelegate); 166 | variablesInScope.AddRange(filteredVariables); 167 | foreach (ModelItem variable in filteredVariables) 168 | { 169 | variableNames.Add(((string)variable.Properties["Name"].ComputedValue)); 170 | } 171 | 172 | currentItem = currentItem.Parent; 173 | } 174 | } 175 | 176 | return variablesInScope; 177 | } 178 | 179 | private static ModelItemCollection GetVariableCollection(ModelItem currentItem) 180 | { 181 | if (null != currentItem) 182 | { 183 | Type elementType = currentItem.ItemType; 184 | if (!(CodeActivityType.IsAssignableFrom(elementType) || GenericAsyncCodeActivityType.IsAssignableFrom(elementType) || 185 | AsyncCodeActivityType.IsAssignableFrom(elementType) || GenericAsyncCodeActivityType.IsAssignableFrom(elementType))) 186 | { 187 | ModelProperty variablesProperty = currentItem.Properties["Variables"]; 188 | if ((variablesProperty != null) && (variablesProperty.PropertyType == VariablesCollectionType)) 189 | { 190 | return variablesProperty.Collection; 191 | } 192 | } 193 | } 194 | 195 | return null; 196 | } 197 | 198 | private static IEnumerable FindActivityDelegateArguments(ModelItem currentItem) 199 | { 200 | List delegateArguments = new List(); 201 | if (currentItem.GetCurrentValue() is ActivityDelegate) 202 | { 203 | delegateArguments.AddRange(currentItem.Properties 204 | .Where(p => (typeof(DelegateArgument).IsAssignableFrom(p.PropertyType) && null != p.Value)) 205 | .Select(p => p.Value)); 206 | } 207 | 208 | return delegateArguments; 209 | } 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/ExpressionHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Expressions; 4 | using System.Activities.Presentation.Model; 5 | using System.ComponentModel; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Globalization; 8 | using System.Reflection; 9 | 10 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 11 | { 12 | internal static class ExpressionHelper 13 | { 14 | internal static string GetExpressionString(Activity expression) 15 | { 16 | return ExpressionHelper.GetExpressionString(expression, null as ParserContext); 17 | } 18 | 19 | internal static string GetExpressionString(Activity expression, ModelItem owner) 20 | { 21 | ParserContext context = new ParserContext(owner); 22 | return ExpressionHelper.GetExpressionString(expression, context); 23 | } 24 | 25 | internal static string GetExpressionString(Activity expression, ParserContext context) 26 | { 27 | string expressionString = null; 28 | if (expression != null) 29 | { 30 | Type expressionType = expression.GetType(); 31 | Type expressionArgumentType = expressionType.IsGenericType ? expressionType.GetGenericArguments()[0] : typeof(object); 32 | bool isLiteral = expressionType.IsGenericType ? Type.Equals(typeof(Literal<>), expressionType.GetGenericTypeDefinition()) : false; 33 | 34 | //handle ITextExpression 35 | if (expression is ITextExpression) 36 | { 37 | ITextExpression textExpression = expression as ITextExpression; 38 | expressionString = textExpression.ExpressionText; 39 | } 40 | //handle Literal Expression 41 | else if (isLiteral) 42 | { 43 | TypeConverter converter = XamlUtilities.GetConverter(expressionArgumentType); 44 | if (converter != null && converter.CanConvertTo(context, typeof(string))) 45 | { 46 | PropertyInfo literalValueProperty = expressionType.GetProperty("Value"); 47 | object literalValue = literalValueProperty.GetValue(expression, null); 48 | string convertedString = null; 49 | if (literalValue != null) 50 | { 51 | try 52 | { 53 | convertedString = converter.ConvertToString(context, literalValue); 54 | } 55 | catch (ArgumentException) 56 | { 57 | convertedString = literalValue.ToString(); 58 | } 59 | } 60 | expressionString = expressionArgumentType == typeof(string) ? ("\"" + convertedString + "\"") : convertedString; 61 | } 62 | } 63 | else if (expressionType.IsGenericType && 64 | (expressionType.GetGenericTypeDefinition() == typeof(VariableValue<>) || 65 | expressionType.GetGenericTypeDefinition() == typeof(VariableReference<>))) 66 | { 67 | PropertyInfo variableProperty = expression.GetType().GetProperty("Variable"); 68 | Variable variable = variableProperty.GetValue(expression, null) as Variable; 69 | if (variable != null) 70 | { 71 | expressionString = variable.Name; 72 | } 73 | } 74 | } 75 | 76 | return expressionString; 77 | } 78 | 79 | [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", 80 | Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")] 81 | [SuppressMessage("Reliability", "Reliability108:IsFatalRule", 82 | Justification = "The conversion to an expression might fail due to invalid user input. Propagating exceptions might lead to VS crash.")] 83 | internal static ActivityWithResult TryCreateLiteral(Type type, string expressionText, ParserContext context) 84 | { 85 | //try easy way first - look if there is a type conversion which supports conversion between expression type and string 86 | TypeConverter literalValueConverter = null; 87 | bool isQuotedString = false; 88 | if (CanTypeBeSerializedAsLiteral(type)) 89 | { 90 | bool shouldBeQuoted = typeof(string) == type; 91 | 92 | //whether string begins and ends with quotes '"'. also, if there are 93 | //more quotes within than those begining and ending ones, do not bother with literal - assume this is an expression. 94 | isQuotedString = shouldBeQuoted && 95 | expressionText.StartsWith("\"", StringComparison.CurrentCulture) && 96 | expressionText.EndsWith("\"", StringComparison.CurrentCulture) && 97 | expressionText.IndexOf("\"", 1, StringComparison.CurrentCulture) == expressionText.Length - 1; 98 | 99 | //if expression is a string, we must ensure it is quoted, in case of other types - just get the converter 100 | if ((shouldBeQuoted && isQuotedString) || !shouldBeQuoted) 101 | { 102 | literalValueConverter = TypeDescriptor.GetConverter(type); 103 | } 104 | } 105 | 106 | //if there is converter - try to convert 107 | if (null != literalValueConverter && literalValueConverter.CanConvertFrom(context, typeof(string))) 108 | { 109 | try 110 | { 111 | var valueToConvert = isQuotedString ? expressionText.Substring(1, expressionText.Length - 2) : expressionText; 112 | var converterValue = literalValueConverter.ConvertFrom(context, CultureInfo.CurrentCulture, valueToConvert); 113 | //ok, succeeded - create literal of given type 114 | var concreteExpType = typeof(Literal<>).MakeGenericType(type); 115 | return (ActivityWithResult)Activator.CreateInstance(concreteExpType, converterValue); 116 | } 117 | catch (Exception e) { Console.WriteLine(e.ToString()); } 118 | } 119 | 120 | return null; 121 | } 122 | 123 | internal static bool CanTypeBeSerializedAsLiteral(Type type) 124 | { 125 | //type must be set and cannot be object 126 | if (null == type || typeof(object) == type) 127 | { 128 | return false; 129 | } 130 | 131 | return type.IsPrimitive || type == typeof(string) || type == typeof(TimeSpan) || type == typeof(DateTime); 132 | } 133 | 134 | // Test whether this activity is Expression 135 | internal static bool IsExpression(this Activity activity) 136 | { 137 | return activity is ActivityWithResult; 138 | } 139 | 140 | internal static bool IsGenericLocationExpressionType(ActivityWithResult expression) 141 | { 142 | Type expressionType = expression.ResultType; 143 | return expressionType.IsGenericType && typeof(Location<>) == expressionType.GetGenericTypeDefinition(); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/ExpressionSelection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities.Presentation; 3 | using System.Activities.Presentation.Model; 4 | 5 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 6 | { 7 | internal class ExpressionSelection : ContextItem 8 | { 9 | ModelItem modelItem; 10 | 11 | public ExpressionSelection() 12 | { 13 | } 14 | 15 | public ExpressionSelection(ModelItem modelItem) 16 | { 17 | this.modelItem = modelItem; 18 | } 19 | 20 | public ModelItem ModelItem 21 | { 22 | get { return this.modelItem; } 23 | } 24 | 25 | public override Type ItemType 26 | { 27 | get 28 | { 29 | return typeof(ExpressionSelection); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/ExpressionValidationContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities.Presentation; 3 | using System.Activities.Presentation.Hosting; 4 | using System.Activities.Presentation.Model; 5 | using System.Collections.Generic; 6 | 7 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 8 | { 9 | public class ExpressionValidationContext 10 | { 11 | private RoslynExpressionEditor etb; 12 | 13 | public ExpressionValidationContext(RoslynExpressionEditor etb) 14 | { 15 | this.etb = etb; 16 | } 17 | 18 | internal ParserContext ParserContext { get; set; } 19 | internal Type ExpressionType { get; set; } 20 | internal String ExpressionText { get; set; } 21 | internal EditingContext EditingContext { get; set; } 22 | internal String ValidatedExpressionText { get; set; } 23 | internal bool UseLocationExpression { get; set; } 24 | 25 | internal void Update(RoslynExpressionEditor etb) 26 | { 27 | this.EditingContext = etb.OwnerActivity.GetEditingContext(); 28 | 29 | //setup ParserContext 30 | this.ParserContext = new ParserContext(etb.OwnerActivity) 31 | { 32 | //callee is a ExpressionTextBox 33 | Instance = etb, 34 | //pass property descriptor belonging to epression's model property (if one exists) 35 | //TODO: etb should have expressionModelProperty and the propertyDescriptor should be used here instead of passing null 36 | PropertyDescriptor = null, 37 | }; 38 | 39 | if (etb.ExpressionType != null) 40 | { 41 | this.ExpressionType = etb.ExpressionType; 42 | } 43 | 44 | this.ValidatedExpressionText = this.ExpressionText; 45 | if (etb.ExpressionEditorInstance != null) 46 | { 47 | this.ExpressionText = etb.ExpressionEditorInstance.Text; 48 | } 49 | else if (etb.EditingTextBox != null) 50 | { 51 | this.ExpressionText = etb.EditingTextBox.Text; 52 | } 53 | else 54 | { 55 | this.ExpressionText = etb.Text; 56 | } 57 | this.UseLocationExpression = etb.UseLocationExpression; 58 | } 59 | 60 | internal IEnumerable ReferencedAssemblies 61 | { 62 | get 63 | { 64 | AssemblyContextControlItem assemblyContext = this.EditingContext.Items.GetValue(); 65 | if (assemblyContext != null) 66 | { 67 | return assemblyContext.AllAssemblyNamesInContext; 68 | } 69 | return null; 70 | } 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Dustin Metzgar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/LineToHeightConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Windows.Data; 5 | using System.Windows.Media; 6 | 7 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 8 | { 9 | internal sealed class LineToHeightConverter : IMultiValueConverter 10 | { 11 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | double convertedValue = double.NaN; 14 | bool isDefault = true; 15 | 16 | // Calculate the height for the textblock as ExpressionTextBox exposes lines properties, 17 | // and TextBlock doesn't have lines properties. 18 | FontFamily fontFamily = values.OfType().FirstOrDefault(); 19 | int lines = values.OfType().FirstOrDefault(); 20 | double[] doubleArray = values.OfType().ToArray(); 21 | 22 | if (doubleArray.Length == 2) 23 | { 24 | double height = doubleArray[0]; // The first element of the array is going to be the height 25 | double fontSize = doubleArray[1]; // The seconed element of the array is going to be the fontSize 26 | 27 | // 0.0 is default for MinHeight, PositiveInfinity is default for MaxHeight 28 | if (string.Equals(parameter as string, "MinHeight")) 29 | { 30 | isDefault = height == 0.0; 31 | } 32 | else if (string.Equals(parameter as string, "MaxHeight")) 33 | { 34 | isDefault = double.IsPositiveInfinity(height); 35 | } 36 | 37 | // If the height value we are evaluating is default, use Lines for sizing... 38 | // If no heights (height or lines) have been explicitly specified, we would rather default the height 39 | // as if the Line was 1 - so use the line heights, rather than 0.0 and/or PositiveInfinity. 40 | if (isDefault) 41 | { 42 | double lineHeight = fontSize * fontFamily.LineSpacing; 43 | 44 | if (fontFamily != null) 45 | { 46 | convertedValue = (lineHeight * (double)lines) + 4; 47 | } 48 | } 49 | else 50 | { 51 | convertedValue = height; 52 | } 53 | } 54 | 55 | return convertedValue; 56 | } 57 | 58 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 59 | { 60 | throw new NotSupportedException(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/ParserContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Presentation; 4 | using System.Activities.Presentation.Hosting; 5 | using System.Activities.Presentation.Model; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | using System.Globalization; 9 | using System.Linq; 10 | using System.Reflection; 11 | using System.Windows.Markup; 12 | using System.Xaml; 13 | 14 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 15 | { 16 | class ParserContext : LocationReferenceEnvironment, IValueSerializerContext, IXamlNameResolver, INamespacePrefixLookup, IXamlNamespaceResolver 17 | { 18 | ModelItem baseModelItem; 19 | EditingContext context; 20 | IDictionary namespaceLookup; 21 | 22 | public ParserContext() 23 | { 24 | } 25 | 26 | public ParserContext(ModelItem modelItem) 27 | { 28 | this.Initialize(modelItem); 29 | } 30 | 31 | public IContainer Container 32 | { 33 | get { return null; } 34 | } 35 | 36 | public object Instance 37 | { 38 | get; 39 | internal set; 40 | } 41 | 42 | public PropertyDescriptor PropertyDescriptor 43 | { 44 | get; 45 | internal set; 46 | } 47 | 48 | public override Activity Root 49 | { 50 | get { return null; } 51 | } 52 | 53 | IDictionary NamespaceLookup 54 | { 55 | get 56 | { 57 | if (this.namespaceLookup == null) 58 | { 59 | this.namespaceLookup = new Dictionary(); 60 | } 61 | return this.namespaceLookup; 62 | } 63 | } 64 | 65 | public bool Initialize(ModelItem modelItem) 66 | { 67 | this.baseModelItem = modelItem; 68 | if (null != modelItem) 69 | { 70 | this.context = modelItem.GetEditingContext(); 71 | } 72 | return (null != this.baseModelItem); 73 | } 74 | 75 | public override bool IsVisible(LocationReference reference) 76 | { 77 | object other = this.Resolve(reference.Name); 78 | 79 | return object.ReferenceEquals(other, reference); 80 | } 81 | 82 | public override bool TryGetLocationReference(string name, out LocationReference result) 83 | { 84 | result = (LocationReference)this.Resolve(name); 85 | return result != null; 86 | } 87 | 88 | 89 | public string GetNamespace(string prefix) 90 | { 91 | var nameSpace = this.NamespaceLookup 92 | .Where(p => string.Equals(p.Value, prefix)) 93 | .Select(p => p.Key) 94 | .FirstOrDefault(); 95 | 96 | return nameSpace; 97 | } 98 | 99 | public IEnumerable GetNamespacePrefixes() 100 | { 101 | List namespacePrefixes = new List(); 102 | LoadNameSpace(namespacePrefixes); 103 | return namespacePrefixes; 104 | } 105 | 106 | public override IEnumerable GetLocationReferences() 107 | { 108 | List toReturn = new List(); 109 | if (this.baseModelItem != null) 110 | { 111 | List declaredVariables = CSharpExpressionHelper.GetVariablesInScope(this.baseModelItem); 112 | 113 | foreach (ModelItem modelItem in declaredVariables) 114 | { 115 | toReturn.Add(modelItem.GetCurrentValue() as LocationReference); 116 | } 117 | } 118 | return toReturn; 119 | } 120 | 121 | public object Resolve(string name) 122 | { 123 | IEnumerable variables = this.GetLocationReferences(); 124 | return variables.FirstOrDefault(p => 125 | { 126 | return p != null && p.Name != null && p.Name.Equals(name); 127 | }); 128 | } 129 | 130 | public object Resolve(string name, out bool isFullyInitialized) 131 | { 132 | object result = Resolve(name); 133 | isFullyInitialized = (result != null); 134 | return result; 135 | } 136 | 137 | public bool IsFixupTokenAvailable 138 | { 139 | get 140 | { 141 | 142 | return false; 143 | } 144 | } 145 | 146 | internal IEnumerable Namespaces 147 | { 148 | get 149 | { 150 | var namespacesToReturn = new HashSet(); 151 | 152 | //with custom ones, defined in user provided assemblies 153 | if (null != this.namespaceLookup) 154 | { 155 | foreach (var nameSpace in this.namespaceLookup.Keys) 156 | { 157 | //out of full namespace declaration (i.e. "clr-namespace:;assembly=" 158 | //get clear namespace name 159 | int startIndex = nameSpace.IndexOf(":", StringComparison.Ordinal); 160 | int endIndex = nameSpace.IndexOf(";", StringComparison.Ordinal); 161 | if (startIndex >= 0 && endIndex >= 0) 162 | { 163 | string clrNamespace = nameSpace.Substring(startIndex + 1, endIndex - startIndex - 1); 164 | namespacesToReturn.Add(clrNamespace); 165 | } 166 | } 167 | } 168 | 169 | ImportedNamespaceContextItem importedNamespaces = this.context.Items.GetValue(); 170 | namespacesToReturn.UnionWith(importedNamespaces.ImportedNamespaces); 171 | //return all namespaces 172 | return namespacesToReturn; 173 | } 174 | } 175 | 176 | public object GetFixupToken(IEnumerable names) 177 | { 178 | return null; 179 | } 180 | 181 | public object GetFixupToken(IEnumerable names, bool canAssignDirectly) 182 | { 183 | return null; 184 | } 185 | 186 | public object GetService(Type serviceType) 187 | { 188 | if (serviceType == typeof(IXamlNameResolver) 189 | || serviceType == typeof(INamespacePrefixLookup) 190 | || serviceType == typeof(IXamlNamespaceResolver)) 191 | { 192 | return this; 193 | } 194 | else 195 | { 196 | return null; 197 | } 198 | } 199 | 200 | public ValueSerializer GetValueSerializerFor(Type type) 201 | { 202 | return null; 203 | } 204 | 205 | public ValueSerializer GetValueSerializerFor(PropertyDescriptor descriptor) 206 | { 207 | return null; 208 | } 209 | 210 | public string LookupPrefix(string ns) 211 | { 212 | //get reference to namespace lookup dictionary (create one if necessary) 213 | var lookupTable = this.NamespaceLookup; 214 | string prefix; 215 | //check if given namespace is already registered 216 | if (!lookupTable.TryGetValue(ns, out prefix)) 217 | { 218 | //no, create a unique prefix 219 | prefix = string.Format(CultureInfo.InvariantCulture, "__{0}", Guid.NewGuid().ToString().Replace("-", "").Substring(0, 5)); 220 | //and store value in the dictionary 221 | lookupTable[ns] = prefix; 222 | } 223 | //return prefix 224 | return prefix; 225 | } 226 | 227 | public void OnComponentChanged() 228 | { 229 | throw new NotSupportedException("Not Supported"); 230 | } 231 | 232 | public bool OnComponentChanging() 233 | { 234 | throw new NotSupportedException("Not Supported"); 235 | } 236 | 237 | void LoadNameSpace(List result) 238 | { 239 | if (null == this.context) 240 | { 241 | //Fx.Assert("EditingContext is null"); 242 | return; 243 | } 244 | AssemblyContextControlItem assemblyContext = this.context.Items.GetValue(); 245 | if (null == assemblyContext) 246 | { 247 | //Fx.Assert("AssemblyContextControlItem not defined in EditingContext.Items"); 248 | return; 249 | } 250 | if (null != assemblyContext.LocalAssemblyName) 251 | { 252 | result.Add(GetEntry(assemblyContext.LocalAssemblyName)); 253 | } 254 | if (null != assemblyContext.ReferencedAssemblyNames) 255 | { 256 | foreach (AssemblyName name in assemblyContext.ReferencedAssemblyNames) 257 | { 258 | result.Add(GetEntry(name)); 259 | } 260 | } 261 | } 262 | 263 | NamespaceDeclaration GetEntry(AssemblyName name) 264 | { 265 | string ns = 266 | string.Format(CultureInfo.InvariantCulture, "clr-namespace:{0};assembly={1}", 267 | Guid.NewGuid().ToString().Replace('-', '_'), name.Name); 268 | return new NamespaceDeclaration(ns, Guid.NewGuid().ToString()); 269 | } 270 | 271 | IEnumerable> IXamlNameResolver.GetAllNamesAndValuesInScope() 272 | { 273 | return null; 274 | } 275 | 276 | event EventHandler IXamlNameResolver.OnNameScopeInitializationComplete 277 | { 278 | add { } 279 | remove { } 280 | } 281 | 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/README.md: -------------------------------------------------------------------------------- 1 | # WF Rehosted Designer with Roslyn C# Expression Editor 2 | 3 | The rehostable designer in Workflow Foundation is limited to only allow Visual Basic expressions. This project 4 | is to show how it is possible to use Roslyn for C# expressions. Roslyn is used to parse the code into syntax 5 | trees that can be used to fill completion windows. The user interface is powered by AvalonEdit. 6 | 7 | High level steps needed to implement the custom expression editor: 8 | 9 | 1. Implement the IExpressionEditorService interface. This interface manages the creation and destruction of expression editors. 10 | 2. Implement the IExpressionEditorInstance interface. This interface implements the UI for expression editing UI. 11 | 3. Publish the IExpressionEditorService in your rehosted workflow application. 12 | 4. Implement a custom Expression Activity Editor with C# expression support a WPF based text editor component like AvalonEdit (https://github.com/icsharpcode/AvalonEdit) and register it to the ExpressionTextBox used by workflow designer. 13 | 5. Use Roslyn to parse the code into syntax trees that can be used for IntelliSense. 14 | 15 | While it is not a fully working custom expression editor implementation, it implements a custom Expression Activity Editor and shows how to work around below .NET workflow runtime issues you hit attempting above steps. 16 | 1) Expression Editor defaults to VB expressions when implementing custom expression editor. 17 | When rehosting the workflow designer, the workflow runtime uses .NET framework 4.0 by default and this should be set to .NET 4.5 or higher to use the C# expression support. You can do this by using DesignerConfigurationService class as shown below. 18 | 19 | DesignerConfigurationService configurationService = wd.Context.Services.GetService(); 20 | configurationService.TargetFrameworkName = new FrameworkName(".NETFramework", new System.Version(4, 5)); 21 | 22 | 23 | 2) By default, workflow runtime does not allow loading XAML from untrusted source. 24 | You can again use the DesignerConfigurationService class to configure the workflow designer as shown below. 25 | 26 | configurationService.LoadingFromUntrustedSourceEnabled = true; 27 | 28 | 3) When loading custom XAML, workflow runtime defaults to VB in rehosted designer. 29 | Set the below XAML attached property to indicate workflow runtime that you are using C# expressions in your workflow. 30 | 31 | sap2010:ExpressionActivityEditor.ExpressionActivityEditor="C#" 32 | 33 | ## Links to useful resources 34 | 35 | [Rehosting the Workflow Designer](https://msdn.microsoft.com/en-us/library/dd489451.aspx) 36 | 37 | [Using a Custom Expression Editor](https://msdn.microsoft.com/en-us/library/ff521564.aspx) 38 | 39 | [AvalonEdit on GitHub](https://github.com/icsharpcode/AvalonEdit) 40 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/RoslynExpressionEditor.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 85 | 86 | 106 | 107 | 114 | 115 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 143 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/RoslynExpressionEditorInstance.cs: -------------------------------------------------------------------------------- 1 | using ICSharpCode.AvalonEdit; 2 | using ICSharpCode.AvalonEdit.CodeCompletion; 3 | using ICSharpCode.AvalonEdit.Highlighting; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using RehostedWorkflowDesigner.Helpers; 8 | using System; 9 | using System.Activities.Presentation.Model; 10 | using System.Activities.Presentation.View; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Windows; 14 | using System.Windows.Controls; 15 | using System.Windows.Input; 16 | 17 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 18 | { 19 | public class RoslynExpressionEditorInstance : TextEditor, IExpressionEditorInstance 20 | { 21 | private CompletionWindow completionWindow; 22 | private string variableDeclarations; 23 | 24 | public RoslynExpressionEditorInstance() 25 | { 26 | this.TextArea.TextEntering += TextArea_TextEntering; 27 | this.TextArea.TextEntered += TextArea_TextEntered; 28 | this.TextArea.LostKeyboardFocus += TextArea_LostFocus; // Need to detach events. 29 | 30 | this.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#"); 31 | this.FontFamily = new System.Windows.Media.FontFamily("Consolas"); 32 | this.FontSize = 12; 33 | } 34 | 35 | public RoslynExpressionEditorInstance(Size initialSize) : this() 36 | { 37 | this.Width = initialSize.Width; 38 | this.Height = initialSize.Height; 39 | } 40 | 41 | public void UpdateInstance(List variables, string text) 42 | { 43 | this.Text = text; 44 | if (variables != null) 45 | try 46 | { 47 | if (variables.Count > 0) 48 | { 49 | this.variableDeclarations = string.Join("", variables.Select(v => 50 | { 51 | var c = v.GetCurrentValue() as System.Activities.Variable; 52 | if (c != null) 53 | return c.Type.FullName + " " + c.Name + ";\n"; 54 | var d = v.GetCurrentValue() as System.Activities.DelegateArgument; 55 | if (d != null) 56 | return d.Type.FullName + " " + d.Name + ";\n"; 57 | return null; 58 | }).ToArray()); 59 | } 60 | } 61 | catch (Exception ex) 62 | { 63 | Console.WriteLine(ex.ToString()); 64 | } 65 | } 66 | 67 | private void TextArea_TextEntered(object sender, System.Windows.Input.TextCompositionEventArgs e) 68 | { 69 | if (e.Text == ".") 70 | { 71 | try 72 | { 73 | string startString = RoslynExpressionEditorService.Instance.UsingNamespaces 74 | + "using System; using System.Collections.Generic; using System.Text; namespace SomeNamespace { public class NotAProgram { private void SomeMethod() { " 75 | + variableDeclarations + "var blah = "; 76 | string endString = " ; } } }"; 77 | string codeString = startString + this.Text.Substring(0, this.CaretOffset) + endString; 78 | 79 | var tree = CSharpSyntaxTree.ParseText(codeString); 80 | 81 | var root = (CompilationUnitSyntax)tree.GetRoot(); 82 | 83 | var compilation = CSharpCompilation.Create("CustomIntellisense") 84 | .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) 85 | .AddSyntaxTrees(tree); 86 | 87 | var model = compilation.GetSemanticModel(tree); 88 | 89 | var exprString = root.FindToken(codeString.LastIndexOf('.') - 1).Parent; 90 | 91 | var literalInfo = model.GetTypeInfo(exprString); 92 | 93 | var stringTypeSymbol = (INamedTypeSymbol)literalInfo.Type; 94 | IList symbols = new List() { }; 95 | foreach (var s in (from method in stringTypeSymbol.GetMembers() where method.DeclaredAccessibility == Accessibility.Public select method).Distinct()) 96 | symbols.Add(s); 97 | 98 | if (symbols != null && symbols.Count > 0) 99 | { 100 | completionWindow = new CompletionWindow(this.TextArea); 101 | IList data = completionWindow.CompletionList.CompletionData; 102 | data.Clear(); 103 | var distinctSymbols = from s in symbols group s by s.Name into g select new { Name = g.Key, Symbols = g }; 104 | foreach (var g in distinctSymbols.OrderBy(s => s.Name)) 105 | { 106 | data.Add(new QueryCompletionData(g.Name, g.Symbols.ToArray())); 107 | } 108 | 109 | completionWindow.Show(); 110 | completionWindow.Closed += delegate 111 | { 112 | completionWindow = null; 113 | }; 114 | } 115 | } 116 | catch (Exception ex) 117 | { 118 | Console.WriteLine(ex.ToString()); 119 | } 120 | } 121 | } 122 | 123 | private void TextArea_TextEntering(object sender, System.Windows.Input.TextCompositionEventArgs e) 124 | { 125 | if (e.Text.Length > 0 && completionWindow != null) 126 | { 127 | if (!char.IsLetterOrDigit(e.Text[0])) 128 | { 129 | // Whenever a non-letter is typed while the completion window is open, 130 | // insert the currently selected element. 131 | completionWindow.CompletionList.RequestInsertion(e); 132 | } 133 | } 134 | // Do not set e.Handled=true. 135 | // We still want to insert the character that was typed. 136 | } 137 | 138 | private void TextArea_LostFocus(object sender, RoutedEventArgs e) 139 | { 140 | if (this.LostAggregateFocus != null) 141 | { 142 | this.LostAggregateFocus(sender, e); 143 | } 144 | } 145 | 146 | #region IExpressionEditorInstance implicit 147 | 148 | public bool AcceptsReturn { get; set; } 149 | 150 | public bool AcceptsTab { get; set; } 151 | 152 | public bool HasAggregateFocus 153 | { 154 | get 155 | { 156 | return true; 157 | } 158 | } 159 | 160 | public Control HostControl 161 | { 162 | get 163 | { 164 | return this; 165 | } 166 | } 167 | 168 | public int MaxLines { get; set; } 169 | 170 | public int MinLines { get; set; } 171 | 172 | public event EventHandler Closing; 173 | public event EventHandler GotAggregateFocus; 174 | public event EventHandler LostAggregateFocus; 175 | 176 | public bool CanCompleteWord() 177 | { 178 | return true; 179 | } 180 | 181 | public bool CanCopy() 182 | { 183 | return true; 184 | } 185 | 186 | public bool CanCut() 187 | { 188 | return true; 189 | } 190 | 191 | public bool CanDecreaseFilterLevel() 192 | { 193 | return true; 194 | } 195 | 196 | public bool CanGlobalIntellisense() 197 | { 198 | return true; 199 | } 200 | 201 | public bool CanIncreaseFilterLevel() 202 | { 203 | return true; 204 | } 205 | 206 | public bool CanParameterInfo() 207 | { 208 | return true; 209 | } 210 | 211 | public bool CanPaste() 212 | { 213 | return true; 214 | } 215 | 216 | public bool CanQuickInfo() 217 | { 218 | return true; 219 | } 220 | 221 | public void ClearSelection() 222 | { 223 | 224 | } 225 | 226 | public void Close() 227 | { 228 | 229 | } 230 | 231 | public bool CompleteWord() 232 | { 233 | return true; 234 | } 235 | 236 | public string GetCommittedText() 237 | { 238 | return this.Text; 239 | } 240 | 241 | public bool GlobalIntellisense() 242 | { 243 | return true; 244 | } 245 | public bool DecreaseFilterLevel() 246 | { 247 | return true; 248 | } 249 | 250 | public bool IncreaseFilterLevel() 251 | { 252 | return true; 253 | } 254 | 255 | public bool ParameterInfo() 256 | { 257 | return true; 258 | } 259 | 260 | public bool QuickInfo() 261 | { 262 | return true; 263 | } 264 | 265 | #endregion 266 | 267 | #region IExpressionEditorInstance explicit 268 | 269 | void IExpressionEditorInstance.Focus() 270 | { 271 | base.Focus(); 272 | } 273 | 274 | bool IExpressionEditorInstance.Cut() 275 | { 276 | base.Cut(); 277 | return true; 278 | } 279 | 280 | bool IExpressionEditorInstance.Copy() 281 | { 282 | base.Copy(); 283 | return true; 284 | } 285 | 286 | bool IExpressionEditorInstance.Paste() 287 | { 288 | base.Paste(); 289 | return true; 290 | } 291 | 292 | bool IExpressionEditorInstance.Undo() 293 | { 294 | return base.Undo(); 295 | } 296 | 297 | bool IExpressionEditorInstance.Redo() 298 | { 299 | return base.Redo(); 300 | } 301 | 302 | bool IExpressionEditorInstance.CanUndo() 303 | { 304 | return base.CanUndo; 305 | } 306 | 307 | bool IExpressionEditorInstance.CanRedo() 308 | { 309 | return base.CanRedo; 310 | } 311 | 312 | event EventHandler IExpressionEditorInstance.TextChanged 313 | { 314 | add 315 | { 316 | base.TextChanged += value; 317 | } 318 | 319 | remove 320 | { 321 | base.TextChanged -= value; 322 | } 323 | } 324 | 325 | string IExpressionEditorInstance.Text 326 | { 327 | get 328 | { 329 | return base.Text; 330 | } 331 | 332 | set 333 | { 334 | base.Text = value; 335 | } 336 | } 337 | 338 | ScrollBarVisibility IExpressionEditorInstance.VerticalScrollBarVisibility 339 | { 340 | get 341 | { 342 | return base.VerticalScrollBarVisibility; 343 | } 344 | 345 | set 346 | { 347 | base.VerticalScrollBarVisibility = value; 348 | } 349 | } 350 | 351 | ScrollBarVisibility IExpressionEditorInstance.HorizontalScrollBarVisibility 352 | { 353 | get 354 | { 355 | return base.HorizontalScrollBarVisibility; 356 | } 357 | 358 | set 359 | { 360 | base.HorizontalScrollBarVisibility = value; 361 | } 362 | } 363 | 364 | 365 | #endregion 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/RoslynExpressionEditorService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System; 3 | using System.Activities.Presentation.Hosting; 4 | using System.Activities.Presentation.Model; 5 | using System.Activities.Presentation.View; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Windows; 10 | 11 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 12 | { 13 | public class RoslynExpressionEditorService : IExpressionEditorService 14 | { 15 | private static RoslynExpressionEditorService instance = new RoslynExpressionEditorService(); 16 | private MetadataReference[] baseAssemblies = new MetadataReference[0]; 17 | private string usingNamespaces = string.Empty; 18 | 19 | public static RoslynExpressionEditorService Instance 20 | { 21 | get { return instance; } 22 | } 23 | 24 | internal string UsingNamespaces 25 | { 26 | get { return usingNamespaces; } 27 | } 28 | 29 | internal MetadataReference[] BaseAssemblies 30 | { 31 | get { return baseAssemblies; } 32 | } 33 | 34 | public void CloseExpressionEditors() 35 | { 36 | 37 | } 38 | 39 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text) 40 | { 41 | return CreateExpressionEditor(assemblies, importedNamespaces, variables, text, null, Size.Empty); 42 | } 43 | 44 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, Size initialSize) 45 | { 46 | return CreateExpressionEditor(assemblies, importedNamespaces, variables, text, null, initialSize); 47 | } 48 | 49 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, Type expressionType) 50 | { 51 | return CreateExpressionEditor(assemblies, importedNamespaces, variables, text, expressionType, Size.Empty); 52 | } 53 | 54 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, Type expressionType, Size initialSize) 55 | { 56 | UpdateContext(assemblies, importedNamespaces); 57 | var editor = new RoslynExpressionEditorInstance(initialSize); 58 | editor.UpdateInstance(variables, text); 59 | return editor; 60 | } 61 | 62 | public void UpdateContext(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces) 63 | { 64 | var references = new List(); 65 | 66 | foreach (var assembly in assemblies.AllAssemblyNamesInContext) 67 | { 68 | System.Reflection.Assembly asm = null; 69 | try 70 | { 71 | asm = System.Reflection.Assembly.Load(assembly); 72 | } 73 | catch (Exception ex) { 74 | //Console.WriteLine(ex.ToString()); 75 | } 76 | if(asm != null) 77 | if(File.Exists(asm.Location)) 78 | references.Add(MetadataReference.CreateFromFile(asm.Location)); 79 | } 80 | 81 | baseAssemblies = references.ToArray(); 82 | 83 | usingNamespaces = string.Join("", importedNamespaces.ImportedNamespaces.Select(ns => "using " + ns + ";\n").ToArray()); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/CSharpExpressionEditor/XamlUtilities.cs: -------------------------------------------------------------------------------- 1 | namespace RehostedWorkflowDesigner.CSharpExpressionEditor 2 | { 3 | using System; 4 | using System.Collections; 5 | using System.ComponentModel; 6 | using System.Reflection; 7 | 8 | internal static class XamlUtilities 9 | { 10 | static Hashtable converterCache; 11 | static object converterCacheSyncObject = new object(); 12 | 13 | public static TypeConverter GetConverter(Type itemType) 14 | { 15 | TypeConverter converter = TypeDescriptor.GetConverter(itemType); 16 | 17 | if (converter == null || converter.GetType() == typeof(TypeConverter)) 18 | { 19 | 20 | // We got an invalid converter. WPF will do this if the converter 21 | // is internal, but we use internal converters all over the place 22 | // at design time. Detect this and build the converter ourselves. 23 | 24 | if (converterCache != null) 25 | { 26 | converter = (TypeConverter)converterCache[itemType]; 27 | if (converter != null) 28 | { 29 | return converter; 30 | } 31 | } 32 | 33 | AttributeCollection attrs = TypeDescriptor.GetAttributes(itemType); 34 | TypeConverterAttribute tca = attrs[typeof(TypeConverterAttribute)] as TypeConverterAttribute; 35 | if (tca != null && tca.ConverterTypeName != null) 36 | { 37 | Type type = Type.GetType(tca.ConverterTypeName); 38 | if (type != null && !type.IsPublic && typeof(TypeConverter).IsAssignableFrom(type)) 39 | { 40 | ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(Type) }); 41 | if (ctor != null) 42 | { 43 | converter = (TypeConverter)ctor.Invoke(new object[] { itemType }); 44 | } 45 | else 46 | { 47 | converter = (TypeConverter)Activator.CreateInstance(type); 48 | } 49 | 50 | lock (converterCacheSyncObject) 51 | { 52 | if (converterCache == null) 53 | { 54 | converterCache = new Hashtable(); 55 | 56 | // Listen to type changes and clear the cache. 57 | // This allows new metadata tables to be installed 58 | 59 | TypeDescriptor.Refreshed += delegate (RefreshEventArgs args) 60 | { 61 | converterCache.Remove(args.TypeChanged); 62 | }; 63 | } 64 | 65 | converterCache[itemType] = converter; 66 | } 67 | } 68 | } 69 | } 70 | 71 | return converter; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Helpers/CustomCommands.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Input; 2 | 3 | namespace RehostedWorkflowDesigner.Helpers 4 | { 5 | /// 6 | /// Custom Commands 7 | /// 8 | public static class CustomCommands 9 | { 10 | public static ICommand CmdWfNewCSharp = new RoutedCommand("CmdWfNewCSharp", typeof(CustomCommands)); 11 | public static ICommand CmdWfNewVB = new RoutedCommand("CmdWfNewVB", typeof(CustomCommands)); 12 | public static ICommand CmdWfNew = new RoutedCommand("CmdWfNew", typeof(CustomCommands)); 13 | public static ICommand CmdWfRun = new RoutedCommand("CmdWfRun", typeof(CustomCommands)); 14 | public static ICommand CmdWfStop = new RoutedCommand("CmdWfStop", typeof(CustomCommands)); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Helpers/CustomTrackingParticipant.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Activities.Tracking; 7 | using System.IO; 8 | 9 | namespace RehostedWorkflowDesigner.Helpers 10 | { 11 | 12 | /// 13 | /// Workflow Tracking Participant - Custom Implementation 14 | /// 15 | class CustomTrackingParticipant : TrackingParticipant 16 | { 17 | public string TrackData = String.Empty; 18 | 19 | /// 20 | /// Appends the current TrackingRecord data to the Workflow Execution Log 21 | /// 22 | /// Tracking Record Data 23 | /// Timestamp 24 | protected override void Track(TrackingRecord trackRecord, TimeSpan timeStamp) 25 | { 26 | ActivityStateRecord recordEntry = trackRecord as ActivityStateRecord; 27 | 28 | if (recordEntry != null) 29 | { 30 | TrackData += String.Format("[{0}] [{1}] [{2}]" + Environment.NewLine, recordEntry.EventTime.ToLocalTime().ToString(), recordEntry.Activity.Name, recordEntry.State); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Helpers/CustomWfDesigner.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CSharp.Activities; 2 | using RehostedWorkflowDesigner.CSharpExpressionEditor; 3 | using RehostedWorkflowDesigner.VbExpressionEditor; 4 | using System; 5 | using System.Activities.Core.Presentation; 6 | using System.Activities.Presentation; 7 | using System.Activities.Presentation.View; 8 | using System.Activities.Statements; 9 | 10 | namespace RehostedWorkflowDesigner.Helpers 11 | { 12 | /// 13 | /// Workflow Designer Wrapper 14 | /// 15 | static class CustomWfDesigner 16 | { 17 | private static WorkflowDesigner _wfDesigner; 18 | private const String _defaultWorkflow = "defaultWorkflow.xaml"; 19 | private const String _defaultWorkflowCSharp = "defaultWorkflowCSharp.xaml"; 20 | private static RoslynExpressionEditorService _expressionEditorService; 21 | private static VbExpressionEditorService _expressionEditorServiceVB; 22 | 23 | /// 24 | /// Gets the current WorkflowDesigner Instance 25 | /// 26 | public static WorkflowDesigner Instance 27 | { 28 | get 29 | { 30 | if (_wfDesigner == null) 31 | NewInstance(_defaultWorkflow); 32 | return _wfDesigner; 33 | } 34 | } 35 | 36 | /// 37 | /// Creates a new Workflow Designer instance (VB) 38 | /// 39 | /// Workflow FileName 40 | public static void NewInstance(string sourceFile = _defaultWorkflow) 41 | { 42 | _wfDesigner = new WorkflowDesigner(); 43 | _wfDesigner.Context.Services.GetService().TargetFrameworkName = new System.Runtime.Versioning.FrameworkName(".NETFramework", new Version(4, 5)); 44 | _wfDesigner.Context.Services.GetService().LoadingFromUntrustedSourceEnabled = true; 45 | 46 | //associates all of the basic activities with their designers 47 | new DesignerMetadata().Register(); 48 | 49 | //load Workflow Xaml 50 | _wfDesigner.Load(sourceFile); 51 | } 52 | 53 | /// 54 | /// Creates a new Workflow Designer instance (VB) with Intellisense 55 | /// 56 | /// Workflow FileName 57 | public static void NewInstanceVB(string sourceFile = _defaultWorkflow) 58 | { 59 | _expressionEditorServiceVB = new VbExpressionEditorService(); 60 | 61 | _wfDesigner = new WorkflowDesigner(); 62 | _wfDesigner.Context.Services.GetService().TargetFrameworkName = new System.Runtime.Versioning.FrameworkName(".NETFramework", new Version(4, 5)); 63 | _wfDesigner.Context.Services.GetService().LoadingFromUntrustedSourceEnabled = true; 64 | _wfDesigner.Context.Services.Publish(_expressionEditorServiceVB); 65 | 66 | //associates all of the basic activities with their designers 67 | new DesignerMetadata().Register(); 68 | 69 | //load Workflow Xaml 70 | _wfDesigner.Load(sourceFile); 71 | } 72 | 73 | /// 74 | /// Creates a new Workflow Designer instance with C# Expression Editor 75 | /// 76 | /// Workflow FileName 77 | public static void NewInstanceCSharp(string sourceFile = _defaultWorkflowCSharp) 78 | { 79 | _expressionEditorService = new RoslynExpressionEditorService(); 80 | ExpressionTextBox.RegisterExpressionActivityEditor(new CSharpValue().Language, typeof(RoslynExpressionEditor), CSharpExpressionHelper.CreateExpressionFromString); 81 | 82 | _wfDesigner = new WorkflowDesigner(); 83 | _wfDesigner.Context.Services.GetService().TargetFrameworkName = new System.Runtime.Versioning.FrameworkName(".NETFramework", new Version(4, 5)); 84 | _wfDesigner.Context.Services.GetService().LoadingFromUntrustedSourceEnabled = true; 85 | _wfDesigner.Context.Services.Publish(_expressionEditorService); 86 | 87 | //associates all of the basic activities with their designers 88 | new DesignerMetadata().Register(); 89 | 90 | //load Workflow Xaml 91 | _wfDesigner.Load(sourceFile); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Helpers/QueryCompletionData.cs: -------------------------------------------------------------------------------- 1 | using ICSharpCode.AvalonEdit.CodeCompletion; 2 | using ICSharpCode.AvalonEdit.Document; 3 | using ICSharpCode.AvalonEdit.Editing; 4 | using Microsoft.CodeAnalysis; 5 | using System; 6 | using System.Windows.Media; 7 | using System.Windows.Media.Imaging; 8 | 9 | namespace RehostedWorkflowDesigner.Helpers 10 | { 11 | public class QueryCompletionData : ICompletionData 12 | { 13 | private static ImageSource MethodIcon; 14 | private static ImageSource PropertyIcon; 15 | private static ImageSource FieldIcon; 16 | private static ImageSource EventIcon; 17 | 18 | private IconType iconType; 19 | 20 | static QueryCompletionData() 21 | { 22 | MethodIcon = GetImageSourceFromResource("Method.png"); 23 | PropertyIcon = GetImageSourceFromResource("Property.png"); 24 | FieldIcon = GetImageSourceFromResource("Field.png"); 25 | EventIcon = GetImageSourceFromResource("Event.png"); 26 | } 27 | 28 | static internal ImageSource GetImageSourceFromResource(string resourceName) 29 | { 30 | return BitmapFrame.Create(typeof(QueryCompletionData).Assembly.GetManifestResourceStream("RehostedWorkflowDesigner.Resources.ExpressionEditor." + resourceName)); 31 | } 32 | 33 | public QueryCompletionData(string name, ISymbol[] symbols) 34 | { 35 | this.Text = name; 36 | switch (symbols[0].Kind) 37 | { 38 | case SymbolKind.Event: iconType = IconType.Event; break; 39 | case SymbolKind.Field: iconType = IconType.Field; break; 40 | case SymbolKind.Method: iconType = IconType.Method; break; 41 | case SymbolKind.Property: iconType = IconType.Property; break; 42 | } 43 | } 44 | 45 | public ImageSource Image 46 | { 47 | get 48 | { 49 | switch (iconType) 50 | { 51 | case IconType.Event: return EventIcon; 52 | case IconType.Field: return FieldIcon; 53 | case IconType.Property: return PropertyIcon; 54 | default: return MethodIcon; 55 | } 56 | } 57 | } 58 | 59 | public string Text { get; private set; } 60 | public string HintText { get; private set; } 61 | 62 | // Use this property if you want to show a fancy UIElement in the list. 63 | public object Content 64 | { 65 | get { return this.Text; } 66 | } 67 | 68 | public object Description 69 | { 70 | get { return "Description for " + this.Text; } 71 | } 72 | 73 | public void Complete(TextArea textArea, ISegment completionSegment, 74 | EventArgs insertionRequestEventArgs) 75 | { 76 | textArea.Document.Replace(completionSegment, this.Text); 77 | } 78 | 79 | public double Priority 80 | { 81 | get { return 1.0; } 82 | } 83 | 84 | enum IconType 85 | { 86 | Property, 87 | Field, 88 | Method, 89 | Event, 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("meetup - workflow foundation - intro")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Andrei Oros")] 14 | [assembly: AssemblyProduct("meetup - workflow foundation - intro")] 15 | [assembly: AssemblyCopyright("Copyright © 2014")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RehostedWorkflowDesigner.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RehostedWorkflowDesigner.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap Event { 67 | get { 68 | object obj = ResourceManager.GetObject("Event", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap Field { 77 | get { 78 | object obj = ResourceManager.GetObject("Field", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap Method { 87 | get { 88 | object obj = ResourceManager.GetObject("Method", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap Property { 97 | get { 98 | object obj = ResourceManager.GetObject("Property", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\ExpressionEditor\Event.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\ExpressionEditor\Field.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\ExpressionEditor\Method.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\ExpressionEditor\Property.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace RehostedWorkflowDesigner.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.3.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/ExpressionEditor/Event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/ExpressionEditor/Event.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/ExpressionEditor/Field.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/ExpressionEditor/Field.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/ExpressionEditor/Method.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/ExpressionEditor/Method.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/ExpressionEditor/Property.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/ExpressionEditor/Property.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/exit.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/new.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/open.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/pause.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/run.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/save.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/Menu/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/Menu/stop.png -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Resources/icon_app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/CoreFlow.Designer/Resources/icon_app.ico -------------------------------------------------------------------------------- /src/CoreFlow.Designer/SampleWorkflow/LocalWinServicesCSV.xaml: -------------------------------------------------------------------------------- 1 |  15 | 16 | 17 | 18 | 19 | RehostedWorkflowDesigner.Workflow_1 20 | 21 | 22 | System.Management.Automation 23 | System.Activities 24 | System.Collections.Generic 25 | System 26 | 27 | 28 | 29 | 30 | System.Management.Automation 31 | System.Activities 32 | mscorlib 33 | System 34 | System.Core 35 | System.ServiceModel 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | [ServicesCSV] 45 | 46 | 47 | ["Service,Status" + Environment.NewLine] 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | [ServicesCSV] 59 | 60 | 61 | [ServicesCSV + svc.ToString() + "," + Status + Environment.NewLine] 62 | 63 | 64 | 65 | 66 | 67 | 68 | d0NDOlxVc2Vyc1xBbmRyZWlcRGVza3RvcFxNUyBTdW1taXRcZGVtbyBiaW5cTG9jYWxXaW5TZXJ2aWNlc0NTVi54YW1sEQFhAWkBAiYDRQ4CAQEqBTEOAgERMgUyrQECAQ4zBUEPAgEIQgVCjAECAQRDBUN/AgECLzAvWAIBFCwxLD4CARIyngEyqgECAQ8ziAEzlAECAQ04CT8SAgEJQnpCiQECAQZCM0JBAgEFQz1DSwIBAz00PXcCAQw6NTpCAgEK 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | True 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/VbExpressionEditor/VbExpressionEditorInstance.cs: -------------------------------------------------------------------------------- 1 | using ICSharpCode.AvalonEdit; 2 | using ICSharpCode.AvalonEdit.CodeCompletion; 3 | using ICSharpCode.AvalonEdit.Highlighting; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | using Microsoft.CodeAnalysis.VisualBasic; 8 | using RehostedWorkflowDesigner.Helpers; 9 | using System; 10 | using System.Activities.Presentation.Model; 11 | using System.Activities.Presentation.View; 12 | using System.Collections.Generic; 13 | using System.Linq; 14 | using System.Reflection; 15 | using System.Windows; 16 | using System.Windows.Controls; 17 | using System.Windows.Input; 18 | 19 | namespace RehostedWorkflowDesigner.VbExpressionEditor 20 | { 21 | public class VbExpressionEditorInstance : TextEditor, IExpressionEditorInstance 22 | { 23 | private CompletionWindow completionWindow; 24 | 25 | private TextBox textBox = new TextBox(); 26 | 27 | public VbExpressionEditorInstance() 28 | { 29 | this.TextArea.TextEntering += TextArea_TextEntering; 30 | this.TextArea.TextEntered += TextArea_TextEntered; 31 | this.TextArea.LostKeyboardFocus += TextArea_LostFocus; 32 | 33 | this.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("VB"); 34 | this.FontFamily = new System.Windows.Media.FontFamily("Consolas"); 35 | this.FontSize = 12; 36 | } 37 | 38 | private void TextArea_TextEntered(object sender, System.Windows.Input.TextCompositionEventArgs e) 39 | { 40 | if (e.Text == ".") 41 | { 42 | try 43 | { 44 | string startString = @" 45 | Imports System 46 | Imports System.Collections.Generic 47 | Imports System.Text 48 | 49 | Namespace SomeNamespace 50 | 51 | Public Class NotAProgram 52 | Private Sub SomeMethod() 53 | " 54 | + "var blah = "; 55 | 56 | string endString = @" 57 | 58 | End Sub 59 | End Class 60 | End Namespace 61 | "; 62 | string codeString = startString + this.Text.Substring(0, this.CaretOffset) + endString; 63 | 64 | var tree = VisualBasicSyntaxTree.ParseText(codeString); 65 | 66 | var root = (Microsoft.CodeAnalysis.VisualBasic.Syntax.CompilationUnitSyntax)tree.GetRoot(); 67 | 68 | var compilation = VisualBasicCompilation.Create("CustomIntellisense") 69 | .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) 70 | .AddSyntaxTrees(tree); 71 | 72 | var model = compilation.GetSemanticModel(tree); 73 | 74 | var exprString = root.FindToken(codeString.LastIndexOf('.') - 1).Parent; 75 | 76 | var literalInfo = model.GetTypeInfo(exprString); 77 | 78 | var stringTypeSymbol = (INamedTypeSymbol)literalInfo.Type; 79 | IList symbols = new List() { }; 80 | foreach (var s in (from method in stringTypeSymbol.GetMembers() where method.DeclaredAccessibility == Accessibility.Public select method).Distinct()) 81 | symbols.Add(s); 82 | 83 | if (symbols != null && symbols.Count > 0) 84 | { 85 | completionWindow = new CompletionWindow(this.TextArea); 86 | IList data = completionWindow.CompletionList.CompletionData; 87 | data.Clear(); 88 | var distinctSymbols = from s in symbols group s by s.Name into g select new { Name = g.Key, Symbols = g }; 89 | foreach (var g in distinctSymbols.OrderBy(s => s.Name)) 90 | { 91 | data.Add(new QueryCompletionData(g.Name, g.Symbols.ToArray())); 92 | } 93 | 94 | completionWindow.Show(); 95 | completionWindow.Closed += delegate 96 | { 97 | completionWindow = null; 98 | }; 99 | } 100 | } 101 | catch (Exception ex) 102 | { 103 | Console.WriteLine(ex.ToString()); 104 | } 105 | } 106 | } 107 | 108 | private void TextArea_LostFocus(object sender, RoutedEventArgs e) 109 | { 110 | if (this.LostAggregateFocus != null) 111 | { 112 | this.LostAggregateFocus(sender, e); 113 | } 114 | } 115 | 116 | private void TextArea_TextEntering(object sender, System.Windows.Input.TextCompositionEventArgs e) 117 | { 118 | if (e.Text.Length > 0 && completionWindow != null) 119 | { 120 | if (!char.IsLetterOrDigit(e.Text[0])) 121 | { 122 | // Whenever a non-letter is typed while the completion window is open, 123 | // insert the currently selected element. 124 | completionWindow.CompletionList.RequestInsertion(e); 125 | } 126 | } 127 | // Do not set e.Handled=true. 128 | // We still want to insert the character that was typed. 129 | } 130 | 131 | #region IExpressionEditorInstance implicit 132 | 133 | public bool AcceptsReturn { get; set; } 134 | 135 | public bool AcceptsTab { get; set; } 136 | 137 | public bool HasAggregateFocus 138 | { 139 | get 140 | { 141 | return true; 142 | } 143 | } 144 | 145 | public Control HostControl 146 | { 147 | get 148 | { 149 | return this; 150 | } 151 | } 152 | 153 | public int MaxLines { get; set; } 154 | 155 | public int MinLines { get; set; } 156 | 157 | public event EventHandler Closing; 158 | public event EventHandler GotAggregateFocus; 159 | public event EventHandler LostAggregateFocus; 160 | 161 | public bool CanCompleteWord() 162 | { 163 | return true; 164 | } 165 | 166 | public bool CanCopy() 167 | { 168 | return true; 169 | } 170 | 171 | public bool CanCut() 172 | { 173 | return true; 174 | } 175 | 176 | public bool CanDecreaseFilterLevel() 177 | { 178 | return true; 179 | } 180 | 181 | public bool CanGlobalIntellisense() 182 | { 183 | return true; 184 | } 185 | 186 | public bool CanIncreaseFilterLevel() 187 | { 188 | return true; 189 | } 190 | 191 | public bool CanParameterInfo() 192 | { 193 | return true; 194 | } 195 | 196 | public bool CanPaste() 197 | { 198 | return true; 199 | } 200 | 201 | public bool CanQuickInfo() 202 | { 203 | return true; 204 | } 205 | 206 | public void ClearSelection() 207 | { 208 | 209 | } 210 | 211 | public void Close() 212 | { 213 | 214 | } 215 | 216 | public bool CompleteWord() 217 | { 218 | return true; 219 | } 220 | 221 | public string GetCommittedText() 222 | { 223 | return this.Text; 224 | } 225 | 226 | public bool GlobalIntellisense() 227 | { 228 | return true; 229 | } 230 | public bool DecreaseFilterLevel() 231 | { 232 | return true; 233 | } 234 | 235 | public bool IncreaseFilterLevel() 236 | { 237 | return true; 238 | } 239 | 240 | public bool ParameterInfo() 241 | { 242 | return true; 243 | } 244 | 245 | public bool QuickInfo() 246 | { 247 | return true; 248 | } 249 | 250 | #endregion 251 | 252 | #region IExpressionEditorInstance explicit 253 | 254 | void IExpressionEditorInstance.Focus() 255 | { 256 | base.Focus(); 257 | } 258 | 259 | bool IExpressionEditorInstance.Cut() 260 | { 261 | base.Cut(); 262 | return true; 263 | } 264 | 265 | bool IExpressionEditorInstance.Copy() 266 | { 267 | base.Copy(); 268 | return true; 269 | } 270 | 271 | bool IExpressionEditorInstance.Paste() 272 | { 273 | base.Paste(); 274 | return true; 275 | } 276 | 277 | bool IExpressionEditorInstance.Undo() 278 | { 279 | return base.Undo(); 280 | } 281 | 282 | bool IExpressionEditorInstance.Redo() 283 | { 284 | return base.Redo(); 285 | } 286 | 287 | bool IExpressionEditorInstance.CanUndo() 288 | { 289 | return base.CanUndo; 290 | } 291 | 292 | bool IExpressionEditorInstance.CanRedo() 293 | { 294 | return base.CanRedo; 295 | } 296 | 297 | event EventHandler IExpressionEditorInstance.TextChanged 298 | { 299 | add 300 | { 301 | base.TextChanged += value; 302 | } 303 | 304 | remove 305 | { 306 | base.TextChanged -= value; 307 | } 308 | } 309 | 310 | string IExpressionEditorInstance.Text 311 | { 312 | get 313 | { 314 | return base.Text; 315 | } 316 | 317 | set 318 | { 319 | base.Text = value; 320 | } 321 | } 322 | 323 | ScrollBarVisibility IExpressionEditorInstance.VerticalScrollBarVisibility 324 | { 325 | get 326 | { 327 | return base.VerticalScrollBarVisibility; 328 | } 329 | 330 | set 331 | { 332 | base.VerticalScrollBarVisibility = value; 333 | } 334 | } 335 | 336 | ScrollBarVisibility IExpressionEditorInstance.HorizontalScrollBarVisibility 337 | { 338 | get 339 | { 340 | return base.HorizontalScrollBarVisibility; 341 | } 342 | 343 | set 344 | { 345 | base.HorizontalScrollBarVisibility = value; 346 | } 347 | } 348 | 349 | 350 | #endregion 351 | } 352 | } 353 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/VbExpressionEditor/VbExpressionEditorService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System; 3 | using System.Activities.Presentation.Hosting; 4 | using System.Activities.Presentation.Model; 5 | using System.Activities.Presentation.View; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Windows; 10 | 11 | namespace RehostedWorkflowDesigner.VbExpressionEditor 12 | { 13 | public class VbExpressionEditorService : IExpressionEditorService 14 | { 15 | public void CloseExpressionEditors() 16 | { 17 | 18 | } 19 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text) 20 | { 21 | VbExpressionEditorInstance instance = new VbExpressionEditorInstance(); 22 | return instance; 23 | } 24 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, System.Windows.Size initialSize) 25 | { 26 | VbExpressionEditorInstance instance = new VbExpressionEditorInstance(); 27 | return instance; 28 | } 29 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, Type expressionType) 30 | { 31 | VbExpressionEditorInstance instance = new VbExpressionEditorInstance(); 32 | return instance; 33 | } 34 | public IExpressionEditorInstance CreateExpressionEditor(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces, List variables, string text, Type expressionType, System.Windows.Size initialSize) 35 | { 36 | VbExpressionEditorInstance instance = new VbExpressionEditorInstance(); 37 | return instance; 38 | } 39 | public void UpdateContext(AssemblyContextControlItem assemblies, ImportedNamespaceContextItem importedNamespaces) 40 | { 41 | 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/CoreFlow.Designer/Views/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 76 | 77 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/defaultWorkflow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | RehostedWorkflowDesigner.Workflow_1 11 | 12 | 13 | 14 | 15 | 16 | True 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/defaultWorkflowCSharp.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | RehostedWorkflowDesigner.Workflow_1 11 | 12 | 13 | 14 | 15 | 16 | True 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/CoreFlow.Designer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Controllers/WorkflowDefinitionController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Hosting; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using CoreFlow.Activities; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | 11 | namespace CoreFlow.Engine.Controllers 12 | { 13 | // Maintain the database of Workflow Definitions 14 | 15 | [Route("api/model")] 16 | [ApiController] 17 | public class WorkflowModelController : ControllerBase 18 | { 19 | RuntimeEngine runtime; 20 | public WorkflowModelController(RuntimeEngine runtime) 21 | { 22 | this.runtime = runtime; 23 | } 24 | 25 | // GET: api/WorkflowModel 26 | [HttpGet] 27 | public IEnumerable Get() 28 | { 29 | return new String[0]; 30 | } 31 | 32 | // GET: api/WorkflowModel/5 33 | [HttpGet("{name}")] 34 | public string Get(String name) 35 | { 36 | return "value"; 37 | } 38 | 39 | // POST: api/WorkflowInstance 40 | [HttpPost("{name}")] 41 | public void Post([FromBody] string value) 42 | { 43 | } 44 | 45 | // DELETE: api/WorkflowModel/5 46 | [HttpDelete("{name}")] 47 | public void Delete(String name) 48 | { 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Controllers/WorkflowInstanceController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | using System.Activities.Hosting; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using CoreFlow.Activities; 8 | using Microsoft.AspNetCore.Http; 9 | using Microsoft.AspNetCore.Mvc; 10 | 11 | namespace CoreFlow.Engine.Controllers 12 | { 13 | [Route("api/instance")] 14 | [ApiController] 15 | public class WorkflowInstanceController : ControllerBase 16 | { 17 | RuntimeEngine runtime; 18 | public WorkflowInstanceController(RuntimeEngine runtime) 19 | { 20 | this.runtime = runtime; 21 | } 22 | 23 | // GET: api/instance 24 | [HttpGet] 25 | public IActionResult Get() 26 | { 27 | runtime.StartNewInstance("Process1"); 28 | 29 | return Ok(runtime.GetInstances()); 30 | } 31 | 32 | // GET: api/instance/5 33 | [HttpGet("{id}/{bookmark}/{data}")] 34 | public IActionResult Get(Guid id, String bookmark, String data) 35 | { 36 | runtime.ResumeBookmark(id, bookmark, data); 37 | return Ok(); 38 | } 39 | 40 | // POST: api/instance 41 | [HttpPost] 42 | public void Post([FromBody] string value) 43 | { 44 | } 45 | 46 | // PUT: api/instance/5 47 | [HttpPut("{id}")] 48 | public void Put(int id, [FromBody] string value) 49 | { 50 | } 51 | 52 | // DELETE: api/ApiWithActions/5 53 | [HttpDelete("{id}")] 54 | public void Delete(int id) 55 | { 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/CoreFlow.Engine.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 46e84156-d3c4-403a-b866-301eba69da7d 6 | Linux 7 | ..\.. 8 | ..\docker-compose.dcproj 9 | Debug;Release;Debug-no-compose 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | MSBuild:Compile 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Dockerfile: -------------------------------------------------------------------------------- 1 | #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 | 3 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base 4 | WORKDIR /app 5 | EXPOSE 80 6 | EXPOSE 443 7 | 8 | FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build 9 | WORKDIR /src 10 | COPY ["CoreFlow/CoreFlow.Engine/CoreFlow.Engine.csproj", "CoreFlow/CoreFlow.Engine/"] 11 | RUN dotnet restore "CoreFlow/CoreFlow.Engine/CoreFlow.Engine.csproj" 12 | COPY . . 13 | WORKDIR "/src/CoreFlow/CoreFlow.Engine" 14 | RUN dotnet build "CoreFlow.Engine.csproj" -c Release -o /app/build 15 | 16 | FROM build AS publish 17 | RUN dotnet publish "CoreFlow.Engine.csproj" -c Release -o /app/publish 18 | 19 | FROM base AS final 20 | WORKDIR /app 21 | COPY --from=publish /app/publish . 22 | ENTRYPOINT ["dotnet", "CoreFlow.Engine.dll"] -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace CoreFlow.Engine 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .ConfigureAppConfiguration((hostingContext, config) => 23 | { 24 | var env = hostingContext.HostingEnvironment; 25 | config.SetBasePath(env.ContentRootPath) 26 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 27 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); 28 | config.AddCommandLine(args); 29 | config.AddEnvironmentVariables(); 30 | }) 31 | .ConfigureWebHostDefaults(webBuilder => 32 | { 33 | webBuilder.UseStartup(); 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:55074", 7 | "sslPort": 44354 8 | } 9 | }, 10 | "$schema": "http://json.schemastore.org/launchsettings.json", 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "launchUrl": "api/instance", 16 | "environmentVariables": { 17 | "ASPNETCORE_ENVIRONMENT": "Development" 18 | } 19 | }, 20 | "CoreFlow.Engine": { 21 | "commandName": "Project", 22 | "launchBrowser": true, 23 | "launchUrl": "api/instance", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | }, 27 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 28 | }, 29 | "Docker": { 30 | "commandName": "Docker", 31 | "launchBrowser": true, 32 | "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/api/instance", 33 | "publishAllPorts": true, 34 | "useSSL": true 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/CoreFlow.Engine/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using CoreFlow.Activities; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.AspNetCore.HttpsPolicy; 9 | using Microsoft.AspNetCore.Mvc; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Hosting; 13 | using Microsoft.Extensions.Logging; 14 | 15 | namespace CoreFlow.Engine 16 | { 17 | public class Startup 18 | { 19 | public Startup(IConfiguration configuration) 20 | { 21 | Configuration = configuration; 22 | } 23 | 24 | public IConfiguration Configuration { get; } 25 | 26 | // This method gets called by the runtime. Use this method to add services to the container. 27 | public void ConfigureServices(IServiceCollection services) 28 | { 29 | services.AddControllers(); 30 | services.AddSingleton((services) => { 31 | var store = new CoreFlow.Activities.InstanceStores.FileInstanceStore(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CoreFlow/Instances")); 32 | return new RuntimeEngine().WithInstanceStore(store).AddExtension(new CoreFlow.Activities.WorkflowModelCatalog.FileWorkflowModelCatalog()); 33 | }); 34 | 35 | } 36 | 37 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 38 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 39 | { 40 | if (env.IsDevelopment()) 41 | { 42 | app.UseDeveloperExceptionPage(); 43 | } 44 | 45 | app.UseHttpsRedirection(); 46 | 47 | app.UseRouting(); 48 | 49 | app.UseAuthorization(); 50 | 51 | app.UseEndpoints(endpoints => 52 | { 53 | endpoints.MapControllers(); 54 | }); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/CoreFlow.Engine/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*", 10 | 11 | "Extensions": { 12 | "CoreFlow.Activites.WorkflowModelCatalog.FileWorkflowModelCatalog": { 13 | "Path": "c:\\" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/CoreFlow.Shared/CoreFlow.Shared.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | Debug;Release;Debug-no-compose 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/CoreFlow.Shared/IAddonRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | 6 | namespace CoreFlow.Shared 7 | { 8 | public interface IAddonRepository 9 | { 10 | void RegisterAddOn(System.IO.Stream stream); 11 | Assembly Resolve(String fullname); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/CoreFlow.Shared/IInstanceDirectory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities.Hosting; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace CoreFlow.Shared 7 | { 8 | public interface IInstanceDirectory 9 | { 10 | IEnumerable GetInstances(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/CoreFlow.Shared/IWorkflowModelCatalog.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using System; 3 | using System.Activities; 4 | using System.Collections.Generic; 5 | using System.Configuration; 6 | using System.Text; 7 | 8 | 9 | namespace CoreFlow.Shared 10 | { 11 | public interface IWorkflowModelCatalog 12 | { 13 | void Initialize(IConfiguration configuration); 14 | WorkflowIdentity RegisterModel(String name, Activity workflowModel); 15 | Activity GetModel(WorkflowIdentity workflowIdentity); 16 | Activity GetActiveModel(String name); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/CoreForm.Activities/CoreForm.Activities.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/CoreForm.Activities/CoreFormActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Activities; 3 | 4 | namespace CoreForm.Activities 5 | { 6 | public class CoreFormActivity : System.Activities.NativeActivity 7 | { 8 | protected override void Execute(NativeActivityContext context) 9 | { 10 | throw new NotImplementedException(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/CoreForm.Activities/CoreFormExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace CoreForm.Activities 6 | { 7 | public class CoreFormExtension 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Engine.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreFlow.Engine", "CoreFlow.Engine\CoreFlow.Engine.csproj", "{678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}" 7 | EndProject 8 | Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreFlow.Shared", "CoreFlow.Shared\CoreFlow.Shared.csproj", "{65801F26-99EC-4783-8797-201ACA82B00E}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreFlow.Activities", "CoreFlow.Activities\CoreFlow.Activities.csproj", "{D7A3DA85-815F-4FF5-869F-0E5C6E64C232}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreForm.Activities", "CoreForm.Activities\CoreForm.Activities.csproj", "{2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Debug-no-compose|Any CPU = Debug-no-compose|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Debug-no-compose|Any CPU.ActiveCfg = Debug-no-compose|Any CPU 26 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Debug-no-compose|Any CPU.Build.0 = Debug-no-compose|Any CPU 27 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {678925DE-9F6D-4C8D-A363-7D5EBAC7EB28}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}.Debug-no-compose|Any CPU.ActiveCfg = Debug-no-compose|Any CPU 32 | {5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {5B5D635C-F80F-4686-BC65-1FBBB2EF8CF2}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {65801F26-99EC-4783-8797-201ACA82B00E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {65801F26-99EC-4783-8797-201ACA82B00E}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {65801F26-99EC-4783-8797-201ACA82B00E}.Debug-no-compose|Any CPU.ActiveCfg = Debug-no-compose|Any CPU 37 | {65801F26-99EC-4783-8797-201ACA82B00E}.Debug-no-compose|Any CPU.Build.0 = Debug-no-compose|Any CPU 38 | {65801F26-99EC-4783-8797-201ACA82B00E}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {65801F26-99EC-4783-8797-201ACA82B00E}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Debug-no-compose|Any CPU.ActiveCfg = Debug-no-compose|Any CPU 43 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Debug-no-compose|Any CPU.Build.0 = Debug-no-compose|Any CPU 44 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {D7A3DA85-815F-4FF5-869F-0E5C6E64C232}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Debug-no-compose|Any CPU.ActiveCfg = Debug|Any CPU 49 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Debug-no-compose|Any CPU.Build.0 = Debug|Any CPU 50 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Release|Any CPU.ActiveCfg = Release|Any CPU 51 | {2A1BFC44-B727-499B-A4C0-3D9BB3DA12E7}.Release|Any CPU.Build.0 = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(SolutionProperties) = preSolution 54 | HideSolutionNode = FALSE 55 | EndGlobalSection 56 | GlobalSection(ExtensibilityGlobals) = postSolution 57 | SolutionGuid = {9A5BCA58-D0EF-4BF1-A274-B7A3F8A94FDB} 58 | EndGlobalSection 59 | EndGlobal 60 | -------------------------------------------------------------------------------- /src/System.Activitites/System.Activities.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/System.Activities.dll -------------------------------------------------------------------------------- /src/System.Activitites/System.Activities.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/System.Activities.pdb -------------------------------------------------------------------------------- /src/System.Activitites/ar/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/ar/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/cs/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/cs/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/da/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/da/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/de/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/de/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/el/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/el/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/es/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/es/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/fi/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/fi/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/fr/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/fr/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/he/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/he/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/hu/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/hu/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/it/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/it/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/ja/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/ja/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/ko/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/ko/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/nb/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/nb/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/nl/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/nl/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/pl/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/pl/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/pt-br/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/pt-br/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/pt-pt/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/pt-pt/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/ru/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/ru/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/sv/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/sv/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/tr/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/tr/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/zh-chs/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/zh-chs/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/System.Activitites/zh-cht/System.Activities.resources.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoreStuffs/CoreFlow/9f9f26701d1a048fa697530e9d053a20887c02d1/src/System.Activitites/zh-cht/System.Activities.resources.dll -------------------------------------------------------------------------------- /src/docker-compose.dcproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug-no-compose 6 | AnyCPU 7 | 8 | 9 | Debug 10 | AnyCPU 11 | 12 | 13 | Release 14 | AnyCPU 15 | 16 | 17 | 18 | 2.1 19 | Linux 20 | 5b5d635c-f80f-4686-bc65-1fbbb2ef8cf2 21 | LaunchBrowser 22 | {Scheme}://localhost:{ServicePort}/weatherforecast 23 | coreflow.engine 24 | 25 | 26 | 27 | docker-compose.yml 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/docker-compose.override.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | 3 | services: 4 | coreflow.engine: 5 | environment: 6 | - ASPNETCORE_ENVIRONMENT=Development 7 | - ASPNETCORE_URLS=https://+:443;http://+:80 8 | ports: 9 | - "80" 10 | - "443" 11 | volumes: 12 | - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro 13 | - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro -------------------------------------------------------------------------------- /src/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | 3 | services: 4 | coreflow.engine: 5 | image: ${DOCKER_REGISTRY-}coreflowengine 6 | build: 7 | context: . 8 | dockerfile: CoreFlow.Engine/Dockerfile 9 | --------------------------------------------------------------------------------