I have the following line in my Startup.cs file:
services.AddSingleton<IFirewallPorts>(Configuration.GetSection("FirewallPorts").Get<FirewallPorts>());
This reads data from the FirewallPorts section of my appsettings.json file and assigns that data to the FirewallPorts class.
I understand AddSingleton to be:
creates a single instance throughout the application. It creates the instance for the first time and reuses the same object in the all calls.
Now if I directly inject the FirewallPorts into a class like this, it works fine.
public class SomeClass : ISomeClass
{
private readonly IFirewallPorts _fireWallPorts;
public SomeClass(IFirewallPorts fireWallPorts)
{
_fireWallPorts = fireWallPorts;
}
But if I do this:
FirewallPorts fp = new FirewallPorts();
SomeClass sc = new SomeClass(fp);
Everything in fp is null.
Why would this be and how would I fix this?
Thanks!
Why would this be
Most probably because the default constructor of FirewallPorts doesn't do any intialization of the fields or properties.
how would I fix this?
Implement the constructor to actually initialize the object as expected, or set the properties yourself after you have created the instance:
FirewallPorts fp = new FirewallPorts() { SomeProperty = "somevalue.." };
The Configuration.GetSection.Get method does the latter for you behind the scenes, i.e. it creates and instance and set its properties according to what you specified in the configuration file.
There is no magic with Dependency Injection. When you do:
FirewallPorts fp = new FirewallPorts();
SomeClass sc = new SomeClass(fp);
You are not using any DI implementation. You're just creating the class with the default properties which in your case is null values.
Lets say for example you're using asp.net. Asp.net is using the DI infrastructure to create instances of your classes in response to http requests.
As an example you could do the same thing in your startup code if you built the service provider:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFirewallPorts>(Configuration.GetSection("FirewallPorts").Get<FirewallPorts>());
IServiceProvider provider = services.BuildServiceProvider();
IFirewallPorts ports = provider.GetRequiredService<IFirewallPorts>();
}
Your "ports" instance above would now have valid values. To state this another way, you shouldn't be manually creating IFirewallPorts instances.
Related
If I have:
public CatManager(ICatCastle catCastle, int something)
I want to set this up to be dependency injected, but I am not sure how.
I think I can do this:
services.AddScoped<ICatCastle, CatCastle>();
services.AddScoped<ICatManager>(new CatManager(???, 42));
But I am not sure what to put in as the ??? to get the CatCastle. I'd like it to resolve a new CatCastle every time CatManager is injected.
As a further step, I wonder if it possible to do something like:
public CatManager(int something)
services.AddScoped<ICatManager>(new CatManager(ResolveICatCastleIntoCatCastle().SomeID));
So that CatManager's constructor is automatically invoked with the ID, but not the object that gets the IDs. For example, if it is a database connection I want that resolution to occur when it is created and not later on when the property is actually accessed.
You can use the factory delegate overload.
Like
services.AddScoped<ICatManager>(serviceProvider =>
new CatManager(serviceProvider.GetRequiredService<ICatCastle>(), 42));
I'd like it to resolve a new CatCastle every time CatManager is injected.
If you want a new castle then you need to register CatCastle with a transient scope
services.AddTransient<ICatCastle, CatCastle>();
Regarding the further step public CatManager(int something), a similar approach can be done
services.AddScoped<ICatManager>(serviceProvider =>
new CatManager(serviceProvider.GetRequiredService<ICatCastle>().SomeID));
where the dependency is resolved and what ever action is performed before injecting it into the dependent class.
You should wrap the value 42 in a component-specific configuration class and register and inject that configuration object instead.
For instance:
public class CatSettings
{
public readonly int AnswerToAllCats;
public CatSettings(int answerToAllCats) => AnswerToAllCats = answerToAllCats;
}
public class CatManager : ICatManager
{
public CatManager(ICatCastle castle, CatSettings settings) ...
}
The configuration would then look like
services.AddScoped<ICatManager, CatManager>();
services.AddSingleton(new CatSettings(42));
I have a repository class that has a constructor with string parameter argument. It is a connection string. I created an interface for it and I'm using Unity in my UI project.
My question is, how do I set this up the 'right' way so that Unity will know how to properly construct my class in order to inject it when instantiating my controller?
I currently 'worked around' this by using a parameterless constructor for my repository but feel like this is a cop out.
Here is my repository constructor I want to use...
public CobraLettersRepository(string dbConnectionString)
{
_connString = dbConnectionString ?? throw new ArgumentNullException(dbConnectionString);
dbConnection = new SqlConnection(_connString);
dbConnection.Open();
}
I created ICobraLettersRepository and want to inject it into my controller constructor.
public CobraLetterController(ICobraLetterRepository cobraLetterRepository)
{
if (cobraLetterRepository == null)
throw new ArgumentNullException(cobraLetterRepository);
_cobraLetterRepo = cobraLetterRepository;
}
When I try this, the code compiles but I get runtime errors whenever I attempt to navigate to a part of my app where those controller methods are called.
I would say to encapsulate the Connection String inside a configuration object and put the get of the connection string inside the constructor of that configuration object.
Then just register your configuration object as other class.
public class ProjectConfiguration
{
public string ConnectionString { get; set; }
public ProjectConfiguration()
{
ConnectionString = //Get the configuration from , i.e: ConfigurationManager
}
}
And then, inject it :
public CobraLettersRepository(ProjectConfiguration configuration)
{
if(configuration == null){
throw new ArgumentNullException(configuration);
}
_connString = configuration.ConnectionString;
dbConnection = new SqlConnection(_connString);
dbConnection.Open();
}
With that you can always isolate the config from the DI container and leave the injection as simple as you can. Also, you can get the config from your config files (one per environment).
EDIT: Also check your repository constructor logic, maybe you don't want to Open the connection on the constructor. Is better to make a using statement on your class methods like :
using(SqlConnection connection = new SqlConnection(_injectedConfiguration.ConnectionString)){
connection.Open();
//Make your stuff here
}
With the using you ensure that the connection will be correctly disposed.
Note that with the configuration object approach you can just store the configuration object in a private readonly variable and use it whatever you need.
During registration use an InjectionConstructor to pass the connection string name. You need to remove all constructors except one that expects a string argument.
container.RegisterType<ICobraLetterRepository,CobraLettersRepository>(new InjectionConstructor("connectionstringname"));
Please note that it will lead to problems somewhere/sometime. You need to change the logic to create the database connection (you may refer to Breaking SOLID Principles in multiple implementation of an Interface or Resolve named registration dependency in Unity with runtime parameter).
Consider the following example:
public class CommunicationClient : IClient
{
public CommunicationClient(IServerSettings settings) { ... }
// Code
}
public class SettingsManager : ISettingsManager
{
SettingsManager(IDbSettingManager manager)
// Code
public IDictionary<string, string> GetSettings() { ... }
}
Problem:
While performing registrations (using SimpleInjector), I need to provide values that are obtained from an instance of SetingsManager and fill ServerSettings instance (concrete type for IServerSettings) but if I call GetInstance<ISettingsManager> before registering CommunicationClient, it gives me an error that I cannot do that
Error:
The container can't be changed after the first call to GetInstance, GetAllInstances and Verify.)
One solution could be to inject ISettingsManager as a dependency to CommunicationClient but I really don't want to pass it as it would provide more than required information to it.
EDIT: Container Registration
container.Register(typeof(ICommunicationClient), typeof(CommunicationClient));
ISettingsManager settingsManager = container.GetInstance<ISettingsManager>();
string url = settingsManager.GetSetting("url");
string userName = settingsManager.GetSetting("username");
string password = settingsManager.GetSetting("password");
container.Register(typeof(IServerConfiguration), () =>
new ServerConfiguration(url, userName, password);
Any suggestions/alternative solutions on how to achieve above in a cleaner way? Thanks.
Simple Injector locks the container for further changes after its first use. This is an explicit design choice, which is described here. This means that you can't call Register after you called GetInstance, but there should never be a reason to do this. Or in other words, your configuration can always be rewritten in a way that you don't need this. In your case your configuration will probably look something like this:
var settingsManager = new SettingsManager(new SqlSettingManager("connStr"));
container.RegisterSingle<ISettingsManager>(settingsManager);
container.Register<ICommunicationClient, CommunicationClient>();
string url = settingsManager.GetSetting("url");
string userName = settingsManager.GetSetting("username");
string password = settingsManager.GetSetting("password");
container.Register<IServerConfiguration>(() =>
new ServerConfiguration(url, userName, password));
There you see that SettingsManager is not built-up by the container. When using a DI container, you are not required to let the DI container build up every instance for you. Letting the container auto-wire instances for you is done to lower the maintenance burden of your Composition Root and makes it easier to apply cross-cutting concerns (using decorators for instance) to groups of related classes. In the case of the SettingsManager and SqlSettingsManager classes, it is very unlikely that their constructor will change that often that it will increase the maintenance burden of your Composition Root. It's therefore perfectly fine to manually create those instances once.
If I understand correctly, to create your CommunicationClient class, you need to pass information that are retrieved by calling a method on an instance of your ISettingsManager, but you don't want to pass the ISettingsManager as a dependency to your CommunicationClient?
One solution for that would be to create, and register, a factory that would have a dependency on ISettingsManager and that would have a CreateClient method that would return the configured client.
public class CommunicationClientFactory : ICommunicationClientFactory
{
public CommunicationClientFactory(ISettingsManager settingsManager) {...}
public CreateClient() {...}
}
This way your CommunicationClient is not dependent on the ISettingsManager and you have just this factory that does the work of creating your instance.
Edit:
An alternative, if you don't want to create a factory for this, would be to have your CommunicationClient object be created in an "invalid" state, and have a method that would set the settings and make its state valid.
Something like:
public class CommunicationClient : IClient
{
public CommunicationClient() { ... }
// Code
CommunicationClient WithSettings(IServerSettings settings) { ... }
}
Of course, then you'd have to make sure that the user don't use it when the settings have not been passed yet, potentially sending an exception if that would be the case. I like this solution less, because it's less explicit that you NEED those settings to have your object in a correct state.
I need help with this. I'm using Unity as my container and I want to inject two different instances of the same type into my constructor.
class Example
{
Example(IQueue receiveQueue, IQueue sendQueue) {}
}
....and IQueue is implemented in my MessageQueue class....
class MessageQueue : IQueue
{
MessageQueue(string path) {}
}
How can I inject two different instances of MessageQueue into my Example class? Each of the MessageQueue instances to be created with different path.
There are many ways to achieve the results you want (as evidenced by the multiple answers). Here is another way using named registrations (without attributes):
IUnityContainer container = new UnityContainer();
container.RegisterType<IQueue, MessageQueue>("ReceiveQueue",
new InjectionConstructor("receivePath"));
container.RegisterType<IQueue, MessageQueue>("SendQueue",
new InjectionConstructor("sendPath"));
container.RegisterType<Example>(
new InjectionConstructor(
new ResolvedParameter<IQueue>("ReceiveQueue"),
new ResolvedParameter<IQueue>("SendQueue")));
Example example = container.Resolve<Example>();
The downside of this approach is that if the Example constructor is changed then the registration code must also be modified to match. Also, the error would be a runtime error and not a more preferable compile time error.
You could combine the above with an InjectionFactory to invoke the constructor manually to give compile time checking:
IUnityContainer container = new UnityContainer();
container.RegisterType<IQueue, MessageQueue>("ReceiveQueue",
new InjectionConstructor("receivePath"));
container.RegisterType<IQueue, MessageQueue>("SendQueue",
new InjectionConstructor("sendPath"));
container.RegisterType<Example>(new InjectionFactory(c =>
new Example(c.Resolve<IQueue>("ReceiveQueue"),
c.Resolve<IQueue>("SendQueue"))));
Example example = container.Resolve<Example>();
If you are using a composition root then the use of the magic strings ("ReceiveQueue" and "SendQueue") would be limited to the one registration location.
Not everything has to be automatically wired by the container. You can register the Example class like this:
container.Register<Example>(new InjectionFactory(c =>
{
var receive = new MessageQueue("receivePath");
var send = new MessageQueue("sendPath");
return new Example(receive, send);
});
You could register the two instances with names:
myContainer.RegisterInstance<IQueue>("ReceiveQueue", myReceiveMessageQueue);
myContainer.RegisterInstance<IQueue>("SendQueue", mySendMessageQueue);
and then you should be able to resolve by name, but it requires using the Dependency attribute:
class Example
{
Example([Dependency("ReceiveQueue")] IQueue receiveQueue,
[Dependency("SendQueue")] IQueue sendQueue) {
}
}
or inject the unity container and then resolve the instances within the constructor:
class Example
{
Example(IUnityContainter container)
{
_receiveQueue = container.Resolve<IQueue>("ReceiveQueue");
_sendQueue = container.Resolve<IQueue>("SendQueue");
}
}
Well, don't
You should use the factory pattern in this case.
class Example
{
Example(IQueueFactory factory)
{
_sendQueue = factory.Create("MySend");
_receiveQueue = factory.Create("MyReceive");
}
}
It makes the intention a lot more clear and you can internally in the Example class handle if the queues are not found or incorrectly configured.
5 years later, but I was looking for this answer too.
I worked through it with my own code and then decided to create working code using (slightly altered) classes the OP provided.
This is an entire working example that you can copy into LINQPad (programmer's playground) and run.
Using Statement / Unity Libary
You'll need to add a reference to Microsoft.Practices.Unity.dll
You'll also need to add a using statement of :
Microsoft.Practices.Unity
In LinqPad you press F4 to add the reference and the using statement (namespace import).
void Main()
{
// Create your unity container (one-time creation)
UnityContainer uc = new UnityContainer();
// Create simple list to hold your target objects
// (makes the sample easy to follow)
List<MessageQueue> allMQs = new List<MessageQueue>();
// I'm adding TransientLifetimeManager() in order to
// explicitly ask for new object creation each time
// uc.Resolve<MessageQueue>() is called
uc.RegisterType<IQueue, MessageQueue>(new TransientLifetimeManager());
// ### override the parameters by matching the parameter name (inPath)
var item = uc.Resolve<MessageQueue>(new ParameterOverride("inPath", "extra.txt").OnType<MessageQueue>());
allMQs.Add(item);
item = uc.Resolve<MessageQueue>(new ParameterOverride("inPath", "super.txt").OnType<MessageQueue>());
allMQs.Add(item);
foreach (MessageQueue mq in allMQs){
Console.WriteLine($"mq.Path : {mq.Path}");
}
Console.WriteLine("######################\n");
uc.RegisterType<Example>(new InjectionConstructor((allMQs[0] as IQueue),(allMQs[1] as IQueue)));
// #### Create a new Example from the UnityContainer
var example1 = uc.Resolve<Example>();
// ##### Notice that the Example object uses the default values of super.txt & extra.txt
Console.WriteLine("#### example1 obj. uses default values ###########");
Console.WriteLine($"example1.receiver.Path : {example1.receiver.Path}");
Console.WriteLine($"example1.sender.Path : {example1.sender.Path}");
// ##################################################
// Override the parameters that he Example class uses.
// ### override the parameters by matching the parameter
// names (receiveQueue, sendQueue) found in the target
// class constructor (Example class)
var example2 = uc.Resolve<Example>(
new ParameterOverrides {
{"receiveQueue", new MessageQueue("newReceiveFile")},
{ "sendQueue", new MessageQueue("newSendFile")}
}.OnType<Example>());
Console.WriteLine("######################\n");
Console.WriteLine("#### example1 obj. uses ParameterOverride values ###########");
Console.WriteLine($"example2.sender.Path : {example2.sender.Path}");
Console.WriteLine($"example2.receiver.Path : {example2.receiver.Path}");
}
class Example
{
public MessageQueue receiver {get;set;}
public MessageQueue sender {get;set;}
public Example(IQueue receiveQueue, IQueue sendQueue) {
this.receiver = receiveQueue as MessageQueue;
this.sender = sendQueue as MessageQueue;
}
}
public class MessageQueue : IQueue
{
public string Path {get;set;}
public MessageQueue(string inPath) {
Path = inPath;}
}
interface IQueue{
}
Output For Examination
If you run the script above you'll see sample output which will look like the following:
mq.Path : extra.txt
mq.Path : super.txt
######################
#### example1 obj. uses default values ###########
example1.receiver.Path : extra.txt
example1.sender.Path : super.txt
######################
#### example1 obj. uses ParameterOverride values ###########
example2.sender.Path : newSendFile
example2.receiver.Path : newReceiveFile
I think this has been asked before on Stackoverflow.
You need to use ParameterOverride:
ParameterOverride enables you to pass in values for constructor parameters to override a parameter passed to a given named constructor. Only the parameter value is overridden, not the constructor.
Link to MSDN Article
Link to Stackoverflow Article
var exampleInstance = new Example();
var queue1 = unityContainer.Resolve<IQueue>(new ParameterOverrides<MessageQueue> { { "path", "yourPath" }});
var queue2 = unityContainer.Resolve<IQueue>(new ParameterOverrides<MessageQueue> { { "path", "yourPath2Queue2" }});
exampleInstance.Example(queue1,queue2);
Using vs2012, I've got a Test Unit project (for testing a Service) that incorporates an .edmx file and linq. The edmx is created at design time and I have created an object (called Store.Data.Common) that retrieves the connection string from the App.Config file (decrypts the string and builds the entire string including the meta data):
//Object is called Store.Data.Common
public static string GetConnectionString(string databaseName)
{
var security = new Security();
var connectionString = security.GetDecoded(ConfigurationManager.ConnectionStrings[databaseName+"Encrypted"].ToString(), 0);
var environment = ConfigurationManager.AppSettings["Environment"].ToString();
var dataSource = security.GetDecoded(ConfigurationManager.AppSettings[environment], 0);
connectionString = string.Format(connectionString, dataSource);
return connectionString;
}
I've also modified the .tt files to include an overload of the constructor to call this method to build the connection string, like so:
//Original Constructor which I modified and added the parameter to pass to the other constructor.
public StoreContext()
: base("name=StoreContext")
{
}
//Constructor I added:
public StoreContext(string connection)
{
Store.Data.Common.ConnectionBuilder.GetConnectionString("StoreContext");
}
Everything builds correctly, however, when I try to new-up an object for the StoreContext and leave the constructor empty, it never gets to the second constructor:
StoreContext storeContext = new StoreContext();
When I debug this test and walk through it, it only gets to the first constructor and that's it. Obviously, if I do something like this:
StoreContext storeContext = new StoreContext("Blah");
Then it goes to the second one as expected....by my question is, why doesn't the first method work when passing nothing to the constructor? Technically it should work, right?
I think you mean to use
public StoreContext()
: this("name=StoreContext")
{
}
(using this rather than base).
using this() means you're calling a constructor on the same class. When you say base() you're trying to call a constructor on the base class.
Edit: It also doesn't look like you're using the parameter you're passing into that non-default constructor. But that's another issue, not the root of your problem.