|
1 | | -# Transmitly.Microsoft.Extensions.Dependencyinjection |
| 1 | +# Transmitly.Microsoft.Extensions.DependencyInjection |
2 | 2 |
|
3 | | -A [Transmitly](https://github.com/transmitly/transmitly) extension to help with configuring a communications client using Microsoft Dependency Injection. |
| 3 | +Microsoft DI integration for [Transmitly](https://github.com/transmitly/transmitly). |
4 | 4 |
|
5 | | -### Getting started |
| 5 | +This package wraps Transmitly registration so `ICommunicationsClient` and core Transmitly factories are wired through `IServiceCollection`, allowing constructor injection in your Transmitly components. |
6 | 6 |
|
7 | | -To use the dependency injection extension, first install the [NuGet package](https://nuget.org/packages/transmitly.microsoft.extensions.dependencyinjection): |
| 7 | +## What this package adds |
| 8 | + |
| 9 | +- Registers `ICommunicationsClient` so it can be resolved from Microsoft DI. |
| 10 | +- Bridges Transmitly factories to `IServiceProvider`, including channel provider dispatcher resolution and: |
| 11 | + - platform identity resolvers |
| 12 | + - content model enrichers |
| 13 | + - platform identity profile enrichers |
| 14 | +- Supports class-based configuration via `ICommunicationsClientConfigurator`. |
| 15 | +- Supports swapping in a custom `ICommunicationsClient` implementation. |
| 16 | + |
| 17 | +## Install |
8 | 18 |
|
9 | 19 | ```shell |
10 | | -dotnet add package Transmitly.Microsoft.Extensions.Dependencyinjection |
| 20 | +dotnet add package Transmitly.Microsoft.Extensions.DependencyInjection |
11 | 21 | ``` |
12 | 22 |
|
13 | | -Then start configuring... |
| 23 | +## Quick Start |
| 24 | + |
| 25 | +Use inline builder configuration: |
14 | 26 |
|
15 | 27 | ```csharp |
16 | 28 | using Transmitly; |
17 | | -... |
18 | 29 |
|
19 | 30 | var builder = WebApplication.CreateBuilder(args); |
20 | | -builder.Services.AddTransmitly(tly=>{ |
21 | | - //Check out the Transmit.ly project for details on configuration options! |
| 31 | + |
| 32 | +builder.Services.AddTransmitly(tly => |
| 33 | +{ |
| 34 | + // Configure channels, pipelines, templates, resolvers, enrichers, etc. |
22 | 35 | }); |
23 | 36 |
|
| 37 | +var app = builder.Build(); |
| 38 | + |
| 39 | +// Anywhere in your app: |
| 40 | +var client = app.Services.GetRequiredService<ICommunicationsClient>(); |
24 | 41 | ``` |
25 | | -* Check out the [Transmitly](https://github.com/transmitly/transmitly) project for more details on how to configure a communications client as well as how it can be used to improve how you manage your customer communications. |
26 | 42 |
|
27 | | -### Advanced Configuration |
28 | | -If you need to access a database or service or just in general need to access services via dependency injection consdering registring an `ICommunicationsClientConfigurator` object to give yourself more control. |
| 43 | +## DI-Backed Components |
29 | 44 |
|
30 | | -First we'll create implement the `ICommunicationsClientConfigurator` |
| 45 | +If a resolver/enricher has constructor dependencies, register the type in DI first. |
31 | 46 |
|
32 | | -MyPlatformCommsConfig.cs |
| 47 | +```csharp |
| 48 | +builder.Services.AddSingleton<IMyDependency, MyDependency>(); |
| 49 | +builder.Services.AddTransient<MyIdentityResolver>(); |
| 50 | +builder.Services.AddTransient<MyContentModelEnricher>(); |
| 51 | +builder.Services.AddTransient<MyProfileEnricher>(); |
| 52 | + |
| 53 | +builder.Services.AddTransmitly(tly => |
| 54 | +{ |
| 55 | + tly.AddPlatformIdentityResolver<MyIdentityResolver>(); |
| 56 | + tly.AddContentModelEnricher<MyContentModelEnricher>(); |
| 57 | + tly.AddPlatformIdentityProfileEnricher<MyProfileEnricher>(); |
| 58 | +}); |
| 59 | +``` |
| 60 | + |
| 61 | +If these types are added to the Transmitly builder but not registered in DI, they may fail to resolve at dispatch time. |
| 62 | + |
| 63 | +## Class-Based Configuration |
| 64 | + |
| 65 | +If you want the Transmitly setup itself to use DI dependencies, implement `ICommunicationsClientConfigurator`. |
33 | 66 |
|
34 | 67 | ```csharp |
35 | | -public class MyPlatformCommsConfig : ICommunicationsClientConfigurator |
| 68 | +public sealed class MyTransmitlyConfigurator : ICommunicationsClientConfigurator |
36 | 69 | { |
37 | | - private readonly IOptions<TransmitlySettings> _options; |
38 | | - private readonly ICommunicationsPipelineConfigurator[] _pipelineConfigurators; |
| 70 | + private readonly IOptions<MyTransmitlyOptions> _options; |
39 | 71 |
|
40 | | - // ICommunicationsPipelineConfigurator would be a custom inteface and you would be responsible for registering these implementations. |
41 | | - public MyPlatformCommsConfig(IOptions<TransmitlySettings> options, IEnumerable<ICommunicationsPipelineConfigurator> pipelineConfigurators) |
| 72 | + public MyTransmitlyConfigurator(IOptions<MyTransmitlyOptions> options) |
42 | 73 | { |
43 | 74 | _options = options; |
44 | | - _pipelineConfigurators = [.. pipelineConfigurators]; |
45 | | - } |
46 | | - |
47 | | - public void ConfigureClient(CommunicationsClientBuilder cfg) |
48 | | - { |
49 | | - var transmitlySettings = _options.Value; |
50 | | - |
51 | | - cfg |
52 | | - .AddTwilioSupport(twilio => |
53 | | - { |
54 | | - var twilioConfig = transmitlySettings.ChannelProviders.Twilio; |
55 | | - |
56 | | - twilio.AuthToken = twilioConfig.AuthToken; |
57 | | - twilio.AccountSid = twilioConfig.AccountSid; |
58 | | - }) |
59 | | - .AddSmtpSupport(smtp => |
60 | | - { |
61 | | - var smtpConfig = transmitlySettings.ChannelProviders.Smtp; |
62 | | - |
63 | | - smtp.Host = smtpConfig.Host; |
64 | | - smtp.Port = smtpConfig.Port; |
65 | | - smtp.UserName = smtpConfig.UserName; |
66 | | - smtp.Password = smtpConfig.Password; |
67 | | - }); |
68 | 75 | } |
69 | 76 |
|
70 | | - private void ConfigurePipelines(CommunicationsClientBuilder cfg) |
| 77 | + public void ConfigureClient(CommunicationsClientBuilder builder) |
71 | 78 | { |
72 | | - foreach (var communicationsPipelineConfigurator in _pipelineConfigurators) |
73 | | - { |
74 | | - cfg.AddPipeline(communicationsPipelineConfigurator.Name, cfg => |
75 | | - { |
76 | | - communicationsPipelineConfigurator.Configure(cfg); |
77 | | - }); |
78 | | - } |
| 79 | + // Build Transmitly config using _options and other injected services. |
79 | 80 | } |
80 | | - |
81 | 81 | } |
82 | 82 | ``` |
83 | | -If you're familiiar with Transmitly, it's doing all the same things you're familiar with. The difference is you can now use registered classes and interfaces from your app's registration. This exmpale allows you to pull your config from jsut about anywhere. It also allows you to define custom pipeline configurators. These would allow you to spread your pipline configuration by domain, service, team or just about any way that makes sense for your team. |
84 | 83 |
|
85 | | -Example Pipline Configurator |
| 84 | +Register it: |
86 | 85 |
|
87 | 86 | ```csharp |
88 | | -public class MyOrderPlacePipeline : ICommunicationsPipelineConfigurator |
89 | | -{ |
90 | | - public string Name => "ordering.placement.thankyou"; |
91 | | - |
92 | | - public void Configure(IPipelineConfiguration pipeline) |
93 | | - { |
94 | | - pipeline |
95 | | - .AddEmail("from@example.com".AsIdentityAddress(), email => |
96 | | - { |
97 | | - email.Subject.AddStringTemplate("Transmit.ly order receipt: {{OrderId}}"); |
98 | | - email.HtmlBody.AddStringTemplate("<h1>Thank you for your order {{aud.FirstName}}</h1><p>Totaling ${{GrandTotal}}. Your order id is {{OrderId}}.</p>"); |
99 | | - email.TextBody.AddStringTemplate("Thank you for your order {{aud.FirstName}}, totaling ${{GrandTotal}} dollars. Your order id is {{OrderId}}."); |
100 | | - }) |
101 | | - .AddVoice("18881234567".AsIdentityAddress(), sms => |
102 | | - { |
103 | | - sms.Message.AddStringTemplate("Thank you for your order {{aud.FirstName}}, totaling {{GrandTotal}} dollars. Your order id is {{OrderId}}"); |
104 | | - }); |
105 | | - } |
106 | | -} |
107 | | - |
| 87 | +builder.Services.AddTransmitly<MyTransmitlyConfigurator>(); |
108 | 88 | ``` |
109 | 89 |
|
110 | | -Next, we'll need to let Transmitly know you're taking going to take control over the configuration in our `MyPlatformCommsConfig` class |
| 90 | +## Custom Client Override |
111 | 91 |
|
112 | | -Program.cs |
113 | | -```csharp |
114 | | -using Transmitly; |
115 | | -... |
116 | | - |
117 | | -var builder = WebApplication.CreateBuilder(args); |
118 | | -builder.Services.AddTransmitly<MyPlatformCommsConfig>(); |
119 | | -``` |
120 | | -Yup, it's that simple. Now when you resolve an `ICommunicationsClient` your custom `MyPlatformCommsConfig` will be called. |
| 92 | +To provide your own `ICommunicationsClient` implementation: |
121 | 93 |
|
122 | | - |
123 | | - |
124 | | -### Still need more control? |
125 | | -If implementing your own `ICommunicationsClientConfigurator` isn't enough control. Consider also registering your own custom `ICommunciationsClient` implementations |
126 | | - |
127 | | -MyCustomClient |
128 | 94 | ```csharp |
129 | | -public class InjectedConfiguredCommunicationsClient : ICommunicationsClient |
130 | | -{ |
131 | | - private readonly Lazy<ICommunicationsClient> _lazy; |
132 | | - |
133 | | - public InjectedConfiguredCommunicationsClient(ICommunicationsClientConfigurator configurator) |
134 | | - { |
135 | | - _lazy = new Lazy<ICommunicationsClient>(() => |
136 | | - { |
137 | | - var cfg = new CommunicationsClientBuilder(); |
138 | | - configurator.ConfigureClient(cfg); |
139 | | - return cfg.BuildClient(); |
140 | | - }); |
141 | | - } |
142 | | - |
143 | | - public ICommunicationsClient Client |
144 | | - { |
145 | | - get |
146 | | - { |
147 | | - return _lazy.Value; |
148 | | - } |
149 | | - } |
150 | | - |
151 | | - public void DeliverReport(DeliveryReport report) |
152 | | - { |
153 | | - Client.DeliverReport(report); |
154 | | - } |
155 | | - |
156 | | - public void DeliverReports(IReadOnlyCollection<DeliveryReport> reports) |
157 | | - { |
158 | | - Client.DeliverReports(reports); |
159 | | - } |
160 | | - |
161 | | - public Task<IDispatchCommunicationResult> DispatchAsync(string pipelineName, IReadOnlyCollection<IPlatformIdentityProfile> platformIdentities, ITransactionModel transactionalModel, IReadOnlyCollection<string> channelPreferences, string? cultureInfo = null, CancellationToken cancellationToken = default) |
162 | | - { |
163 | | - return Client.DispatchAsync(pipelineName, platformIdentities, transactionalModel, channelPreferences, cultureInfo, cancellationToken); |
164 | | - } |
165 | | - |
166 | | - public Task<IDispatchCommunicationResult> DispatchAsync(string pipelineName, IReadOnlyCollection<IPlatformIdentityReference> identityReferences, ITransactionModel transactionalModel, IReadOnlyCollection<string> channelPreferences, string? cultureInfo = null, CancellationToken cancellationToken = default) |
167 | | - { |
168 | | - return Client.DispatchAsync(pipelineName, identityReferences, transactionalModel, channelPreferences, cultureInfo, cancellationToken); |
169 | | - } |
| 95 | +builder.Services.AddTransmitly<MyTransmitlyConfigurator, MyCommunicationsClient>(); |
170 | 96 | ``` |
171 | 97 |
|
| 98 | +## More Transmitly Docs |
172 | 99 |
|
173 | | -Registration example |
174 | | - |
175 | | -```csharp |
176 | | -using Transmitly; |
177 | | -... |
178 | | - |
179 | | -var builder = WebApplication.CreateBuilder(args); |
180 | | -builder.Services.AddTransmitly<MyPlatformCommsConfig, InjectedConfiguredCommunicationsClient>(); |
181 | | -``` |
182 | | - |
183 | | -Registering your own communications client gives you the ultimate flexibility and control over configuration, and execution of your notifications. |
| 100 | +For full channel/pipeline/template configuration options, see the main [Transmitly project](https://github.com/transmitly/transmitly). |
184 | 101 |
|
185 | 102 | --- |
186 | | -_Copyright © Code Impressions, LLC. This open-source project is sponsored and maintained by Code Impressions |
187 | | -and is licensed under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._ |
| 103 | +_Copyright (c) Code Impressions, LLC. This open-source project is sponsored and maintained by Code Impressions and is licensed under the [Apache License, Version 2.0](http://apache.org/licenses/LICENSE-2.0.html)._ |
0 commit comments