Dependency injection Email Manager constructor call - c#

This one is a follow up question to Dependency Injection using Unity
So , as a set up I have a CustomConfiguration.cs file which is supposed to populate from a config section in my web.config file
This is the signature for the file
public class CustomConfiguration : ICustomProcessorConfig, IEmailConfig, IReportConfig
{
#region Properties
private CustomProcessorConfig ConfigSection { get; set; }
#endregion
#region Constructors (1)
public CustomConfiguration()
{
ConfigSection = ConfigurationManager.GetSection("customConfiguration") as ConfigSection;
}
#endregion Constructors 
#region ICustomConfiguration Members
public string Text { get { return ConfigSection.Text; } }
public string Subject { get { return ConfigSection.Subject; } }
public string SmtpHost { get { return ConfigSection.EmailSettings.SmtpHost; } }
public int SmtpPort { get { return ConfigSection.EmailSettings.SmtpPort; } }
These are the 3 files I have for Email Generation :
public interface IEmailManager
{
void SendEmail(string toAddress, string fromAddress, string subject, string body, bool htmlBody);
}
public interface IEmailConfig
{
string SmtpHost { get; }
int SmtpPort { get; }
}
And Finally I have the Email Manager which inherits the IEmailManager interface
public class EmailManager: IEmailManager
{
#region Constructors (1)
public EmailManager(IEmailConfiguration configuration)
{
CurrentSmtpClient = new SmtpClient
{
Host = configuration.SmtpHost,
Port = configuration.SmtpPort,
Credentials =
new NetworkCredential(configuration.UserName, configuration.Password)
};
}
#endregion Constructors 
// send Mail is also implemented
}
Coming back to the previous question I have my set up like :
Container = new UnityContainer();
Container.RegisterType<ICustomConfiguration,CustomConfiguration>(new ContainerControlledLifetimeManager());
Container.RegisterType<IEmailManager, EmailManager>(new ContainerControlledLifetimeManager());
Container.RegisterType<IReportGenerator, ReportGenerator>(new ContainerControlledLifetimeManager());
Configuration = Container.Resolve<ICustomConfiguration>();
Emailer = Container.Resolve<IEmailManager>();
ReportGenerator = Container.Resolve<IReportGenerator>();
I'm getting a ResolutionFailedExceptionsaying The parameter configuration could not be resolved when attempting to call constructor for EmailManager.
I had a different DI setup and I would need the configuration information from IEmailConfig still. Is there a way of going past this ? I need the config information to proceed with sending the email as you can guess with my setup.
Am I binding different repo to my Container ? Or how should I change my EmailManager code ?

You need to register the IEmailConfig interface with the CustomConfiguration class in the container.
Container.RegisterType<IEmailConfig , CustomConfiguration >(new ContainerControlledLifetimeManager());

IEmailConfiguration missing mapping in the unity container. Need to add the concrete class that maps this interface

Related

Register multiple singletons with same interface but different constructor parameters values

I got stuck and need some advice or pointer to a solution.
A web API with ASP.NET Core 3.1
Startup.cs
services.AddSingleton<ITopicClient>(s => new TopicClient({connectionstring},{topic}));
TopicRepository.cs
public class TopicRepository : ITopicRepository
{
private readonly ITopicClient _topicClient1;
private readonly ITopicClient _topicClient2;
public TopicRepository (ITopicClient topicClient1, ITopicClient topicClient2)
{
_topicClient1 = topicClient1;
_topicClient2 = topicClient2;
}
public async Task<Response> SendToTopicAsync(string message, string topic)
{
if( topic == "topic1")
await _topicClient1.send(message);
else if (topic == "topic2")
await _topicClient2.send(message);
}
}
TopicClient.cs in a shared library
public TopicClient(string serviceBusConnectionString, string topicName)
{
_topicClient = new TopicClient(_serviceBusConnectionString,topicName);
}
I need to send message to different topics. I would like to register services with different topic names in startup.cs. I want to reuse topicClient connection.
services.AddSingleton(s => new TopicClient({connectionstring},{topic1}));
services.AddSingleton(s => new TopicClient({connectionstring},{topic2}));
How can I achieve this by registering singleton instances of same type using same interface ?
Thank you in advance!
You could use a client resolver that holds your registered clients with a wrapper around the client.
First create a wrapper around your client with a name or enum for how to resolve it. As I'm not a fan of magic strings I decided to go with an enum in the example.
// Wrapper for your TopicClients
public interface ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
}
// Implement the ICustomTopicClient interface
public class CustomTopicClient : ICustomTopicClient
{
public ITopicClient TopicClient { get; }
public TopicName TopicName { get; }
public CustomTopicClient(ITopicClient topicClient, TopicName topicName)
{
TopicClient = topicClient;
TopicName = topicName;
}
}
// Enum for how to resolve the requested TopicClient
public enum TopicName
{
Topic1 = 0,
Topic2 = 1
}
// Register all ICustomTopicClients in your container
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic}), TopicName.Topic1));
services.AddSingleton<ICustomTopicClient>(s => new CustomTopicClient(new TopicClient({connectionstring},{topic2}), TopicName.Topic2));
Then you create a resolver that holds all custom clients.
You inject the collection of clients from the container and create a dictionary with a public method to resolve the clients.
public interface IMessageClientResolver
{
ITopicClient ResolveClient(TopicName name);
}
public class MessageClientResolver : IMessageClientResolver
{
private readonly Dictionary<TopicName, ITopicClient> topicClients;
public MessageClientResolver(IEnumerable<ICustomTopicClient> clients)
{
topicClients = clients.ToDictionary(k => k.TopicName, v => v.TopicClient);
}
public ITopicClient ResolveClient(TopicName name)
{
topicClients.TryGetValue(name, out var client);
if (client is null)
throw new ArgumentException(nameof(client));
return client;
}
}
Register the resolver to the container.
services.AddSingleton<IMessageClientResolver, MessageClientResolver>();
And then use it like this:
public class Foo
{
private readonly ITopicClient topicClient;
private readonly ITopicClient topicClient2;
public Foo(IMessageClientResolver clientResolver)
{
topicClient = clientResolver.ResolveClient(TopicName.Topic1);
topicClient2 = clientResolver.ResolveClient(TopicName.Topic2);
}
}
You can use the same pattern and extend the resolver with IQueueClients. And add a resolve method to return the IQueueClient by a QueueName enum.
You can already register multiple instances as the same interface, so when you do:
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic1"));
services.AddSingleton<ITopicClient>(_ => new TopicClient("topic2"));
you already added two instances to the container.
It is just when you resolve interface ITopicClient, you always get the last added instance. For example, if you resolve:
// instance = topic2
var instance = container.GetService<ITopicClient>();
If you need all instances, you should resolve / inject IEnumerable<ITopicClient>.
class TopicRepository
{
public TopicRepository(IEnumerable<ITopicClient> clients)
{
// clients contains topic1 and topic2
}
}

Dependency injection implementation for app setting c#

NotificationHubConnectionSettings.cs file to fetch connection string from web.config
public class NotificationHubConnectionSettings
{
public NotificationHubClient Hub { get; set; }
public NotificationHubConnectionSettings()
{
Hub = NotificationHubClient.CreateClientFromConnectionString(ConfigurationManager.AppSettings["Microsoft.Azure.NotificationHubs.ConnectionString"], ConfigurationManager.AppSettings["NotificationHub"]);
}
}
Inside Bootstrapper.cs
using Unity dependency injection nuget
private static IUnityContainer BuildUnityContainer()
{
try
{
var container = new UnityContainer();
container.RegisterType<NotificationHubConnectionSettings>().RegisterType<NotificationHubConnectionSettings>(new HierarchicalLifetimeManager());
return container;
}
catch (Exception)
{
return null;
}
}
In HomeController.cs
want to implement dependency injection -
private readonly NotificationHubClient _hub;
public HomeController(NotificationHubConnectionSettings hub)
{
_hub = hub.Hub;
}
// POST api/register
// This creates a registration id
public async Task<string> Post(string handle = null)
{
string newRegistrationId = null;
if (handle != null)
{
var registrations = await _hub.GetRegistrationsByChannelAsync(handle, 100);
Is this correct way to implement dependency injection?
You should be using a interface type here.
Create a contract for INotificationHubConnectionSettings class in the form of a interface which dictates to your system all public methods and properties available.
public interface INotificationHubConnectionSettings
{
NotificationHubClient Hub { get; set; }
}
Then have your actual NotificationHubConnectionSettings class inherit from this interface;
public class NotificationHubConnectionSettings : INotificationHubConnectionSettings
{
public NotificationHubClient Hub { get; set; }
public NotificationHubConnectionSettings()
{
Hub = NotificationHubClient.CreateClientFromConnectionString(ConfigurationManager.AppSettings["Microsoft.Azure.NotificationHubs.ConnectionString"], ConfigurationManager.AppSettings["NotificationHub"]);
}
}
Now register the interface and class inside of UnityContainer and change your constructor to the following;
private readonly INotificationHubClient _hub;
public HomeController(NotificationHubConnectionSettings hub)
{
_hub = hub.Hub;
}
Always use interfaces for dependency injection.

How to convert this static class method into a dependency injection? (Specific code included)

(I am sure that I formatted the question badly, I would be happy to revise and fix depending on comments)
I have a static class and I am trying to improve the design with dependency injection. I don't necessarily want this class to be static anymore because I will be using .NET Core, which promotes dependency injection over static class situations.
The simplified code in .NET (not Core):
public static class Utils
{
public static readonly string tokenUrl = ConfigurationManager.AppSettings["tokenUrl"];
public static readonly string tokenKey = ConfigurationManager.AppSettings["tokenKey"];
public async static Task<bool> SendEmail(Email email)
{
var http = new HttpClient();
http.DefaultRequestHeaders.Add("subscription-key", tokenKey);
try
{
await http.PostAsync(tokenUrl + "email", new StringContent(JsonConvert.SerializeObject(email), Encoding.UTF8, "application/json"));
}
catch (Exception e)
{
return false;
}
return true;
}
}
For ConfigurationManager.AppSettings (it does not exist in .NET Core), I am planning to use the method in this link: http://www.danylkoweb.com/Blog/no-configurationmanager-in-aspnet-core-GC
However, for converting this (SendMail) method into a dependency injection, I am quite lost. I have read many examples and articles and I understand the logic of dependency injection but I don't know how to convert this static class into a proper dependency injection. There are other methods in the same Utils class but this is the simplest one and I hope to figure out the others using this one.
An approach that I was thinking off was:
public interface ISendMail
{
FormSettings ConfigSettings { get; set; }
Task<bool> SendEmail(IOptions<FormSettings> settings, Email email);
}
and:
public class SendEmail : ISendMail
{
public async static Task<bool> SendEmail(IOptions<FormSettings> settings, Email email)
{
//do same things
}
}
but I am CLEARLY lost with this because it does not even make sense. Another approach that I was thinking of was:
public class SendEmail
{
FormSettings ConfigSettings { get; set; }
protected Email email = null;
public SendEmail(IOptions<FormSettings> settings, Email email)
{
ConfigSettings = settings.Value;
this.email = email;
}
public async static Task<bool> SendEmailAction()
{
//do same things with "email" and "ConfigSettings"
}
}
I know I am giving a lot of code here and I wasn't sure if I should ask about this in "Code Review" or something. My biggest concern is not the FormSettings part but implementing the functionality of SendEmail in a dependency injection format.
Shortly, how can I convert this "SendEmail" class into a format where I can use it with .NET Core, without having a static class? This particular method does not require change with .NET Core but my other methods do, that is why I am trying to get rid of the static class approach.
I can exclude the tokenUrl and tokenKey parts and simplify the problem if requested, I am just quite lost as to how to approach this situation.
What should do this class? Sending email, right? So interface:
public interface IEmailSender
{
Task<bool> Send(Email email);
}
How we can implement it? Like this:
public class MyEmailSenderOne : IEmailSender
{
public static readonly string tokenUrl = ConfigurationManager.AppSettings["tokenUrl"];
public static readonly string tokenKey = ConfigurationManager.AppSettings["tokenKey"];
public async Task<bool> Send(Email email)
{
var http = new HttpClient();
http.DefaultRequestHeaders.Add("subscription-key", tokenKey);
try
{
await http.PostAsync(tokenUrl + "email", new StringContent(JsonConvert.SerializeObject(email), Encoding.UTF8, "application/json"));
}
catch (Exception e)
{
return false;
}
return true;
}
}
or
public class MyAnotherAwesomeEmailSender : IEmailSender
{
public async Task<bool> Send(Email email)
{
// send with different way
return true;
}
}
How we can inject this?
public class SomeClass
{
private IEmailSender _sender;
public SomeClass(IEmailSender sender)
{
_sender = sender;
}
public void Foo()
{
// do smth useful
_sender.Send(new Email());
}
}
UPD.
Because your email settings persistant (will not change during lifetime), and because this settings related ONLY to your implementation of IEMailSender, you should to inject them in your implementation. Just think about = why caller code (Controller) should know about how your implementation works?
So
public class MyEmailSenderOne : IEmailSender
{
private FormSettings _settings;
public MyEmailSenderOne(IOptions<FormSettings> settings)
{
_settings = settings.Value;
}
public async Task<bool> Send(Email email)
{
var http = new HttpClient();
http.DefaultRequestHeaders.Add("subscription-key", _settings.tokenApiKey);
try
{
await http.PostAsync(_settings.tokenApiUrl + "email", new StringContent(JsonConvert.SerializeObject(email), Encoding.UTF8, "application/json"));
}
catch (Exception e)
{
return false;
}
return true;
}
}
And, controller now dint know about any settings for your implementation, and it looks like
public class CommunicationsController : Controller
{
private IEmailSender _sender;
public CommunicationsController(IEmailSender sender)
{
_sender = sender;
}
public async Task<ActionResult> ContactUsFormSubmit(ContactUs request)
{
...
request.EmailSent = await _sender.SendEmail(new Email() { TemplateId = 3, Body = JsonConvert.SerializeObject(request) });
...
}
}
As you can see, controller is very clean now and you can easily change your implementation of IEmailSender to any other without changing Controller code. This is one of advantages of using DI.
Based on tym32167's answer, I was able to implement the IEmailSender functionality (finally). I will still choose his answer as the correct answer but this is how I implemented dependency injection.
Please read the link I provided in the question, if you'd like to know more about the IOptions and FormSettings class that I am using.
Here is the interface and the class:
public interface IEmailSender
{
Task<bool> SendEmail(Email email, FormSettings settings);
}
public class EmailSender : IEmailSender
{
FormSettings ConfigSettings { get; set; }
public async Task<bool> SendEmail(Email email, FormSettings settings)
{
var http = new HttpClient();
http.DefaultRequestHeaders.Add("subscription-key", settings.tokenApiKey);
try
{
await http.PostAsync(settings.tokenApiUrl + "email", new StringContent(JsonConvert.SerializeObject(email), Encoding.UTF8, "application/json"));
}
catch (Exception e)
{
return false;
}
return true;
}
}
In controller injection:
public class CommunicationsController : Controller
{
private IEmailSender _sender;
private FormSettings ConfigSettings { get; set; }
public CommunicationsController(IEmailSender sender, IOptions<FormSettings> settings)
{
_sender = sender;
ConfigSettings = settings.Value;
}
public async Task<ActionResult> ContactUsFormSubmit(ContactUs request)
{
...
request.EmailSent = await _sender.SendEmail(new Email() { TemplateId = 3, Body = JsonConvert.SerializeObject(request) }, ConfigSettings);
...
}
Here is FormSettings just for easy reference in case the link dies:
public class FormSettings
{
public string tokenApiUrl { get; set; }
public string tokenApiKey { get; set; }
}
I hope I didn't miss any details, so far it didn't give me any errors but since we do not have unit testing in the project, I won't be able to test immediately. Please let me know if there is something missing with the answer.

NServiceBus.IStartableBus is not registered in the container. NServiceBus 4.6.3

I am attempting a very simple application with NServiceBus and Ninject.
I am attempting to use Ninject as the container for NServiceBus, but I am getting the following error - "NServiceBus.IStartableBus is not registered in the container."
I'm sure the answer is quite obvious... just not to me!
My code is as follows
public class StartApp : IWantCustomInitialization, IWantToRunWhenBusStartsAndStops
{
private static IKernel _kernel;
public IBus Bus { get; set; }
public void Init()
{
Configure.Serialization.Json();
}
public void Start()
{
_kernel = new StandardKernel();
Configure.With()
.NinjectBuilder(_kernel)
.CreateBus()
.Start();
Bus.Send(new TestMessage {Id = Guid.NewGuid(), MessageText = "Bloop"});
}
public void Stop()
{
}
}
namespace NServiceBus_Ninject_Simple
{
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server
{ }
}
This google groups discussion is about the same issue.
It seems you are creating the configuration in the wrong place.
It should look like this:
public abstract class DefaultEndpointConfig
: IConfigureThisEndpoint
, IWantCustomInitialization
{
IWantCustomInitialization.Init()
{
Configure
.With()
.NinjectBuilder();
// + any other config;
// Call optional endpoint specific config
Init();
}
public virtual void Init()
{
}
}
See here (Johannes Gustafsson)
It needs to be done in the EndPoint-Configuration (for every endpoint, this is why he suggests using a base class) and it needs to implement IConfigureThisEndpoint.

C# WCF plugin design and implementation

I would like to get some advice. I am developing a system that will load up plugins at runtime and require them to be available through a WCF endpoint.
I will have a MVC 3 Web app that is only really used for configuration, and a class library (core) that will load up different plugins.
I would appreciate some guidance on how to go about this. I would like to load the plugin up and then be able to create a WCF endpoint that is registered with IIS 7 for access into that plugin.
Thanks in advance :)
Using a derivative of Darko's Dynamic IIS hosted WCF Service work, you can achieve something what you want. Let's start with an example service we might want to host, we'll call it an IMessageBroker, it's contract is simple:
[ServiceContract]
public interface IMessageBroker
{
[OperationContract]
string Send(string message);
}
We use this contract for both the Service, and the MEF Exports/Imports. We'll also define some additional metadata to go along with it:
public interface IMessageBrokerMetadata
{
public string Name { get; }
public string Channel { get; }
}
As it's a simple project, I'll cheat and use a simple static class for managing the MEF CompositionContainer used to compose parts:
public static class MEF
{
private static CompositionContainer container;
private static bool initialised;
public static void Initialise()
{
var catalog = new DirectoryCatalog("bin");
container = new CompositionContainer(catalog);
initialised = true;
}
public static CompositionContainer Container
{
get
{
if (!initialised) Initialise();
return container;
}
}
}
To be able to generate WCF Services dynamically, we need to create a ServiceHostFactory that can access our composition container to access our types, so you could do:
public class MEFServiceHostFactory : ServiceHostFactory
{
public override ServiceHostBase CreateServiceHost(string constructorString, System.Uri[] baseAddresses)
{
var serviceType = MEF.Container
.GetExports<IMessageBroker, IMessageBrokerMetadata>()
.Where(l => l.Metadata.Name == constructorString)
.Select(l => l.Value.GetType())
.Single();
var host = new ServiceHost(serviceType, baseAddresses);
foreach (var contract in serviceType.GetInterfaces())
{
var attr = contract.GetCustomAttributes(typeof(ServiceContractAttribute), true).FirstOrDefault();
if (attr != null)
host.AddServiceEndpoint(contract, new BasicHttpBinding(), "");
}
var metadata = host.Description.Behaviors
.OfType<ServiceMetadataBehavior>()
.FirstOrDefault();
if (metadata == null)
{
metadata = new ServiceMetadataBehavior();
metadata.HttpGetEnabled = true;
host.Description.Behaviors.Add(metadata);
}
else
{
metadata.HttpGetEnabled = true;
}
return host;
}
}
Essentially the constructorString argument is used to pass in the Metadata name we want for the specific service. Next up, we need to handle locating these services. What we now need is a VirtualPathProvider which we can use to dynamically create the instance, through a VirtualFile. The provider would look like:
public class ServiceVirtualPathProvider : VirtualPathProvider
{
private bool IsServiceCall(string virtualPath)
{
virtualPath = VirtualPathUtility.ToAppRelative(virtualPath);
return (virtualPath.ToLower().StartsWith("~/services/"));
}
public override VirtualFile GetFile(string virtualPath)
{
return IsServiceCall(virtualPath)
? new ServiceFile(virtualPath)
: Previous.GetFile(virtualPath);
}
public override bool FileExists(string virtualPath)
{
if (IsServiceCall(virtualPath))
return true;
return Previous.FileExists(virtualPath);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
return IsServiceCall(virtualPath)
? null
: Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
}
What we are doing, is mapping any calls to /Services/ to our MEF derived endpoints. The service needs a virtual file, and this is where we tie it all together:
public class ServiceFile : VirtualFile
{
public ServiceFile(string virtualPath) : base(virtualPath)
{
}
public string GetName(string virtualPath)
{
string filename = virtualPath.Substring(virtualPath.LastIndexOf("/") + 1);
filename = filename.Substring(0, filename.LastIndexOf("."));
return filename;
}
public override Stream Open()
{
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write("<%# ServiceHost Language=\"C#\" Debug=\"true\" Service=\"" + GetName(VirtualPath) +
"\" Factory=\"Core.MEFServiceHostFactory, Core\" %>");
writer.Flush();
stream.Position = 0;
return stream;
}
}
The virtual file will break out the Metadata name from the virtual path, where /Services/SampleMessageBroker.svc -> SampleMessageBroker. We then generate some markup which represents the markup of an .svc file with Service="SampleMessageBroker". This argument will be passed to the MEFServiceHostFactory where we can select out endpoints. So, given a sample endpoint:
[Export(typeof(IMessageBroker)),
ExportMetadata("Name", "SampleMessageBroker"),
ExportMetadata("Channel", "Greetings")]
public class SampleMessageBroker : IMessagerBroker
{
public string Send(string message)
{
return "Hello! " + message;
}
}
We can now access that dynamically at /Services/SampleMessageBroker.svc. What you might want to do, is provide a static service which allows you to interegate what endpoints are available, and feed that back to your consuming clients.
Oh, don't forget to wire up your virtual path provider:
HostingEnvironment.RegisterVirtualPathProvider(new ServiceVirtualPathProvider());

Categories