public static IServiceCollection AddXrmFramework(this IServiceCollection serviceCollection, Action <XrmFrameworkOptionBuilder> optionsBuilderAction = null) { var optionsBuilder = new XrmFrameworkOptionBuilder(); optionsBuilderAction?.Invoke(optionsBuilder); serviceCollection.TryAdd(new ServiceDescriptor(typeof(IOrganizationService), sp => #if NETCOREAPP new Microsoft.PowerPlatform.Dataverse.Client.ServiceClient(optionsBuilder.ConnectionString) #else new Xrm.Tooling.Connector.CrmServiceClient(optionsBuilder.ConnectionString) #endif , ServiceLifetime.Singleton)); serviceCollection.TryAdd(new ServiceDescriptor(typeof(IServiceContext), sp => { var orgService = sp.GetService <IOrganizationService>(); return(new ServiceContextBase(orgService)); }, ServiceLifetime.Singleton)); var assembly = typeof(IService).Assembly; var serviceType = typeof(IService); var serviceTypes = assembly.GetModules().SelectMany(m => m.GetTypes().Where(t => serviceType.IsAssignableFrom(t) && t.IsInterface)).ToList(); var serviceImplementationTypes = assembly.GetModules().SelectMany(m => m.GetTypes().Where(type => !type.IsAbstract && type.IsClass && serviceType.IsAssignableFrom(type))).ToList(); foreach (var type in serviceTypes) { var serviceImplementationType = serviceImplementationTypes.FirstOrDefault(t => type.IsAssignableFrom(t)); if (serviceImplementationType != null) { var descriptor = ServiceDescriptor.Describe(type, (sp) => DynamicProxyLoggingDecorator.Decorate(type, ActivatorUtilities.GetServiceOrCreateInstance(sp, serviceImplementationType)), ServiceLifetime.Scoped); serviceCollection.Add(descriptor); } } return(serviceCollection); }
static async Task TestCompositionProxy() { Console.WriteLine(); Console.WriteLine("--------------------------------"); Console.WriteLine("Creating composition-based proxy"); Console.WriteLine("--------------------------------"); Console.WriteLine(); var undecoratedWidget = new Widget("Widgetty", 9.99); var widget = DynamicProxyLoggingDecorator.DecorateViaComposition <IWidget>(undecoratedWidget); // Set property widget.Color = Color.Red; Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Get property Console.WriteLine($"Last updated: {widget.LastUpdated}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Set field // DynamicProxy interface proxies don't allow access to fields (since they implement an interface) // The only way to get/set fields is via private reflection or by accessing the undecorated object undecoratedWidget._description = "The best widget of all!"; Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Get field Console.WriteLine($"Description updated to : {undecoratedWidget._description}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call overridden method Console.WriteLine($"Widget: {widget.ToString()}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call async method Console.WriteLine($"SetDescriptionAsync return: {await widget.SetDescriptionAsync("The best widget ever!")}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call method with out and ref parameters var boolValue = false; widget.SetDescriptionAndGetPrice("It's a widget!", out double priceOut, ref boolValue); Console.WriteLine($"Received {priceOut} & {boolValue} from out and ref parameters"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call method that throws exception try { widget.BuyWidget(); } catch (NotSupportedException) { Console.WriteLine("Caught expected exception"); } }
static async Task TestInheritanceProxy() { Console.WriteLine(); Console.WriteLine("--------------------------------"); Console.WriteLine("Creating inheritance-based proxy"); Console.WriteLine("--------------------------------"); Console.WriteLine(); var widget = DynamicProxyLoggingDecorator.DecorateViaInheritance <Widget>(); // Set property widget.Color = Color.Red; Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Get property Console.WriteLine($"Last updated: {widget.LastUpdated}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Set field // DynamicProxy class proxies allow access to fields (since they subclass the target), // but don't intercept the access. widget._description = "The best widget of all!"; Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Get field // As with setting fields, this will work but will not be intercepted. Console.WriteLine($"Description updated to : {widget._description}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call overridden method Console.WriteLine($"Widget: {widget.ToString()}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call async method Console.WriteLine($"SetDescriptionAsync return: {await widget.SetDescriptionAsync("The best widget ever!")}"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call method with out and ref parameters var boolValue = false; widget.SetDescriptionAndGetPrice("It's a widget!", out double priceOut, ref boolValue); Console.WriteLine($"Received {priceOut} & {boolValue} from out and ref parameters"); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); // Call method that throws exception try { widget.BuyWidget(); } catch (NotSupportedException) { Console.WriteLine("Caught expected exception"); } }