diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2bce8dca..f081ef3b 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,8 @@ +### 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 * 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..c83e519f 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,19 @@ public static XrmMockup2011 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2011 using the same metadata as the provided + /// + /// 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(settings ?? 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..1d4aad8d 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,18 @@ public static XrmMockup2013 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2013 using the same metadata as the provided + /// + /// 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(settings ?? 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..78315d35 100644 --- a/src/XrmMockup2015/XrmMockup.cs +++ b/src/XrmMockup2015/XrmMockup.cs @@ -16,13 +16,14 @@ 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) : - 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,18 @@ public static XrmMockup2015 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup2015 using the same metadata as the provided + /// + /// 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(settings ?? 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..cbd4f764 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,18 @@ public static XrmMockup2016 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } - } + + /// + /// Gets an instance of XrmMockup2016 using the same metadata as the provided + /// + /// 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(settings ?? 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..5ac2e7d2 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,18 @@ public static XrmMockup365 GetInstance(XrmMockupSettings Settings) { instances[Settings] = instance; return instance; } + + /// + /// Gets an instance of XrmMockup365 using the same metadata as the provided + /// + /// 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(settings ?? xrmMockup.Settings, xrmMockup.Metadata, xrmMockup.Workflows, xrmMockup.SecurityRoles); + } } } diff --git a/src/XrmMockupShared/Core.cs b/src/XrmMockupShared/Core.cs index 8279d4a6..3bb36351 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 ITracingServiceFactory 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 = settings.TracingServiceFactory ?? new 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..dbc74cab 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, ITracingServiceFactory 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/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/TracingService.cs b/src/XrmMockupShared/TracingService.cs index fac9b825..dbef46cc 100644 --- a/src/XrmMockupShared/TracingService.cs +++ b/src/XrmMockupShared/TracingService.cs @@ -1,21 +1,20 @@ 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 { - 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); } - catch + catch { Console.WriteLine(format); } - } - } + } + } } diff --git a/src/XrmMockupShared/TracingServiceFactory.cs b/src/XrmMockupShared/TracingServiceFactory.cs new file mode 100644 index 00000000..2ccbb8f3 --- /dev/null +++ b/src/XrmMockupShared/TracingServiceFactory.cs @@ -0,0 +1,15 @@ +using Microsoft.Xrm.Sdk; +using System; + +namespace DG.Tools.XrmMockup +{ + public interface ITracingServiceFactory + { + ITracingService GetService(); + } + + internal class TracingServiceFactory : ITracingServiceFactory + { + public ITracingService GetService() => 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/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/src/XrmMockupShared/XrmMockupSettings.cs b/src/XrmMockupShared/XrmMockupSettings.cs index 4d4e9756..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) @@ -60,6 +59,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 ITracingServiceFactory 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/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");