From 47619ee24377939c2368158d194ca67de4302120 Mon Sep 17 00:00:00 2001 From: Morten Holt Date: Fri, 22 Dec 2023 14:08:54 +0100 Subject: [PATCH 1/4] Add functionality to instantiate a new XrmMockup instance based on an existing one. This allows us to run multiple instances in parallel, withou having to fully load XrmMockup each time, significantly speeding up the initialization time and reducing file IO. --- RELEASE_NOTES.md | 4 ++ .../MetadataGenerator11/AssemblyInfo.fs | 8 ++-- .../MetadataGenerator13/AssemblyInfo.fs | 8 ++-- .../MetadataGenerator15/AssemblyInfo.fs | 8 ++-- .../MetadataGenerator16/AssemblyInfo.fs | 8 ++-- .../MetadataGenerator365/AssemblyInfo.fs | 8 ++-- src/XrmMockup2011/AssemblyInfo.fs | 8 ++-- src/XrmMockup2011/XrmMockup.cs | 16 +++++-- src/XrmMockup2013/AssemblyInfo.fs | 8 ++-- src/XrmMockup2013/XrmMockup.cs | 16 +++++-- src/XrmMockup2015/AssemblyInfo.fs | 8 ++-- src/XrmMockup2015/XrmMockup.cs | 16 +++++-- src/XrmMockup2016/AssemblyInfo.fs | 8 ++-- src/XrmMockup2016/XrmMockup.cs | 20 ++++++-- src/XrmMockup365/AssemblyInfo.fs | 8 ++-- src/XrmMockup365/XrmMockup.cs | 17 +++++-- .../RetrieveMultipleRequestHandler.cs | 2 - src/XrmMockupShared/XrmMockupBase.cs | 46 ++++++++++++++----- tests/SharedTests/TestZipSnapshot.cs | 11 ++--- 19 files changed, 150 insertions(+), 78 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2bce8dca..10b83327 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,7 @@ +### 1.12.3 - 22 December 2023 +* Add initializer based on an existing instance, letting us copy an already initialized XrmMockup instance (@mkholt) +* Add timers during initialization (@mkholt) + ### 1.12.2 - 24 August 2023 * Add flag to mitigate duplicate security role names (@mkholt) diff --git a/src/MetadataGen/MetadataGenerator11/AssemblyInfo.fs b/src/MetadataGen/MetadataGenerator11/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/MetadataGen/MetadataGenerator11/AssemblyInfo.fs +++ b/src/MetadataGen/MetadataGenerator11/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/MetadataGen/MetadataGenerator13/AssemblyInfo.fs b/src/MetadataGen/MetadataGenerator13/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/MetadataGen/MetadataGenerator13/AssemblyInfo.fs +++ b/src/MetadataGen/MetadataGenerator13/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/MetadataGen/MetadataGenerator15/AssemblyInfo.fs b/src/MetadataGen/MetadataGenerator15/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/MetadataGen/MetadataGenerator15/AssemblyInfo.fs +++ b/src/MetadataGen/MetadataGenerator15/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/MetadataGen/MetadataGenerator16/AssemblyInfo.fs b/src/MetadataGen/MetadataGenerator16/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/MetadataGen/MetadataGenerator16/AssemblyInfo.fs +++ b/src/MetadataGen/MetadataGenerator16/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/MetadataGen/MetadataGenerator365/AssemblyInfo.fs b/src/MetadataGen/MetadataGenerator365/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/MetadataGen/MetadataGenerator365/AssemblyInfo.fs +++ b/src/MetadataGen/MetadataGenerator365/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup2011/AssemblyInfo.fs b/src/XrmMockup2011/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/XrmMockup2011/AssemblyInfo.fs +++ b/src/XrmMockup2011/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup2011/XrmMockup.cs b/src/XrmMockup2011/XrmMockup.cs index 28cb3c4a..ea5e5de0 100644 --- a/src/XrmMockup2011/XrmMockup.cs +++ b/src/XrmMockup2011/XrmMockup.cs @@ -25,10 +25,11 @@ public class XrmMockup2011 : XrmMockupBase { private static Dictionary instances = new Dictionary(); - private XrmMockup2011(XrmMockupSettings Settings) - : base(Settings) { + private XrmMockup2011(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : + base(Settings, metadata, workflows, securityRoles) + { } - + /// /// Gets an instance of XrmMockup2011 /// @@ -42,6 +43,15 @@ public static XrmMockup2011 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2011 using the same metadata as the provided + /// + /// + public static XrmMockup2011 GetInstance(XrmMockup2011 xrmMockup) + { + return new XrmMockup2011(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } } } diff --git a/src/XrmMockup2013/AssemblyInfo.fs b/src/XrmMockup2013/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/XrmMockup2013/AssemblyInfo.fs +++ b/src/XrmMockup2013/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup2013/XrmMockup.cs b/src/XrmMockup2013/XrmMockup.cs index 1ff397d7..056655b5 100644 --- a/src/XrmMockup2013/XrmMockup.cs +++ b/src/XrmMockup2013/XrmMockup.cs @@ -19,10 +19,11 @@ public class XrmMockup2013 : XrmMockupBase { private static Dictionary instances = new Dictionary(); - private XrmMockup2013(XrmMockupSettings Settings) : - base(Settings) { + private XrmMockup2013(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : + base(Settings, metadata, workflows, securityRoles) + { } - + /// /// Gets an instance of XrmMockup2013 /// @@ -36,5 +37,14 @@ public static XrmMockup2013 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2013 using the same metadata as the provided + /// + /// + public static XrmMockup2013 GetInstance(XrmMockup2013 xrmMockup) + { + return new XrmMockup2013(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } } } diff --git a/src/XrmMockup2015/AssemblyInfo.fs b/src/XrmMockup2015/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/XrmMockup2015/AssemblyInfo.fs +++ b/src/XrmMockup2015/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup2015/XrmMockup.cs b/src/XrmMockup2015/XrmMockup.cs index 331bf04d..cac7b5c4 100644 --- a/src/XrmMockup2015/XrmMockup.cs +++ b/src/XrmMockup2015/XrmMockup.cs @@ -19,10 +19,11 @@ public class XrmMockup2015 : XrmMockupBase { private static Dictionary instances = new Dictionary(); - private XrmMockup2015(XrmMockupSettings Settings) : - base(Settings) { + private XrmMockup2015(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : + base(Settings, metadata, workflows, securityRoles) + { } - + /// /// Gets an instance of XrmMockup2015 /// @@ -36,5 +37,14 @@ public static XrmMockup2015 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + /// + /// Gets an instance of XrmMockup2015 using the same metadata as the provided + /// + /// + public static XrmMockup2015 GetInstance(XrmMockup2015 xrmMockup) + { + return new XrmMockup2015(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } + } } diff --git a/src/XrmMockup2016/AssemblyInfo.fs b/src/XrmMockup2016/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/XrmMockup2016/AssemblyInfo.fs +++ b/src/XrmMockup2016/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup2016/XrmMockup.cs b/src/XrmMockup2016/XrmMockup.cs index 69358d8d..20672d24 100644 --- a/src/XrmMockup2016/XrmMockup.cs +++ b/src/XrmMockup2016/XrmMockup.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using Microsoft.Xrm.Sdk; +using System.Collections.Generic; using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("XrmMockup16Test")] @@ -12,10 +13,12 @@ public class XrmMockup2016 : XrmMockupBase { private static Dictionary instances = new Dictionary(); - private XrmMockup2016(XrmMockupSettings Settings) : - base(Settings) {} + private XrmMockup2016(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : + base(Settings, metadata, workflows, securityRoles) + { + } + - /// /// Gets an instance of XrmMockup2016 /// @@ -28,5 +31,14 @@ public static XrmMockup2016 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2016 using the same metadata as the provided + /// + /// + public static XrmMockup2016 GetInstance(XrmMockup2016 xrmMockup) + { + return new XrmMockup2016(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } } } diff --git a/src/XrmMockup365/AssemblyInfo.fs b/src/XrmMockup365/AssemblyInfo.fs index d82a8d8a..55c6b6b9 100644 --- a/src/XrmMockup365/AssemblyInfo.fs +++ b/src/XrmMockup365/AssemblyInfo.fs @@ -7,8 +7,8 @@ using System.Reflection; [assembly: AssemblyDescription("A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic.")] [assembly: AssemblyCompany("Delegate A/S")] [assembly: AssemblyCopyright("Copyright (c) Delegate A/S 2017")] -[assembly: AssemblyVersion("1.12.2")] -[assembly: AssemblyFileVersion("1.12.2")] +[assembly: AssemblyVersion("1.12.3")] +[assembly: AssemblyFileVersion("1.12.3")] namespace System { internal static class AssemblyVersionInformation { internal const System.String AssemblyTitle = "XrmMockup"; @@ -16,7 +16,7 @@ namespace System { internal const System.String AssemblyDescription = "A simulation engine that can mock a specific MS CRM instance. Useful for testing and debugging business logic."; internal const System.String AssemblyCompany = "Delegate A/S"; internal const System.String AssemblyCopyright = "Copyright (c) Delegate A/S 2017"; - internal const System.String AssemblyVersion = "1.12.2"; - internal const System.String AssemblyFileVersion = "1.12.2"; + internal const System.String AssemblyVersion = "1.12.3"; + internal const System.String AssemblyFileVersion = "1.12.3"; } } diff --git a/src/XrmMockup365/XrmMockup.cs b/src/XrmMockup365/XrmMockup.cs index 790e5701..02c4efe4 100644 --- a/src/XrmMockup365/XrmMockup.cs +++ b/src/XrmMockup365/XrmMockup.cs @@ -16,11 +16,11 @@ namespace DG.Tools.XrmMockup { /// public class XrmMockup365 : XrmMockupBase { - private static Dictionary instances = new Dictionary(); + private static readonly Dictionary instances = new Dictionary(); - - private XrmMockup365(XrmMockupSettings Settings) : - base(Settings) { + private XrmMockup365(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : + base(Settings, metadata, workflows, securityRoles) + { } /// @@ -36,5 +36,14 @@ public static XrmMockup365 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup365 using the same metadata as the provided + /// + /// + public static XrmMockup365 GetInstance(XrmMockup365 xrmMockup) + { + return new XrmMockup365(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } } } diff --git a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs index 8348f65b..7d927525 100644 --- a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs +++ b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs @@ -40,8 +40,6 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E db.PrefillDBWithOnlineData(queryExpr); var rows = db.GetDBEntityRows(queryExpr.EntityName); - Console.WriteLine($"\t row count : {rows.Count().ToString()}"); - var entityMetadata = metadata.EntityMetadata[queryExpr.EntityName]; #if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013) diff --git a/src/XrmMockupShared/XrmMockupBase.cs b/src/XrmMockupShared/XrmMockupBase.cs index ab821e82..ff9702b4 100644 --- a/src/XrmMockupShared/XrmMockupBase.cs +++ b/src/XrmMockupShared/XrmMockupBase.cs @@ -8,6 +8,8 @@ using Microsoft.Xrm.Sdk.Query; using Microsoft.Crm.Sdk.Messages; using System.IO; +using System.Diagnostics; +using System.Collections.ObjectModel; namespace DG.Tools.XrmMockup { @@ -50,28 +52,50 @@ public EntityReference BaseCurrency { private Core Core; private MockupServiceProviderAndFactory ServiceFactory; + private readonly Dictionary timers; + public IReadOnlyDictionary Timers => new ReadOnlyDictionary(timers); + + protected XrmMockupSettings Settings { get; } + protected MetadataSkeleton Metadata { get; } + protected List Workflows { get; } + protected List SecurityRoles { get; } /// /// Create a new XrmMockup instance /// - /// - protected XrmMockupBase(XrmMockupSettings settings) { + protected XrmMockupBase(XrmMockupSettings settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) { + timers = new Dictionary(); + Settings = settings; + + Stopwatch stopwatch = Stopwatch.StartNew(); + var metadataDirectory = settings.MetadataDirectoryPath ?? "../../Metadata/"; + Metadata = metadata ?? Utility.GetMetadata(metadataDirectory); + timers[nameof(Utility.GetMetadata)] = stopwatch.ElapsedMilliseconds; + + stopwatch.Restart(); + Workflows = workflows ?? Utility.GetWorkflows(metadataDirectory); + timers[nameof(Utility.GetWorkflows)] = stopwatch.ElapsedMilliseconds; - var metadataDirectory = "../../Metadata/"; - if (settings.MetadataDirectoryPath != null) - metadataDirectory = settings.MetadataDirectoryPath; - MetadataSkeleton metadata = Utility.GetMetadata(metadataDirectory); + stopwatch.Restart(); + SecurityRoles = securityRoles ?? Utility.GetSecurityRoles(metadataDirectory); + timers[nameof(Utility.GetSecurityRoles)] = stopwatch.ElapsedMilliseconds; - List workflows = Utility.GetWorkflows(metadataDirectory); - List securityRoles = Utility.GetSecurityRoles(metadataDirectory); + stopwatch.Restart(); + Core = new Core(settings, Metadata, Workflows, SecurityRoles); + timers[nameof(Core)] = stopwatch.ElapsedMilliseconds; + + stopwatch.Restart(); + ServiceFactory = new MockupServiceProviderAndFactory(Core); + timers[nameof(ServiceFactory)] = stopwatch.ElapsedMilliseconds; - this.Core = new Core(settings, metadata, workflows, securityRoles); - this.ServiceFactory = new MockupServiceProviderAndFactory(this.Core); if (settings.EnableProxyTypes == true) { + stopwatch.Restart(); EnableProxyTypes(); + timers[nameof(EnableProxyTypes)] = stopwatch.ElapsedMilliseconds; } - } + stopwatch.Stop(); + } /// /// Enable early-bound types from the given context diff --git a/tests/SharedTests/TestZipSnapshot.cs b/tests/SharedTests/TestZipSnapshot.cs index a6ee9c8e..90ea34c2 100644 --- a/tests/SharedTests/TestZipSnapshot.cs +++ b/tests/SharedTests/TestZipSnapshot.cs @@ -3,6 +3,7 @@ using DG.XrmFramework.BusinessDomain.ServiceContext; using DG.Tools.XrmMockup; using Xunit; +using System.ServiceModel; namespace DG.XrmMockupTest { @@ -26,14 +27,8 @@ public void TestTakeSnapshot() crm.ResetEnvironment(); - try - { - Contact.Retrieve(orgAdminService, contact.Id); - } - catch (Exception ex) - { - Assert.Equal(ex.Message, $"The record of type '{contact.LogicalName}' with id '{contact.Id}' does not exist. If you use hard-coded records from CRM, then make sure you create those records before retrieving them."); - } + var ex = Assert.Throws(() => Contact.Retrieve(orgAdminService, contact.Id)); + Assert.Equal(ex.Message, $"The record of type '{contact.LogicalName}' with id '{contact.Id}' does not exist. If you use hard-coded records from CRM, then make sure you create those records before retrieving them."); crm.RestoreZipSnapshot("testfile"); From 94180e9d688b588a6f750549512adfbe0857b569 Mon Sep 17 00:00:00 2001 From: Morten Holt Date: Tue, 26 Dec 2023 12:32:50 +0100 Subject: [PATCH 2/4] Add abilty to inject custom ITracingService through new setting. This lets the user inject a ITracingService which they control, thus letting them trace to something other than Console. --- RELEASE_NOTES.md | 1 + src/XrmMockupShared/Core.cs | 6 +++-- .../MockupServiceProviderAndFactory.cs | 11 +++++--- src/XrmMockupShared/Plugin/PluginManager.cs | 4 +-- .../CalculateRollupFieldRequestHandler.cs | 2 +- .../Requests/DeleteRequestHandler.cs | 2 +- src/XrmMockupShared/TracingService.cs | 8 ++---- src/XrmMockupShared/TracingServiceFactory.cs | 17 +++++++++++++ .../Workflow/WorkflowManager.cs | 8 +++--- src/XrmMockupShared/XrmMockupSettings.cs | 6 +++++ src/XrmMockupShared/XrmMockupShared.projitems | 1 + tests/SharedTests/TestTracingService.cs | 25 +++++++++++++++++++ 12 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 src/XrmMockupShared/TracingServiceFactory.cs diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 10b83327..f081ef3b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,6 @@ ### 1.12.3 - 22 December 2023 * Add initializer based on an existing instance, letting us copy an already initialized XrmMockup instance (@mkholt) +* Add optional tracing class factory to settings (@mkholt) * Add timers during initialization (@mkholt) ### 1.12.2 - 24 August 2023 diff --git a/src/XrmMockupShared/Core.cs b/src/XrmMockupShared/Core.cs index 8279d4a6..36e7a41d 100644 --- a/src/XrmMockupShared/Core.cs +++ b/src/XrmMockupShared/Core.cs @@ -74,6 +74,7 @@ internal class Core private int baseCurrencyPrecision; public TimeSpan TimeOffset { get; private set; } public MockupServiceProviderAndFactory ServiceFactory { get; } + public TracingServiceFactory TracingServiceFactory { get; } private List systemAttributeNames; @@ -112,6 +113,7 @@ public Core(XrmMockupSettings Settings, MetadataSkeleton metadata, List this.db = new XrmDb(metadata.EntityMetadata, GetOnlineProxy()); this.snapshots = new Dictionary(); this.security = new Security(this, metadata, SecurityRoles,db); + this.TracingServiceFactory = new TracingServiceFactory(settings.TracingServiceFactory); this.ServiceFactory = new MockupServiceProviderAndFactory(this); //add the additional plugin settings to the meta data @@ -1155,14 +1157,14 @@ internal void ExecuteCalculatedFields(DbRow row) if (definition == null) { - var trace = this.ServiceFactory.GetService(typeof(ITracingService)) as ITracingService; + var trace = this.ServiceFactory.GetService(); trace.Trace($"Calculated field on {attr.EntityLogicalName} field {attr.LogicalName} is empty"); return; } var tree = WorkflowConstructor.ParseCalculated(definition); var factory = this.ServiceFactory; tree.Execute(row.ToEntity().CloneEntity(row.Metadata, new ColumnSet(true)), this.TimeOffset, this.GetWorkflowService(), - factory, factory.GetService(typeof(ITracingService)) as ITracingService); + factory, factory.GetService()); } } #endif diff --git a/src/XrmMockupShared/MockupServiceProviderAndFactory.cs b/src/XrmMockupShared/MockupServiceProviderAndFactory.cs index e6a320d6..b335e77e 100644 --- a/src/XrmMockupShared/MockupServiceProviderAndFactory.cs +++ b/src/XrmMockupShared/MockupServiceProviderAndFactory.cs @@ -24,12 +24,12 @@ internal class MockupServiceProviderAndFactory : IServiceProvider, IOrganization /// Creates new MockupServiceProviderAndFactory object /// /// - public MockupServiceProviderAndFactory(Core core) : this(core, null, new TracingService()) { } + public MockupServiceProviderAndFactory(Core core) : this(core, null, core.TracingServiceFactory) { } - internal MockupServiceProviderAndFactory(Core core, PluginContext pluginContext, ITracingService tracingService) { + internal MockupServiceProviderAndFactory(Core core, PluginContext pluginContext, TracingServiceFactory tracingServiceFactory) { this.core = core; this.pluginContext = pluginContext; - this.tracingService = tracingService; + this.tracingService = tracingServiceFactory.GetService(); } /// @@ -44,6 +44,11 @@ public object GetService(Type serviceType) { return null; } + public TService GetService() where TService: class + { + return GetService(typeof(TService)) as TService; + } + public IOrganizationService CreateOrganizationService(Guid? userId) { return new MockupService(core, userId, this.pluginContext); diff --git a/src/XrmMockupShared/Plugin/PluginManager.cs b/src/XrmMockupShared/Plugin/PluginManager.cs index e9427509..5159c98e 100644 --- a/src/XrmMockupShared/Plugin/PluginManager.cs +++ b/src/XrmMockupShared/Plugin/PluginManager.cs @@ -378,7 +378,7 @@ public PluginExecutionProvider ToPluginExecution(object entityObject, Entity pre { // Create the plugin context var thisPluginContext = CreatePluginContext(pluginContext, guid, logicalName, preImage, postImage); - return new PluginExecutionProvider(pluginExecute, new MockupServiceProviderAndFactory(core, thisPluginContext, new TracingService())); + return new PluginExecutionProvider(pluginExecute, new MockupServiceProviderAndFactory(core, thisPluginContext, core.TracingServiceFactory)); } return null; @@ -398,7 +398,7 @@ public void ExecuteIfMatch(object entityObject, Entity preImage, Entity postImag var thisPluginContext = CreatePluginContext(pluginContext, guid, logicalName, preImage, postImage); //Create Serviceprovider, and execute plugin - MockupServiceProviderAndFactory provider = new MockupServiceProviderAndFactory(core, thisPluginContext, new TracingService()); + MockupServiceProviderAndFactory provider = new MockupServiceProviderAndFactory(core, thisPluginContext, core.TracingServiceFactory); try { pluginExecute(provider); diff --git a/src/XrmMockupShared/Requests/CalculateRollupFieldRequestHandler.cs b/src/XrmMockupShared/Requests/CalculateRollupFieldRequestHandler.cs index 2cb47d4b..0b69aff7 100644 --- a/src/XrmMockupShared/Requests/CalculateRollupFieldRequestHandler.cs +++ b/src/XrmMockupShared/Requests/CalculateRollupFieldRequestHandler.cs @@ -40,7 +40,7 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E } else { var tree = WorkflowConstructor.ParseRollUp(definition); var factory = core.ServiceFactory; - var resultTree = tree.Execute(dbEntity, core.TimeOffset, core.GetWorkflowService(), factory, factory.GetService(typeof(ITracingService)) as ITracingService); + var resultTree = tree.Execute(dbEntity, core.TimeOffset, core.GetWorkflowService(), factory, factory.GetService()); var resultLocaltion = ((resultTree.StartActivity as RollUp).Aggregation[1] as Aggregate).VariableName; var result = resultTree.Variables[resultLocaltion]; if (result != null) { diff --git a/src/XrmMockupShared/Requests/DeleteRequestHandler.cs b/src/XrmMockupShared/Requests/DeleteRequestHandler.cs index f012086b..764c4db9 100644 --- a/src/XrmMockupShared/Requests/DeleteRequestHandler.cs +++ b/src/XrmMockupShared/Requests/DeleteRequestHandler.cs @@ -59,7 +59,7 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E }, userRef); break; case CascadeType.Restrict: - var trace = core.ServiceFactory.GetService(typeof(ITracingService)) as ITracingService; + var trace = core.ServiceFactory.GetService(); trace.Trace($"Delete restricted for {relatedEntities.Key.SchemaName} when trying to delete {entity.LogicalName} with id {entity.Id}"); return new DeleteResponse(); } diff --git a/src/XrmMockupShared/TracingService.cs b/src/XrmMockupShared/TracingService.cs index fac9b825..37fc6d0c 100644 --- a/src/XrmMockupShared/TracingService.cs +++ b/src/XrmMockupShared/TracingService.cs @@ -1,18 +1,14 @@ using Microsoft.Xrm.Sdk; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace DG.Tools.XrmMockup { - internal class TracingService : ITracingService { + internal sealed class TracingService : ITracingService { public void Trace(string format, params object[] args) { try { Console.WriteLine(format, args); } - catch + catch { Console.WriteLine(format); } diff --git a/src/XrmMockupShared/TracingServiceFactory.cs b/src/XrmMockupShared/TracingServiceFactory.cs new file mode 100644 index 00000000..953f777f --- /dev/null +++ b/src/XrmMockupShared/TracingServiceFactory.cs @@ -0,0 +1,17 @@ +using Microsoft.Xrm.Sdk; +using System; + +namespace DG.Tools.XrmMockup +{ + internal class TracingServiceFactory + { + private readonly Func _factory; + + public TracingServiceFactory(Func factory) + { + _factory = factory; + } + + public ITracingService GetService() => _factory?.Invoke() ?? new TracingService(); + } +} diff --git a/src/XrmMockupShared/Workflow/WorkflowManager.cs b/src/XrmMockupShared/Workflow/WorkflowManager.cs index 1b916d08..77be9861 100644 --- a/src/XrmMockupShared/Workflow/WorkflowManager.cs +++ b/src/XrmMockupShared/Workflow/WorkflowManager.cs @@ -119,7 +119,7 @@ public void StageAsync(string operation, ExecutionStage stage, } internal void ExecuteWaitingWorkflows(PluginContext pluginContext, Core core) { - var provider = new MockupServiceProviderAndFactory(core, pluginContext, new TracingService()); + var provider = new MockupServiceProviderAndFactory(core, pluginContext, core.TracingServiceFactory); var service = provider.CreateOrganizationService(null, new MockupServiceSettings(true, true, MockupServiceSettings.Role.SDK)); foreach (var waitInfo in waitingWorkflows.ToList()) { waitingWorkflows.Remove(waitInfo); @@ -128,7 +128,7 @@ internal void ExecuteWaitingWorkflows(PluginContext pluginContext, Core core) { var primaryEntity = shadowService.Retrieve(waitInfo.PrimaryEntity.LogicalName, waitInfo.PrimaryEntity.Id, new ColumnSet(true)); variables["InputEntities(\"primaryEntity\")"] = primaryEntity; - waitInfo.Element.Execute(waitInfo.ElementIndex, ref variables, core.TimeOffset, service, provider, new TracingService()); + waitInfo.Element.Execute(waitInfo.ElementIndex, ref variables, core.TimeOffset, service, provider, provider.GetService()); if (variables["Wait"] != null) { waitingWorkflows.Add(variables["Wait"] as WaitInfo); } @@ -382,9 +382,9 @@ private void Execute(Entity workflow, string operation, object entityObject, Ent } internal WorkflowTree ExecuteWorkflow(WorkflowTree workflow, Entity primaryEntity, PluginContext pluginContext, Core core) { - var provider = new MockupServiceProviderAndFactory(core, pluginContext, new TracingService()); + var provider = new MockupServiceProviderAndFactory(core, pluginContext, core.TracingServiceFactory); var service = provider.CreateAdminOrganizationService(new MockupServiceSettings(true, true, MockupServiceSettings.Role.SDK)); - return workflow.Execute(primaryEntity, core.TimeOffset, service, provider, provider.GetService(typeof(ITracingService)) as ITracingService); + return workflow.Execute(primaryEntity, core.TimeOffset, service, provider, provider.GetService()); } internal WorkflowTree ParseWorkflow(Entity workflow) { diff --git a/src/XrmMockupShared/XrmMockupSettings.cs b/src/XrmMockupShared/XrmMockupSettings.cs index 4d4e9756..0e87be74 100644 --- a/src/XrmMockupShared/XrmMockupSettings.cs +++ b/src/XrmMockupShared/XrmMockupSettings.cs @@ -60,6 +60,12 @@ public class XrmMockupSettings /// public MetaPlugin[] IPluginMetadata { get; set; } + /// + /// Optional factory for creating new instances of ITracingService. + /// If not specified, uses the built-in + /// + public Func TracingServiceFactory { get; set; } + #if XRM_MOCKUP_365 /// /// List of Extensions to XrmMockup. This can be used to extend XrmMockup functionality to a certain degree. diff --git a/src/XrmMockupShared/XrmMockupShared.projitems b/src/XrmMockupShared/XrmMockupShared.projitems index 8022c883..b1e4ac4d 100644 --- a/src/XrmMockupShared/XrmMockupShared.projitems +++ b/src/XrmMockupShared/XrmMockupShared.projitems @@ -80,6 +80,7 @@ + diff --git a/tests/SharedTests/TestTracingService.cs b/tests/SharedTests/TestTracingService.cs index 63d62f83..63e37d4b 100644 --- a/tests/SharedTests/TestTracingService.cs +++ b/tests/SharedTests/TestTracingService.cs @@ -16,5 +16,30 @@ public void TracingServiceShouldAcceptXMLFormatStrings() ITracingService trace = new TracingService(); trace.Trace("cams_signatures :

By signing the Agreement Plan, the signatories are certifying, subject to the exceptions detailed below, both the completeness of the Agreement Plan and the agreed commitment between [CUSTOMER] and [DELIVERY AGENT].

"); } + + [Fact] + public void TracingServiceFactoryCallsInnerFactory() + { + ITracingService trace = new TracingService(); + var factory = new TracingServiceFactory(() => trace); + + var fromFactory = factory.GetService(); + Assert.Equal(trace, fromFactory); + + var fromFactory2 = factory.GetService(); + Assert.Equal(fromFactory, fromFactory2); + } + + [Fact] + public void TracingServiceFactoryUsesFallback() + { + var factory = new TracingServiceFactory(null); + + var fromFactory = factory.GetService(); + Assert.NotNull(fromFactory); + + var fromFactory2 = factory.GetService(); + Assert.NotEqual(fromFactory, fromFactory2); + } } } From 1f6c7fe7645ad83f9d8bab2baff34f81467b3f8e Mon Sep 17 00:00:00 2001 From: Morten Holt Date: Thu, 28 Dec 2023 10:20:17 +0100 Subject: [PATCH 3/4] Add optional parameter to override the settings object. This allows us to e.g. inject a new TracingService on each instance letting us separate them. It should be used with caution, as the metadata won't be re-loaded, so not all settings make sense to change from the original --- src/XrmMockup2011/XrmMockup.cs | 10 +++++--- src/XrmMockup2013/XrmMockup.cs | 10 +++++--- src/XrmMockup2015/XrmMockup.cs | 14 +++++++---- src/XrmMockup2016/XrmMockup.cs | 14 +++++++---- src/XrmMockup365/XrmMockup.cs | 10 +++++--- src/XrmMockupShared/Core.cs | 4 +-- .../MockupServiceProviderAndFactory.cs | 2 +- src/XrmMockupShared/TracingServiceFactory.cs | 14 +++++------ src/XrmMockupShared/XrmMockupSettings.cs | 3 +-- tests/SharedTests/TestTracingService.cs | 25 ------------------- 10 files changed, 49 insertions(+), 57 deletions(-) diff --git a/src/XrmMockup2011/XrmMockup.cs b/src/XrmMockup2011/XrmMockup.cs index ea5e5de0..c83e519f 100644 --- a/src/XrmMockup2011/XrmMockup.cs +++ b/src/XrmMockup2011/XrmMockup.cs @@ -47,10 +47,14 @@ public static XrmMockup2011 GetInstance(XrmMockupSettings Settings) { /// /// Gets an instance of XrmMockup2011 using the same metadata as the provided /// - /// - public static XrmMockup2011 GetInstance(XrmMockup2011 xrmMockup) + /// The existing instance to copy + /// + /// If provided, will override the settings from the existing instance.
+ /// NOTE: Changing will not trigger a reload + /// + public static XrmMockup2011 GetInstance(XrmMockup2011 xrmMockup, XrmMockupSettings settings = null) { - return new XrmMockup2011(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + return new XrmMockup2011(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); } } diff --git a/src/XrmMockup2013/XrmMockup.cs b/src/XrmMockup2013/XrmMockup.cs index 056655b5..1d4aad8d 100644 --- a/src/XrmMockup2013/XrmMockup.cs +++ b/src/XrmMockup2013/XrmMockup.cs @@ -41,10 +41,14 @@ public static XrmMockup2013 GetInstance(XrmMockupSettings Settings) { /// /// Gets an instance of XrmMockup2013 using the same metadata as the provided /// - /// - public static XrmMockup2013 GetInstance(XrmMockup2013 xrmMockup) + /// The existing instance to copy + /// + /// If provided, will override the settings from the existing instance.
+ /// NOTE: Changing will not trigger a reload + /// + public static XrmMockup2013 GetInstance(XrmMockup2013 xrmMockup, XrmMockupSettings settings = null) { - return new XrmMockup2013(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + return new XrmMockup2013(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); } } } diff --git a/src/XrmMockup2015/XrmMockup.cs b/src/XrmMockup2015/XrmMockup.cs index cac7b5c4..78315d35 100644 --- a/src/XrmMockup2015/XrmMockup.cs +++ b/src/XrmMockup2015/XrmMockup.cs @@ -16,7 +16,7 @@ namespace DG.Tools.XrmMockup { ///
public class XrmMockup2015 : XrmMockupBase { - private static Dictionary instances = new Dictionary(); + private static readonly Dictionary instances = new Dictionary(); private XrmMockup2015(XrmMockupSettings Settings, MetadataSkeleton metadata = null, List workflows = null, List securityRoles = null) : @@ -37,14 +37,18 @@ public static XrmMockup2015 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + /// /// Gets an instance of XrmMockup2015 using the same metadata as the provided /// - /// - public static XrmMockup2015 GetInstance(XrmMockup2015 xrmMockup) + /// The existing instance to copy + /// + /// If provided, will override the settings from the existing instance.
+ /// NOTE: Changing will not trigger a reload + /// + public static XrmMockup2015 GetInstance(XrmMockup2015 xrmMockup, XrmMockupSettings settings = null) { - return new XrmMockup2015(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + return new XrmMockup2015(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); } - } } diff --git a/src/XrmMockup2016/XrmMockup.cs b/src/XrmMockup2016/XrmMockup.cs index 20672d24..cbd4f764 100644 --- a/src/XrmMockup2016/XrmMockup.cs +++ b/src/XrmMockup2016/XrmMockup.cs @@ -35,10 +35,14 @@ public static XrmMockup2016 GetInstance(XrmMockupSettings Settings) { /// /// Gets an instance of XrmMockup2016 using the same metadata as the provided /// - /// - public static XrmMockup2016 GetInstance(XrmMockup2016 xrmMockup) + /// The existing instance to copy + /// + /// If provided, will override the settings from the existing instance.
+ /// NOTE: Changing will not trigger a reload + /// + public static XrmMockup2016 GetInstance(XrmMockup2016 xrmMockup, XrmMockupSettings settings = null) { - return new XrmMockup2016(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); - } - } + return new XrmMockup2016(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } + } } diff --git a/src/XrmMockup365/XrmMockup.cs b/src/XrmMockup365/XrmMockup.cs index 02c4efe4..5ac2e7d2 100644 --- a/src/XrmMockup365/XrmMockup.cs +++ b/src/XrmMockup365/XrmMockup.cs @@ -40,10 +40,14 @@ public static XrmMockup365 GetInstance(XrmMockupSettings Settings) { /// /// Gets an instance of XrmMockup365 using the same metadata as the provided /// - /// - public static XrmMockup365 GetInstance(XrmMockup365 xrmMockup) + /// The existing instance to copy + /// + /// If provided, will override the settings from the existing instance.
+ /// NOTE: Changing will not trigger a reload + /// + public static XrmMockup365 GetInstance(XrmMockup365 xrmMockup, XrmMockupSettings settings = null) { - return new XrmMockup365(xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + return new XrmMockup365(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); } } } diff --git a/src/XrmMockupShared/Core.cs b/src/XrmMockupShared/Core.cs index 36e7a41d..3bb36351 100644 --- a/src/XrmMockupShared/Core.cs +++ b/src/XrmMockupShared/Core.cs @@ -74,7 +74,7 @@ internal class Core private int baseCurrencyPrecision; public TimeSpan TimeOffset { get; private set; } public MockupServiceProviderAndFactory ServiceFactory { get; } - public TracingServiceFactory TracingServiceFactory { get; } + public ITracingServiceFactory TracingServiceFactory { get; } private List systemAttributeNames; @@ -113,7 +113,7 @@ public Core(XrmMockupSettings Settings, MetadataSkeleton metadata, List this.db = new XrmDb(metadata.EntityMetadata, GetOnlineProxy()); this.snapshots = new Dictionary(); this.security = new Security(this, metadata, SecurityRoles,db); - this.TracingServiceFactory = new TracingServiceFactory(settings.TracingServiceFactory); + this.TracingServiceFactory = settings.TracingServiceFactory ?? new TracingServiceFactory(); this.ServiceFactory = new MockupServiceProviderAndFactory(this); //add the additional plugin settings to the meta data diff --git a/src/XrmMockupShared/MockupServiceProviderAndFactory.cs b/src/XrmMockupShared/MockupServiceProviderAndFactory.cs index b335e77e..dbc74cab 100644 --- a/src/XrmMockupShared/MockupServiceProviderAndFactory.cs +++ b/src/XrmMockupShared/MockupServiceProviderAndFactory.cs @@ -26,7 +26,7 @@ internal class MockupServiceProviderAndFactory : IServiceProvider, IOrganization /// public MockupServiceProviderAndFactory(Core core) : this(core, null, core.TracingServiceFactory) { } - internal MockupServiceProviderAndFactory(Core core, PluginContext pluginContext, TracingServiceFactory tracingServiceFactory) { + internal MockupServiceProviderAndFactory(Core core, PluginContext pluginContext, ITracingServiceFactory tracingServiceFactory) { this.core = core; this.pluginContext = pluginContext; this.tracingService = tracingServiceFactory.GetService(); diff --git a/src/XrmMockupShared/TracingServiceFactory.cs b/src/XrmMockupShared/TracingServiceFactory.cs index 953f777f..2ccbb8f3 100644 --- a/src/XrmMockupShared/TracingServiceFactory.cs +++ b/src/XrmMockupShared/TracingServiceFactory.cs @@ -3,15 +3,13 @@ namespace DG.Tools.XrmMockup { - internal class TracingServiceFactory + public interface ITracingServiceFactory { - private readonly Func _factory; - - public TracingServiceFactory(Func factory) - { - _factory = factory; - } + ITracingService GetService(); + } - public ITracingService GetService() => _factory?.Invoke() ?? new TracingService(); + internal class TracingServiceFactory : ITracingServiceFactory + { + public ITracingService GetService() => new TracingService(); } } diff --git a/src/XrmMockupShared/XrmMockupSettings.cs b/src/XrmMockupShared/XrmMockupSettings.cs index 0e87be74..442d7c69 100644 --- a/src/XrmMockupShared/XrmMockupSettings.cs +++ b/src/XrmMockupShared/XrmMockupSettings.cs @@ -1,5 +1,4 @@ using Microsoft.Xrm.Sdk.Client; -using Microsoft.Xrm.Sdk; using System; using System.Collections.Generic; #if !(XRM_MOCKUP_2011 || XRM_MOCKUP_2013) @@ -64,7 +63,7 @@ public class XrmMockupSettings /// Optional factory for creating new instances of ITracingService. /// If not specified, uses the built-in ///
- public Func TracingServiceFactory { get; set; } + public ITracingServiceFactory TracingServiceFactory { get; set; } #if XRM_MOCKUP_365 /// diff --git a/tests/SharedTests/TestTracingService.cs b/tests/SharedTests/TestTracingService.cs index 63e37d4b..63d62f83 100644 --- a/tests/SharedTests/TestTracingService.cs +++ b/tests/SharedTests/TestTracingService.cs @@ -16,30 +16,5 @@ public void TracingServiceShouldAcceptXMLFormatStrings() ITracingService trace = new TracingService(); trace.Trace("cams_signatures :

By signing the Agreement Plan, the signatories are certifying, subject to the exceptions detailed below, both the completeness of the Agreement Plan and the agreed commitment between [CUSTOMER] and [DELIVERY AGENT].

"); } - - [Fact] - public void TracingServiceFactoryCallsInnerFactory() - { - ITracingService trace = new TracingService(); - var factory = new TracingServiceFactory(() => trace); - - var fromFactory = factory.GetService(); - Assert.Equal(trace, fromFactory); - - var fromFactory2 = factory.GetService(); - Assert.Equal(fromFactory, fromFactory2); - } - - [Fact] - public void TracingServiceFactoryUsesFallback() - { - var factory = new TracingServiceFactory(null); - - var fromFactory = factory.GetService(); - Assert.NotNull(fromFactory); - - var fromFactory2 = factory.GetService(); - Assert.NotEqual(fromFactory, fromFactory2); - } } } From a0a0e3a4e74110b7c9afd151f113dc000df201eb Mon Sep 17 00:00:00 2001 From: Morten Holt Date: Wed, 3 Jan 2024 10:25:05 +0100 Subject: [PATCH 4/4] Fix indentation in TracingService --- src/XrmMockupShared/TracingService.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/XrmMockupShared/TracingService.cs b/src/XrmMockupShared/TracingService.cs index 37fc6d0c..dbef46cc 100644 --- a/src/XrmMockupShared/TracingService.cs +++ b/src/XrmMockupShared/TracingService.cs @@ -1,9 +1,12 @@ using Microsoft.Xrm.Sdk; using System; -namespace DG.Tools.XrmMockup { - internal sealed class TracingService : ITracingService { - public void Trace(string format, params object[] args) { +namespace DG.Tools.XrmMockup +{ + internal sealed class TracingService : ITracingService + { + public void Trace(string format, params object[] args) + { try { Console.WriteLine(format, args); @@ -12,6 +15,6 @@ public void Trace(string format, params object[] args) { { Console.WriteLine(format); } - } - } + } + } }