.Net core Dependency injection - with parameters - c#

NOTE: This example has been simplified
I have got a Client's Contact table and wanted to retrieve specific client contact information from DB. The code I typed belove brings me all contact details. I wanted to use a parameter to only bring me specific client contacts.
I used IClientContactRepository interface like this
public interface IClientContactRepository
{
IQueryable<ClientContactModel> ClientContacts { get; }
}
And i used this class to retrive data from database with dapper
public class ClientContactRepository : IClientContactRepository
{
private readonly IConfiguration configuration;
private List<ClientContactModel> ClientContactList {get;set;}
public ClientContactRepository(IConfiguration config)
{
configuration = config;
SqlConnection conn = new SqlConnection(configuration["ConnectionString"]);
using (var connection = conn)
{
ClientContactList = connection.Query<ClientContactModel>("Select * FROM ContactTable ").ToList();
}
}
public IQueryable<ClientContactModel> ClientContacts => ClientContactList;
}
In my Startup class
services.AddTransient<IClientContactRepository, ClientContactRepository>();
My QUESTION is: can I pass the client's id parameter to the constructor.
I tried this: add a parameter to the constructor
public ClientContactRepository(IConfiguration config, int clientId)
and tried to start up class.
services.AddTransient<IClientContactRepository, ClientContactRepository(int,i)>()
Didn't work....
Can someone help me how to pass parameter please?

Yes, but where are you getting the client ID from - is it a configured value that will be static for the lifetime of the application? If so, you can use the AddTansient method overload that accepts a factory delegate to create the objects.
The better way (will cover all use cases) is registering the type that can provide that information (create one if no such type exists) with the DI container and use that as a parameter in the constructor of your repo.
As an example, let’s say you get your client ID from a claim, so the type you need to inject is IPrincipal:
services.AddScoped<IPrincipal>(
provider => provider.GetService<IHttpContextAccessor>()
.HttpContext
.User);
You would then inject the IPrincipal into your repo constructor and retrieve the client ID. An even better way would be to create your own type “ClientIdAccessor” which is responsible for providing the client ID. You would then not have a dependency on IPrincipal when testing your repo and the implementation of this new type would only depend on external libraries for your asp.net core implementation.
Side note: are you certain you want to use AddTransient for your repo? Usually you’d want to use the same repo object for the lifetime of the request (I.e. AddScoped).

Related

Dependency Injection & connection strings / Multiple instances of a singleton

I have a Web Api project which relies heavily on Azure Cosmos DB. Until now, having one Cosmos DB account (one connection string) was sufficient. Now a new requirement is to be able to connect to a different Cosmos (two connection strings) depending on an incoming parameter.
For customerId X we should fetch documents from Cosmos DB 1 and for another customer Y we have to look in Cosmos DB 2.
Until now my Startup.cs file registered a singleton instance of CosmosClient. Which in turn gets instantiated like this
cosmosClient = new CosmosClient(endpointUrl, primaryKey);
And this worked really well. The Web Api was easily able to process all requests. But now that we have to new up a CosmosClient per request, performance is really bad.
So my question is; Is there a way to have multiple instances of the same singleton? As in; can we create a single instance of the combination Class+EndPointUrl? (Would that still be a singleton?)
Right now, we are newing up thousands of CosmosClients every minute. And we really need just one more compared to what we had earlier.
There's multiple ways to do this, but an easy implementation would be to create a wrapper around each CosmosClient you use. The only use of the wrapper will be to allow you to use various instances of the CosmosClient and differentiate them by their types.
//Create your own class for each client inheriting the behaviour of CosmosClient
public class ContosoCosmosClient : CosmosClient
{
public ContosoCosmosClient(string connectionString, CosmosClientOptions clientOptions = null) : base(connectionString, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions = null) : base(accountEndpoint, authKeyOrResourceToken, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions = null) : base(accountEndpoint, tokenCredential, clientOptions)
{
}
}
//In Startup.up add a Singleton for each client
services.AddSingleton(new ContosoCosmosClient(...));
services.AddSingleton(new FabrikamCosmosClient(...));
Then in your business logic you can add both clients and depending on your logic choose which client you want to use:
public class MyService
{
public MyService(ContosoCosmosClient contosoClient, FabrikamCosmosClient fabrikamClient)
{
//...
}
}
Thanks for all comments and answers.
In the end, is this case, the best solution was the approach that was suggested by Mr. T. https://devblogs.microsoft.com/cosmosdb/httpclientfactory-cosmos-db-net-sdk/
I'm now still using one CosmosClient, Scoped. Which allows dynamic use of endpoints.
By injecting the IHttpClientFactory and setting the CosmosClientOptions like this;
{
HttpClientFactory = () => _httpClientFactory.CreateClient("cosmos")
});
we are now making full use of the HttpClient and its ability to reuse ports.

access appsetting from data layer without creating instantiation with parameter

How can i access my "appsettings.js" values in Business/Data layer without creating instantiation in the constructor level.
I can access all values in the controller but i don't want to send to all my layers like passing constructor parameter.
I am trying to understand this post but i don't understand fully. can some one provide me some sample code with out creating instantiation
ASP.NET 5 DI app setting outside controller
Controller - Services - DBServices (without parameter constructor?)
appsetting.json
"DbSettings":{
"ConnectionString" : "TESTING Connection string here"
}
Controller:
public class TestController : ControllerBase
{
public TestController(IOptions<DbSettings> dbSettings)
{
_balService = new BALServices(dbSettings.Value); // passing parameter "dbsetting" to constructor which i don't want.
}
}
Startup.cs
services.Configure<DbSettings>(Configuration.GetSection("DbSettings"));
services.AddSingleton<IConfiguration>(Configuration);
Dbsettings.cs
public class DbSettings
{
public string ConnectionString { get; set; }
}
The framework isn’t really designed to allow you to do that. ASP.NET Core uses dependency injection and kind of forces you to follow it, since pretty much everything is inaccessible outside of the DI container. So whenever something depends on something, then it should make that dependency clear by expecting it in the constructor. That is the way it is designed.
That being said, you creating a new instance of BALServices isn’t really in the spirit of dependency injection either. If you want to use BALServices in the controller, then instead of creating an instance of it itself, the controller should just depend on that type.
So you would change the controller to look like this:
public class TestController : ControllerBase
{
private readonly BALServices _balService;
public TestController(BALServices balService)
{
_balService = balService;
}
}
Now, the controller does not need to worry about how it could possibly create that object. It just depends on it being there and letting someone else figure that out. And that’s exactly what dependency injection is about.
In order to make that work, of course you now need to adjust your BALServices to depend on those IOptions<DbSettings> instead:
public class BALServices
{
private readonly DbSettings _dbSettings;
public BALServices(IOptions<DbSettings> dbSettings)
{
_dbSettings = dbSettings.Value;
}
}
And then you only need to register this service in your Startup:
services.AddScoped<BALServices>();
And now you have TestController depend on the actual service it wants to use, and BALServices depend on the configuration it requires. And the DI container will automatically provide you with what you need.

Microsoft.Extensions.Options Do you have to keep passing it through the full stack manually

I'm implementing appsettings.json in place of app.config for the first time so please excuse the potentially stupid question to which I have not been able to find a satisfactory solution in my research.
I have a solution fronted by a .Net Core 2.0 Web API with dependent projects breaking my solution up into layers of class libraries. I need to get to the connection string stored in my top layer appsettings.json (under my Web API) from the bottom persistence layer class library.
I found this article explaining it step by step. and finally got it to work.
Note: I tested this functionality with the connectionString but I need other variables as well which I was planning to do later.
My question is that once I implemented the required constructor:
public Data(IOptions<ConnectionStrings> connectionStrings)
{
ConnectionStrings = connectionStrings;
}
I have to manually pass the IOptions object all the way through the stack.
Data date = new Data(ConnectionStrings);
Is there no solution similar to what ConfigurationManager gave you that does not require me to pass the IOptions object all the way through?
Surely I'm doing something wrong, no?
I had a similar concern when I was building my first dotnet core 2 application. The solution I came up with was to configure dependency injection to resolve T as IOptions<T>.Value, for example:
services.AddTransient<SomeOptions>(sp =>
sp.GetService<IOptions<SomeOptions>>().Value);
This works well if you are using dependency injection for objects that require SomeOptions to be supplied in the constructor. Doesn't really provide much value if you are manually "newing" up objects.
I'm not entirely sure what your application looks like, but from your example above you have a Data class which takes an IOptions<ConnectionStrings> parameter in the constructor.
Given the following code in your startup:
// I don't have your entire project - just looking at your link above, I came up with this
services.Configure<ConnectionStrings>
(Configuration.GetSection("ConnectionStrings"));
services.AddTransient<ConnectionStrings>(sp =>
sp.GetService<IOptions<ConnectionStrings>>().Value);
services.AddTransient<Data>();
You could have your Data class defined as such:
public class Data
{
private readonly ConnectionStrings _connectionStrings;
public Data(ConnectionStrings connectionStrings)
{
//I don't know what you need to do with this here - just guessing
_connectionStrings = connectionStrings;
}
}
You could have your controller class defined as such:
public class SomeController
{
private readonly Data _data;
public SomeController(Data data)
{
_data = data;
}
public IActionResult Get()
{
// do something with _data here
// don't new it up - it gets injected!
}
...
}

Injecting runtime value into Unity dependency resolver

I am working on a webapi project and using Unity as our IOC container. I have a set of layered dependencies something like the following:
unityContainer.RegisterType<BaseProvider, CaseProvider>(new HierarchicalLifetimeManager());
unityContainer.RegisterType<IRulesEngine, RulesEngine>();
unityContainer.RegisterType<IQuestionController, QuestionController>();
unityContainer.RegisterType<IAPIThing, WebAPIThing>();
Now the constructor for BaseProvider accepts an int as a parameter which is the Case identifier. WebAPIThing takes a BaseProvider in its constructor. Normally in a non web scenario I would inject the case id using something like:
public static IAPIThing GetIAPIThing(int caseId)
{
return CreateUnityContainer().Resolve<IAPIThing >(new ParameterOverride("caseId", caseId).OnType<CaseProvider>());
}
But that only works when I explicitly call that method. In a Web API scenario I am using a
config.DependencyResolver = new UnityDependencyResolver(unityContainer); to resolve my api controllers.
I would guess I will still need to influence how the DependencyResolver resolves that BaseProvider object at runtime.
Anyone had to do something similar?
EDIT 1
I have tried using the following which appears to work:
unityContainer.RegisterType<BaseProvider>(
new HierarchicalLifetimeManager()
, new InjectionFactory(x =>
new CaseProvider(SessionManager.GetCaseID())));
You are trying to inject a runtime value (the case id) into the object graph, which means you are complicating configuration, building, and verification of the object graph.
What you should do is promote that primitive value to its own abstraction. This might sound silly at first, but such abstraction will do a much better job in describing its functionality. In your case for instance, the abstraction should probably be named ICaseContext:
public interface ICaseContext
{
int CurrentCaseId { get; }
}
By hiding the int behind this abstraction we effectively:
Made the role of this int very explicit.
Removed any redundancy with any other values of type int that your application might need.
Delayed the resolving of this int till after the object graph has been built.
You can define this ICaseContext in a core layer of your application and everybody can depend on it. In your Web API project you can define a Web API-specific implementation of this ICaseContext abstraction. For instance:
public class WebApiCaseContext : ICaseContext
{
public int CurrentCaseId
{
get { return (int)HttpContext.Current.Session["CaseId"];
}
}
This implementation can be registered as follows:
unityContainer.RegisterType<ICaseContext, WebApiCaseContext>();
UPDATE
Do note that your own new CaseProvider(SessionManager.GetCaseID()) configuration does not solve all problems, because this means that there must be a session available when verifying the object graph, which will neither be the case during application startup and inside a unit/integration test.

Unity -- using information from request to resolve dependencies

I've recently refactored my MVC application to use Unity dependency injection to resolve dependencies, which is great. It's much more decomposable, etc., etc.
What I'm doing now is adding the capability for multiple tenants to use it. The approach I'm using (so that the rest of the code doesn't have to know much about the tenants) is creating things like a tenant-filtered version of my repository interface (which is just a proxy for another repository... so it will call one of the underlying methods, then check if the record has the right tenant and behave accordingly). This lets me basically emulate having a totally separate store for each tenant even though under the hood the data is not segregated, so relatively little of the client code needs to change.
The problem with all of this is how it fits into the DI way of doing things. What I'm planning to do is, at the beginning of the request, detect the host name, then use that to determine the tenant (each tenant will have a list of hostnames in the DB). Although I'm using per-request lifetimes for most objects Unity is constructing and resolving I don't really get how Unity can "know" what tenant to use since it would need both the data about the request (which I suppose the controller will have, but I don't think is available in my container configuration method) and access to the database to know which host (and it hardly seems desirable to have my container configuration making database calls). I can solve #2 by only passing in a host name and making the classes with tenants go figure out which tenant is being referenced, but that doesn't help with #1.
Right now I'm using "property injection" (also known as "a public property" in less high-falutin' circles), but I don't see how I'm going to avoid having my controller be the one that actually feeds the tenant data in, so now I don't really have just the one composition root controlling everything.
Is there a way I can do this in the composition root, or should I just resign myself to having the controller do this work?
For some reason you seem to forget about injection factories. Registering interface/type against a factory lets you execute arbitrarily complicated code upon resolving, including consulting the request, tenant database, whatever.
container.RegisterType<IRepository>(
new InjectionFactory(
c => {
// whatever, consult the database
// whatever, consult the url
return ...;
} );
The factory composition is transparent so that whenever you need it, the target doesn't even know that the factory code has been executed rather than a type instance from simple mapping.
Somewhere it needs to make a database call. Maybe the simplest place would be in global.ascx if it's needed system wide.
private static ConcurrentDictionary<string, string> _tenantCache = new ConcurrentDictionary<string, string>();
protected virtual void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
var tenantId = _tenantCache.GetOrAdd(app.Context.Request.Url.Host, host =>
{
// Make database call in this class
var tenant = new TenantResolver();
return tenant.GetTenantId(host);
})
app.Context.Items["TenantID"] = tenantId ;
}
You will want to cache the result as Application_BeginRequest is called alot. You can then configure Unity to have child containers. Put all the common/default mappings in the parent container then create a child container per tenant and register the correct implementation for each tenant in it's own child container.
Then implement IDependencyResolver to return the correct child container.
public class TenantDependencyResolver : IDependencyResolver
{
private static IUnityContainer _parentContainer;
private static IDictionary<string, IUnityContainer> _childContainers = new Dictionary<string, IUnityContainer>();
public TenantDependencyResolver()
{
var fakeTenentID = "localhost";
var fakeTenentContainer = _parentContainer.CreateChildContainer();
// register any specific fakeTenent Interfaces to classes here
//Add the child container to the dictionary for use later
_childContainers[fakeTenentID] = fakeTenentContainer;
}
private IUnityContainer GetContainer()
{
var tenantID = HttpContext.Current.Items["TenantID"].ToString();
if (_childContainers.ContainsKey(tenantID)
{
return _childContainers[tenantID];
}
return _parentContainer;
}
public object GetService(Type serviceType)
{
var container = GetContainer();
return container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
var container = GetContainer();
return container.ResolveAll(serviceType);
}
}
Then set ASP.NET MVC DependecyResolver to be the TenantDependencyResolver. I didn't run this code but it should give you an idea of what you would need to do. If your implementations are set then you might be able to do it in the static constructor of TenantDependecyResolver.

Categories

Resources