├── Assets ├── Logo.ai ├── Logo.png └── Logo.svg ├── Sample ├── Sample.Test │ ├── Assets │ │ ├── StoreLogo.png │ │ ├── SplashScreen.scale-200.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-200.png │ │ └── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── UnitTestApp.xaml │ ├── project.json │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── UnitTestApp.rd.xml │ ├── Package.appxmanifest │ ├── UnitTest.cs │ ├── UnitTestApp.xaml.cs │ └── Sample.Test.csproj ├── Sample.Consumer │ ├── Assets │ │ ├── StoreLogo.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── SplashScreen.scale-200.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-200.png │ │ └── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── App.xaml │ ├── project.json │ ├── DataTemplateSelector.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Default.rd.xml │ ├── MainPage.xaml.cs │ ├── Viewmodel.cs │ ├── Package.appxmanifest │ ├── MainPage.xaml │ ├── App.xaml.cs │ └── Sample.Consumer.csproj ├── Sample.Provider │ ├── Assets │ │ ├── StoreLogo.png │ │ ├── LockScreenLogo.scale-200.png │ │ ├── SplashScreen.scale-200.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Wide310x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-200.png │ │ └── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── App.xaml │ ├── project.json │ ├── MainPage.xaml │ ├── MainPage.xaml.cs │ ├── Properties │ │ ├── AssemblyInfo.cs │ │ └── Default.rd.xml │ ├── Package.appxmanifest │ ├── App.xaml.cs │ └── Sample.Provider.csproj ├── Sample.Component │ ├── project.json │ ├── AppendPluginOptions.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── AppendPlugin.cs │ ├── ReversePluginOptions.cs │ ├── ReversePluginIntern.cs │ └── Sample.Component.csproj └── Sample.Definition │ ├── project.json │ ├── Properties │ ├── AssemblyInfo.cs │ └── Sample.Definition.rd.xml │ ├── StringPluginsWithOptions.cs │ ├── Options.cs │ └── Sample.Definition.csproj ├── AppPlugin ├── Exceptions │ ├── PluginException.cs │ └── ConnectionFailure.cs ├── project.json ├── IPlugin.cs ├── AppPlugin.nuspec ├── Helper.cs ├── Properties │ ├── AssemblyInfo.cs │ └── AppExtensionService.rd.xml ├── GlobalSuppressions.cs ├── AbstractPlugin.cs ├── AbstractPluginWithOptins.cs ├── AbstractBasePlugin.cs ├── AppPlugin.csproj └── PluginList │ ├── PluginList.cs │ ├── PluginListWithOptions.cs │ └── AbstractPluginList.cs ├── License.md ├── AppPlugin.sln ├── .gitattributes ├── .gitignore └── README.md /Assets/Logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Assets/Logo.ai -------------------------------------------------------------------------------- /Assets/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Assets/Logo.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/StoreLogo.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /Sample/Sample.Test/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Test/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Consumer/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /Sample/Sample.Provider/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LokiMidgard/AppPlugin/HEAD/Sample/Sample.Provider/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /AppPlugin/Exceptions/PluginException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace AppPlugin.Exceptions 4 | { 5 | internal class PluginException : Exception 6 | { 7 | 8 | internal PluginException(string message) : base(message) 9 | { 10 | } 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /Sample/Sample.Consumer/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/Sample.Provider/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/Sample.Test/UnitTestApp.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Sample/Sample.Component/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /Sample/Sample.Consumer/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /Sample/Sample.Definition/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /Sample/Sample.Provider/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2" 4 | }, 5 | "frameworks": { 6 | "uap10.0": {} 7 | }, 8 | "runtimes": { 9 | "win10-arm": {}, 10 | "win10-arm-aot": {}, 11 | "win10-x86": {}, 12 | "win10-x86-aot": {}, 13 | "win10-x64": {}, 14 | "win10-x64-aot": {} 15 | } 16 | } -------------------------------------------------------------------------------- /AppPlugin/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", 4 | "Nito.AsyncEx": "3.0.1" 5 | }, 6 | "frameworks": { 7 | "uap10.0": {} 8 | }, 9 | "runtimes": { 10 | "win10-arm": {}, 11 | "win10-arm-aot": {}, 12 | "win10-x86": {}, 13 | "win10-x86-aot": {}, 14 | "win10-x64": {}, 15 | "win10-x64-aot": {} 16 | } 17 | } -------------------------------------------------------------------------------- /Sample/Sample.Test/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", 4 | "MSTest.TestAdapter": "1.1.4-preview", 5 | "MSTest.TestFramework": "1.0.5-preview", 6 | "Nito.AsyncEx": "3.0.1" 7 | }, 8 | "frameworks": { 9 | "uap10.0": {} 10 | }, 11 | "runtimes": { 12 | "win10-arm": {}, 13 | "win10-arm-aot": {}, 14 | "win10-x86": {}, 15 | "win10-x86-aot": {}, 16 | "win10-x64": {}, 17 | "win10-x64-aot": {} 18 | } 19 | } -------------------------------------------------------------------------------- /Sample/Sample.Provider/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /AppPlugin/IPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace AppPlugin 9 | { 10 | public interface IPlugin 11 | { 12 | Task ExecuteAsync(TIn input, IProgress progress = null, CancellationToken cancelTokem = default(CancellationToken)); 13 | } 14 | 15 | public interface IPlugin 16 | { 17 | Task ExecuteAsync(TIn input, TOption options, IProgress progress = null, CancellationToken cancelTokem = default(CancellationToken)); 18 | 19 | Task PrototypeOptions { get; } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /AppPlugin/AppPlugin.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/LokiMidgard/AppExtensionService/blob/master/License.md 10 | https://github.com/LokiMidgard/AppExtensionService 11 | https://github.com/LokiMidgard/AppExtensionService/blob/master/Assets/Logo.png 12 | false 13 | $description$ 14 | 15 | - Fixed Bugs 16 | - Added Sample 17 | - [BEAKING CHANGE] Method Signatures Changed 18 | 19 | Copyright 2016 20 | UWP AppService AppExtension Plugin 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample/Sample.Provider/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | 16 | // Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x407 dokumentiert. 17 | 18 | namespace Sample.Provider 19 | { 20 | /// 21 | /// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann. 22 | /// 23 | public sealed partial class MainPage : Page 24 | { 25 | public MainPage() 26 | { 27 | this.InitializeComponent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Sample/Sample.Component/AppendPluginOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Sample.Definition; 3 | 4 | namespace Sample.Component 5 | { 6 | internal class AppendPluginOptions : Options 7 | { 8 | internal static readonly Guid ID = new Guid("{ED1E7DD5-7059-461D-9FEE-A5F0F6C7CE5A}"); 9 | private readonly AbstractOption[] abstractOption; 10 | 11 | public AppendPluginOptions() 12 | { 13 | this.abstractOption = new AbstractOption[] 14 | { 15 | new StringOption("To Append", "Defines the String that will be Append.") { Value = "[Please Set a Value]" } 16 | }; 17 | } 18 | 19 | 20 | public AppendPluginOptions(Options o) 21 | { 22 | if (o.OptionsIdentifier != ID) 23 | throw new ArgumentException(); 24 | this.abstractOption = o.Settings; 25 | } 26 | 27 | public StringOption Appending => this[0] as StringOption; 28 | 29 | public override Guid OptionsIdentifier => ID; 30 | 31 | protected override AbstractOption[] GetSettings() => this.abstractOption; 32 | } 33 | } -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Patrick Kranz 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. -------------------------------------------------------------------------------- /Sample/Sample.Consumer/DataTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Windows.UI.Xaml.Data; 9 | 10 | namespace Sample.Consumer 11 | { 12 | class OptionsSelector : DataTemplateSelector 13 | { 14 | public DataTemplate StringOptionTemplate { get; set; } 15 | public DataTemplate IntOptionTemplate { get; set; } 16 | 17 | protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 18 | { 19 | return SelectTemplate(item); 20 | } 21 | 22 | protected override DataTemplate SelectTemplateCore(object item) 23 | { 24 | switch (item) 25 | { 26 | case Definition.IntOption io: 27 | return this.IntOptionTemplate; 28 | case Definition.StringOption so: 29 | return this.StringOptionTemplate; 30 | default: 31 | return base.SelectTemplateCore(item); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Sample.Consumer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Sample.Consumer")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Sample/Sample.Provider/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Sample.Provider")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Sample.Provider")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Sample/Sample.Component/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Sample.Component")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Sample.Component")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Sample/Sample.Definition/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Sample.Definition")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Sample.Definition")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Sample/Sample.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Sample.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Sample.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: AssemblyMetadata("TargetPlatform","UAP")] 17 | 18 | // Version information for an assembly consists of the following four values: 19 | // 20 | // Major Version 21 | // Minor Version 22 | // Build Number 23 | // Revision 24 | // 25 | // You can specify all the values or you can default the Build and Revision Numbers 26 | // by using the '*' as shown below: 27 | // [assembly: AssemblyVersion("1.0.*")] 28 | [assembly: AssemblyVersion("1.0.0.0")] 29 | [assembly: AssemblyFileVersion("1.0.0.0")] 30 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /Sample/Sample.Component/AppendPlugin.cs: -------------------------------------------------------------------------------- 1 | using Sample.Definition; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Windows.ApplicationModel.Background; 9 | 10 | namespace Sample.Component 11 | { 12 | public sealed class AppendPlugin : IBackgroundTask 13 | { 14 | private IBackgroundTask internalTask = new AppendIntern(); 15 | public void Run(IBackgroundTaskInstance taskInstance) 16 | => this.internalTask.Run(taskInstance); 17 | } 18 | 19 | internal class AppendIntern : StringPluginsWithOptions 20 | { 21 | 22 | protected override Task ExecuteAsync(string input, Options options, IProgress progress, CancellationToken cancelToken) 23 | { 24 | var revereseOptions = new AppendPluginOptions(options); 25 | 26 | return Task.FromResult(input + revereseOptions.Appending.Value ?? ""); 27 | } 28 | 29 | 30 | protected override Task GetOptions() 31 | => Task.FromResult(new AppendPluginOptions()); 32 | 33 | protected override Guid GetOptionsGuid() => AppendPluginOptions.ID; 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sample/Sample.Component/ReversePluginOptions.cs: -------------------------------------------------------------------------------- 1 | using Sample.Definition; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Sample.Component 10 | { 11 | 12 | class ReversePluginOptions : Options 13 | { 14 | public static readonly Guid ID = new Guid("AB577183-9A64-47E0-B4B6-E8B5D309F537"); 15 | 16 | private readonly AbstractOption[] abstractOption; 17 | 18 | public ReversePluginOptions() 19 | { 20 | this.abstractOption = new AbstractOption[] 21 | { 22 | new IntOption("Delay", "Sets the delay for each reverse operation in ms.", 0, 1000) { Value = 200 } 23 | }; 24 | } 25 | 26 | 27 | public ReversePluginOptions(Options o) 28 | { 29 | if (o.OptionsIdentifier != ID) 30 | throw new ArgumentException(); 31 | this.abstractOption = o.Settings; 32 | } 33 | 34 | public IntOption Delay => this[0] as IntOption; 35 | 36 | public override Guid OptionsIdentifier => ID; 37 | 38 | protected override AbstractOption[] GetSettings() => this.abstractOption; 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AppPlugin/Helper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.Serialization; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Xml; 9 | 10 | namespace AppPlugin 11 | { 12 | internal static class Helper 13 | { 14 | internal static string Serilize(T output) 15 | { 16 | string outputString; 17 | var serelizerOut = new DataContractSerializer(typeof(T)); 18 | using (var stringWriter = new StringWriter()) 19 | { 20 | using (var xmlWriter = XmlWriter.Create(stringWriter)) 21 | serelizerOut.WriteObject(xmlWriter, output); 22 | outputString = stringWriter.ToString(); 23 | } 24 | 25 | return outputString; 26 | } 27 | 28 | internal static T DeSerilize(string inputString) 29 | { 30 | T input; 31 | var serelizerIn = new DataContractSerializer(typeof(T)); 32 | using (var stringReader = new StringReader(inputString)) 33 | using (var xmlReader = XmlReader.Create(stringReader)) 34 | input = (T)serelizerIn.ReadObject(xmlReader); 35 | return input; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /AppPlugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("AppPlugin")] 9 | [assembly: AssemblyDescription("This project combines UWP AppServices with AppExtensions and DataContracts in order to realize a more Code orientated way to write extensions.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Patrick Kranz")] 12 | [assembly: AssemblyProduct("AppPlugin")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("0.5.*")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] 30 | -------------------------------------------------------------------------------- /Sample/Sample.Test/Properties/UnitTestApp.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Sample/Sample.Definition/StringPluginsWithOptions.cs: -------------------------------------------------------------------------------- 1 | using AppPlugin; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Threading; 8 | 9 | namespace Sample.Definition 10 | { 11 | public abstract class StringPluginsWithOptions : AbstractPlugin 12 | { 13 | 14 | public const String PLUGIN_NAME = "Sample.StringPluginsWithOptions"; 15 | 16 | protected sealed override Task ExecuteAsync(string input, TransfareOptions options, IProgress progress, CancellationToken cancelToken) 17 | { 18 | if (options.OptionsIdentifyer != GetOptionsGuid()) 19 | throw new ArgumentException("Option Not generated by this Plugin", nameof(options)); 20 | return ExecuteAsync(input, options.Options, progress, cancelToken); 21 | } 22 | 23 | protected sealed override async Task GetDefaultOptionsAsync() 24 | => new TransfareOptions() { Options = await GetOptions() }; 25 | 26 | protected abstract Task ExecuteAsync(string input, Options options, IProgress progress, CancellationToken cancelToken); 27 | 28 | protected abstract Task GetOptions(); 29 | protected abstract Guid GetOptionsGuid(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Sample/Sample.Provider/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Sample/Sample.Component/ReversePluginIntern.cs: -------------------------------------------------------------------------------- 1 | using Sample.Definition; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Threading; 8 | using Windows.ApplicationModel.Background; 9 | 10 | namespace Sample.Component 11 | { 12 | 13 | public sealed class ReveresPlugin : IBackgroundTask 14 | { 15 | private IBackgroundTask internalTask = new ReversePluginIntern(); 16 | public void Run(IBackgroundTaskInstance taskInstance) 17 | => this.internalTask.Run(taskInstance); 18 | } 19 | 20 | internal class ReversePluginIntern : StringPluginsWithOptions 21 | { 22 | 23 | protected override async Task ExecuteAsync(string input, Options options, IProgress progress, CancellationToken cancelToken) 24 | { 25 | var revereseOptions = new ReversePluginOptions(options); 26 | var b = new StringBuilder(); 27 | for (int i = input.Length - 1; i >= 0; i--) 28 | { 29 | b.Append(input[i]); 30 | if (cancelToken.IsCancellationRequested) 31 | break; 32 | progress.Report(b.Length / (double)input.Length); 33 | await Task.Delay(revereseOptions.Delay.Value); 34 | } 35 | return b.ToString(); 36 | } 37 | 38 | 39 | protected override Task GetOptions() 40 | => Task.FromResult(new ReversePluginOptions()); 41 | 42 | protected override Guid GetOptionsGuid() => ReversePluginOptions.ID; 43 | 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /AppPlugin/Properties/AppExtensionService.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Sample/Sample.Definition/Properties/Sample.Definition.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using Plugin = AppPlugin.PluginList.PluginList.PluginProvider; 16 | 17 | // Die Elementvorlage "Leere Seite" wird unter https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x407 dokumentiert. 18 | 19 | namespace Sample.Consumer 20 | { 21 | /// 22 | /// Eine leere Seite, die eigenständig verwendet oder zu der innerhalb eines Rahmens navigiert werden kann. 23 | /// 24 | public sealed partial class MainPage : Page 25 | { 26 | public MainPage() 27 | { 28 | this.InitializeComponent(); 29 | } 30 | 31 | private async void Button_Click(object sender, RoutedEventArgs e) 32 | { 33 | this.Progress.IsActive = true; 34 | this.List.IsEnabled = false; 35 | try 36 | { 37 | 38 | var b = sender as Button; 39 | var p = b.DataContext as Plugin; 40 | var o = await p.PrototypeOptions; 41 | var erg = await p.ExecuteAsync(this.Input.Text ?? "", o); 42 | this.Output.Text = erg; 43 | 44 | } 45 | finally 46 | { 47 | this.List.IsEnabled = true; 48 | 49 | this.Progress.IsActive = false; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Viewmodel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Collections.Specialized; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Windows.UI.Xaml; 9 | using Plugin = AppPlugin.PluginList.PluginList.PluginProvider; 10 | 11 | namespace Sample.Consumer 12 | { 13 | class Viewmodel : DependencyObject 14 | { 15 | 16 | public ObservableCollection Plugins { get; } 17 | = new ObservableCollection(); 18 | 19 | public Viewmodel() 20 | { 21 | #pragma warning disable CS4014 // Da dieser Aufruf nicht abgewartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen ist 22 | InitAsync(); 23 | #pragma warning restore CS4014 // Da dieser Aufruf nicht abgewartet wird, wird die Ausführung der aktuellen Methode fortgesetzt, bevor der Aufruf abgeschlossen ist 24 | } 25 | 26 | private async Task InitAsync() 27 | { 28 | await Task.Delay(5000); 29 | var list = await Definition.StringPluginsWithOptions.ListAsync(Definition.StringPluginsWithOptions.PLUGIN_NAME); 30 | 31 | foreach (var item in list.Plugins) 32 | this.Plugins.Add(item); 33 | 34 | (list.Plugins as INotifyCollectionChanged).CollectionChanged += async (sender, e) => 35 | { 36 | await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => 37 | { 38 | if (e.NewItems != null) 39 | foreach (var item in e.NewItems.OfType()) 40 | this.Plugins.Add(item); 41 | if (e.OldItems != null) 42 | foreach (var item in e.OldItems.OfType()) 43 | this.Plugins.Remove(item); 44 | }); 45 | }; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | Sample.Consumer 19 | patri 20 | Assets\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Sample.StringPluginsWithOptions 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /Sample/Sample.Test/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | Sample.Test 17 | patri 18 | Assets\StoreLogo.png 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Sample.StringPluginsWithOptions 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /AppPlugin.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppPlugin", "AppPlugin\AppPlugin.csproj", "{D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RepoFiles", "RepoFiles", "{5F8A45D1-4CA5-433A-8CF5-3E9D17CB21F1}" 9 | ProjectSection(SolutionItems) = preProject 10 | License.md = License.md 11 | README.md = README.md 12 | EndProjectSection 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|ARM = Debug|ARM 18 | Debug|x64 = Debug|x64 19 | Debug|x86 = Debug|x86 20 | Release|Any CPU = Release|Any CPU 21 | Release|ARM = Release|ARM 22 | Release|x64 = Release|x64 23 | Release|x86 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|ARM.ActiveCfg = Debug|ARM 29 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|ARM.Build.0 = Debug|ARM 30 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|x64.ActiveCfg = Debug|x64 31 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|x64.Build.0 = Debug|x64 32 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|x86.ActiveCfg = Debug|x86 33 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Debug|x86.Build.0 = Debug|x86 34 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|ARM.ActiveCfg = Release|ARM 37 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|ARM.Build.0 = Release|ARM 38 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|x64.ActiveCfg = Release|x64 39 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|x64.Build.0 = Release|x64 40 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|x86.ActiveCfg = Release|x86 41 | {D35E5F0F-601C-43BF-82D6-89F51AC6AA8B}.Release|x86.Build.0 = Release|x86 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /Sample/Sample.Test/UnitTest.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System.Linq; 5 | using Nito.AsyncEx; 6 | using System.Threading.Tasks; 7 | using Sample.Definition; 8 | 9 | namespace Sample.Test 10 | { 11 | [TestClass] 12 | public class UnitTest1 13 | { 14 | [TestMethod] 15 | public void TestReversePlugin() 16 | { 17 | AsyncContext.Run(async () => 18 | { 19 | var list = await Definition.StringPluginsWithOptions.ListAsync(Definition.StringPluginsWithOptions.PLUGIN_NAME); 20 | // await Task.Delay(10000); 21 | var reversePlugin = list.Plugins.SingleOrDefault(x => x.Extension.DisplayName == "String Reverser"); 22 | Assert.IsNotNull(reversePlugin, "No Plugin Found Be shure to deploy the Project Sample.Provider"); 23 | 24 | var options = await reversePlugin.PrototypeOptions; 25 | 26 | Assert.IsNotNull(options); 27 | 28 | const string toReverse = "Test"; 29 | var result = await reversePlugin.ExecuteAsync(toReverse, options); 30 | Assert.AreEqual(new String(toReverse.Reverse().ToArray()), result); 31 | 32 | }); 33 | } 34 | 35 | [TestMethod] 36 | public void TestAppendPlugin() 37 | { 38 | AsyncContext.Run(async () => 39 | { 40 | var list = await Definition.StringPluginsWithOptions.ListAsync(Definition.StringPluginsWithOptions.PLUGIN_NAME); 41 | //await Task.Delay(10000); 42 | var reversePlugin = list.Plugins.SingleOrDefault(x => x.Extension.DisplayName == "String Appender"); 43 | Assert.IsNotNull(reversePlugin, "No Plugin Found Be shure to deploy the Project Sample.Provider"); 44 | 45 | var options = await reversePlugin.PrototypeOptions; 46 | 47 | Assert.IsNotNull(options); 48 | Assert.AreEqual(1, options.Count); 49 | Assert.IsInstanceOfType(options[0], typeof(StringOption)); 50 | 51 | var strOptions = options[0] as StringOption; 52 | const string toAppend = "Appending"; 53 | strOptions.Value = toAppend; 54 | 55 | const string input = "Test"; 56 | var result = await reversePlugin.ExecuteAsync(input, options); 57 | Assert.AreEqual(input + toAppend, result); 58 | 59 | }); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Assets/Logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 21 | 23 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 37 | 39 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /Sample/Sample.Provider/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | Sample.Provider 11 | patri 12 | Assets\StoreLogo.png 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | ReverseService 42 | 43 | 44 | 45 | 46 | 51 | 52 | AppendService 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /AppPlugin/Exceptions/ConnectionFailure.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.ApplicationModel.AppService; 7 | 8 | namespace AppPlugin.Exceptions 9 | { 10 | 11 | public class ConnectionFailureException : Exception 12 | { 13 | private AppServiceConnectionStatus status; 14 | private AppServiceConnection connection; 15 | 16 | public AppServiceResponseStatus Status { get; } 17 | 18 | internal ConnectionFailureException(AppServiceResponseStatus status) : base(GenerateMessage(status)) 19 | { 20 | this.Status = status; 21 | } 22 | 23 | internal ConnectionFailureException(AppServiceConnectionStatus status, AppServiceConnection connection) : base(GenerateMessage(status, connection)) 24 | { 25 | this.status = status; 26 | this.connection = connection; 27 | } 28 | 29 | private static string GenerateMessage(AppServiceResponseStatus status) 30 | { 31 | switch (status) 32 | { 33 | case AppServiceResponseStatus.Success: 34 | throw new ArgumentException("Success sollte keine Exception auslösen.", nameof(status)); 35 | case AppServiceResponseStatus.Failure: 36 | case AppServiceResponseStatus.ResourceLimitsExceeded: 37 | case AppServiceResponseStatus.Unknown: 38 | case AppServiceResponseStatus.RemoteSystemUnavailable: 39 | case AppServiceResponseStatus.MessageSizeTooLarge: 40 | return ""; 41 | default: 42 | return "Unknown failure"; 43 | } 44 | 45 | } 46 | 47 | private static string GenerateMessage(AppServiceConnectionStatus status, AppServiceConnection connection) 48 | { 49 | switch (status) 50 | { 51 | case AppServiceConnectionStatus.Success: 52 | throw new ArgumentException("Success sollte keine Exception auslösen.", nameof(status)); 53 | case AppServiceConnectionStatus.AppNotInstalled: 54 | return "The app AppServicesProvider is not installed. Deploy AppServicesProvider to this device and try again."; 55 | case AppServiceConnectionStatus.AppUnavailable: 56 | return "The app AppServicesProvider is not available. This could be because it is currently being updated or was installed to a removable device that is no longer available."; 57 | case AppServiceConnectionStatus.AppServiceUnavailable: 58 | return string.Format("The app AppServicesProvider is installed but it does not provide the app service {0}.", connection.AppServiceName); 59 | case AppServiceConnectionStatus.Unknown: 60 | return "An unkown error occurred while we were trying to open an AppServiceConnection."; 61 | case AppServiceConnectionStatus.RemoteSystemUnavailable: 62 | return "The remote system is unavailable."; 63 | case AppServiceConnectionStatus.RemoteSystemNotSupportedByApp: 64 | return "The Remote System is not supported by the app."; 65 | case AppServiceConnectionStatus.NotAuthorized: 66 | return "You are not authorized."; 67 | default: 68 | return "Unknown failure"; 69 | } 70 | 71 | 72 | 73 | 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /AppPlugin/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | 2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.Catalog_PackageUpdating(Windows.ApplicationModel.AppExtensions.AppExtensionCatalog,Windows.ApplicationModel.AppExtensions.AppExtensionPackageUpdatingEventArgs)")] 8 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.Catalog_PackageUpdated(Windows.ApplicationModel.AppExtensions.AppExtensionCatalog,Windows.ApplicationModel.AppExtensions.AppExtensionPackageUpdatedEventArgs)")] 9 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.Catalog_PackageInstalled(Windows.ApplicationModel.AppExtensions.AppExtensionCatalog,Windows.ApplicationModel.AppExtensions.AppExtensionPackageInstalledEventArgs)")] 10 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.Catalog_PackageUninstalling(Windows.ApplicationModel.AppExtensions.AppExtensionCatalog,Windows.ApplicationModel.AppExtensions.AppExtensionPackageUninstallingEventArgs)")] 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.Catalog_PackageStatusChanged(Windows.ApplicationModel.AppExtensions.AppExtensionCatalog,Windows.ApplicationModel.AppExtensions.AppExtensionPackageStatusChangedEventArgs)")] 12 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.PluginConnection.Canceld")] 13 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.AbstractPluginList`2.PluginConnection.Connection_RequestReceived(Windows.ApplicationModel.AppService.AppServiceConnection,Windows.ApplicationModel.AppService.AppServiceRequestReceivedEventArgs)")] 14 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.PluginList`3.PluginConnection.Canceld")] 15 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.PluginList`3.PluginConnection.Connection_RequestReceived(Windows.ApplicationModel.AppService.AppServiceConnection,Windows.ApplicationModel.AppService.AppServiceRequestReceivedEventArgs)")] 16 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.PluginList`4.PluginConnection.Canceld")] 17 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Stil", "IDE1006:Benennungsstile", Justification = "", Scope = "member", Target = "~M:AppPlugin.PluginList.PluginList`4.PluginConnection.Connection_RequestReceived(Windows.ApplicationModel.AppService.AppServiceConnection,Windows.ApplicationModel.AppService.AppServiceRequestReceivedEventArgs)")] 18 | 19 | -------------------------------------------------------------------------------- /AppPlugin/AbstractPlugin.cs: -------------------------------------------------------------------------------- 1 | using AppPlugin.PluginList; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Runtime.Serialization; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | using System.Xml; 11 | using Windows.ApplicationModel.AppService; 12 | using Windows.ApplicationModel.Background; 13 | using Windows.Foundation.Collections; 14 | 15 | namespace AppPlugin 16 | { 17 | /// 18 | /// Abstract class that can be implemented to define a simple Plugin that provides one Function. 19 | /// 20 | /// The Type that will be passed to the funtion. (Must have a valid ) 21 | /// The return type of the function. (Must have a valid ) 22 | /// The type that will be used to report progress. (Must have a valid ) 23 | public abstract class AbstractPlugin : AbstractBasePlugin 24 | { 25 | /// 26 | /// Instanziate the Plugin. 27 | /// 28 | /// 29 | /// Normaly an AppService uses its own process without UI. It also does not provide a SyncronisationContext. This results that async/await calls will run in the ThreadPool. This includes the Progress report. If the Plugin spans many Tasks, progress will be reported with higher latency. 30 | /// 31 | /// Discrips if the code should be called using a SyncronisationContext. 32 | public AbstractPlugin(bool useSyncronisationContext = true) : base(useSyncronisationContext) 33 | { 34 | 35 | } 36 | 37 | /// 38 | /// Returns an Object that Lists the Availaible Plugins. 39 | /// 40 | /// 41 | /// The length must be less or equal to 39, because of a limitation of the appmanifest. 42 | /// 43 | /// 44 | /// the length of is 40 or greater. 45 | /// 46 | /// The Plugin name defined in the appmanifest. 47 | /// The 48 | public static async Task> ListAsync(string pluginName) 49 | { 50 | var pluginList = new PluginList(pluginName); 51 | await pluginList.InitAsync(); 52 | return pluginList; 53 | } 54 | 55 | /// 56 | /// Provides the Funktionality of this Plugin. 57 | /// 58 | /// The Input Parameter. 59 | /// The Progress that will report data to the Client. 60 | /// The cancel token. 61 | /// The result of the execution. 62 | protected abstract Task Execute(TIn input, IProgress progress, CancellationToken cancelToken); 63 | 64 | 65 | internal override async Task PerformStartAsync(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args, Guid? id, CancellationTokenSource cancellationTokenSource) 66 | { 67 | var inputString = args.Request.Message[START_KEY] as String; 68 | 69 | var input = Helper.DeSerilize(inputString); 70 | 71 | var progress = new Progress(async r => 72 | { 73 | var data = Helper.Serilize(r); 74 | var dataSet = new ValueSet(); 75 | dataSet.Add(PROGRESS_KEY, data); 76 | dataSet.Add(ID_KEY, id); 77 | await sender.SendMessageAsync(dataSet); 78 | }); 79 | 80 | var output = await Execute(input, progress, cancellationTokenSource.Token); 81 | return output; 82 | } 83 | 84 | 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Sample/Sample.Consumer/MainPage.xaml: -------------------------------------------------------------------------------- 1 | 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 |