I have 2 MongoDB Databases and want to use in Worker Service class:
services.Configure<DbConnectSetting>(
hostContext.Configuration.GetSection("fwkConfiguration:DataBase1Settings"))
.AddTransient<IDbConnectSetting>(s =>
s.GetRequiredService<IOptions<DbConnectSetting>>().Value)
.AddTransient(typeof(IRepository<>), typeof(Repository<>))
.AddTransient(typeof(IDB1Repository), typeof(DB1Repository));
services.Configure<DbConnectSetting>(
hostContext.Configuration.GetSection("fwkConfiguration:DataBase2Setting"))
.AddTransient<IDbConnectSetting>(s =>
s.GetRequiredService<IOptions<DbConnectSetting>>().Value)
.AddTransient(typeof(IRepository<>),typeof(Repository<>))
.AddTransient(typeof(IDB2Repository), typeof(DB2Repository));
But the problem is it always takes the lastly create DB2 value for both the Instance of Object in worker class, is there anything to resolve to take seperate values.
Try to give the options a name. Check this docs
Something like:
services.Configure<DbConnectSetting>("DB1" ,...);
services.Configure<DbConnectSetting>("DB12 ,...);
// Usage
public Foo(IOptionsSnapshot<DbConnectSetting> options){
options.Get("DB1");
Related
Description
My app takes user input (ReadLine()) and calls its corresponding function as a result.
At the moment, it's just a switch that checks for certain commands, with their response code inside cases, but I though I ought to separate them for cleaner code.
What's the design pattern of choice here?
Attempted Solution
I could make an abstract Command class with a commandName field and a mandatory Respond() function. Then, I'd hold a List of Commands, iterate over each to check if its commandName matches what the user input, and call its Respond() function (and break the loop) if so.
Problem
That still necessitates manually creating instances of each Command and adding them to the List that holds them.
If possible, I'd like for each Command to be automatically added. I wish to instruct the program to loop over every class in a Commands/ directory and instantiate and add it on its own, or something like that.
Can I do that? If not, what's the best alternative?
You have two solutions for what you are trying to achieve:
Reflection. You can use reflection to find all the classes that extend the abstraction of command.
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Then
// use activator to create an instance and add it to list
list.Add(Activator.CreateInstance(types[0])) // etc
Use dependency injection to create the list of types, by configuring a json or other configuration file.
This varies greatly, depending on the di framework of your choice.
I'm using Hangfire v1.7.9 and I'm trying to configure a series of recurring background jobs within my MVC 5 application to automate the retrieval of external reference data into the application. I've tested this with one task and this works great, but I'd like administrators within the system to be able to configure the Attempts and DelayInSeconds attribute parameters associated with the method that is called in these background jobs.
The AutomaticRetryAttribute states that you have to use...
...a constant expression, typeof expression or an array creation expression of an attribute parameter type
... which from what I've read is typical of all Attributes. However, this means that I can't achieve my goal by setting a property value elsewhere and then referencing that in the class that contains the method I want to run.
Additionally, it doesn't look like there is any way to configure the automatic retry properties in the BackgroundJob.Enqueue or RecurringJob.AddOrUpdate methods. Lastly, I looked at whether you could utilise a specific retry count for each named Queue but alas the only properties about Hangfire queues you can set is their names in the BackgroundJobServerOptions class when the Hangfire server is initialised.
Have I exhausted every avenue here? The only other thing I can think of is to create my own implementation of the AutomaticRetryAttribute and set the values at compile time by using an int enum, though that in itself would create an issue in the sense that I would need to provide a defined list of each of the values that a user would need to select. Since I wanted the number of retries to be configurable from 5 minutes all the way up to 1440 minutes (24 hours), I really don't want a huge, lumbering enum : int with every available value. Has anyone ever encountered this issue or is this something I should submit as a request on the Hangfire GitHub?
I would take the approach of making a custom attribute that decorates AutomaticRetryAttribute:
public class MyCustomRetryAttribute : JobFilterAttribute, IElectStateFilter, IApplyStateFilter
{
public void OnStateElection(ElectStateContext context)
{
GetAutomaticRetryAttribute().OnStateElection(context);
}
public void OnStateApplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
GetAutomaticRetryAttribute().OnStateApplied(context, transaction);
}
public void OnStateUnapplied(ApplyStateContext context, IWriteOnlyTransaction transaction)
{
GetAutomaticRetryAttribute().OnStateUnapplied(context, transaction);
}
private AutomaticRetryAttribute GetAutomaticRetryAttribute()
{
// Somehow instantiate AutomaticRetryAttribute with dynamically fetched/set `Attempts` value
return new AutomaticRetryAttribute { Attempts = /**/ };
}
}
Edit: To clarify, this method allows you to reuse AutomaticRetryAttribute's logic, without duplicating it. However, if you need to change more aspects on per-job basis, you may need to duplicate the logic inside your own attribute.
Also, you can use context.GetJobParameter<T> to store arbitrary data on per-job basis
Is it possible to register a single service that has dependencies that can change depending on a setting?
For instance
A DBExecutor requries a different DBconnection object depending which geographical region it is running under.
I've tried something like
builder.RegisterType<DbConnection>().Named<IDbConnection>("US")
builder.RegisterType<DbConnection>().Named<IDbConnection>("AU")
builder.RegisterType<SqlExecutor>().As<IDbExecutor>();
and I'd like to resolve the service with something like
var au = container.ResolveNamed<IDbExecutor>("AU");
var us = container.ResolveNamed<IDbExecutor>("US");
However this doesn't work because the IDbExecutor itself hasn't been registered with a key, and if I try a normal Resolve it wont work as it cannot create the dependent services.
Basically I just want an instance of of IDbExecutor with a DBConnection based upon a certain parameter.
I'm trying to do this in a more general sense so I'm trying to avoid any specific code where I can.
The current generic code I have that doesn't use keyed services looks like
var job = (IJob) lifetimeScope.Resolve(bundle.JobDetail.JobType);
where JobType is a class Type and depending on if this is possible the final version would look something like
var job = (IJob) lifetimeScope.Resolve(bundle.JobDetail.JobType, bundle.JobDetail.JobDataMap["Region"]);
where bundle.JobDetail.JobDataMap["Region"] would return either "AU" or "US"
You won't be able to rig it to resolve a named IDbExecutor because you didn't register it as named. It's also probably not the best idea since it implies that IDbExecutor somehow "knows" about its dependencies, which it shouldn't - the implementation knows, but the interface/service doesn't - and shouldn't.
You can get something close to what you want by updating the SqlExecutor to use the IIndex<X,B> relationship in Autofac. Instead of taking just an IDbConnection in your constructor, take an IIndex<string,IDbConnection>.
When you need to get the connection, look it up from the indexed dictionary using the job type:
public class SqlExecutor
{
private IIndex<string, IDbConnection> _connections;
public SqlExecutor(IIndex<string, IDbConnection> connections)
{
this._connections = connections;
}
public void DoWork(string jobType)
{
var connection = this._connections[jobType];
// do something with the connection
}
}
Another way to do it would be to create a delegate factory for the SqlExecutor that takes in the job type and automatically picks the right named service. That's a bit more involved so check out the documentation for an example.
I need to access my business layer object 4 times with different constructor.
Specifically I need to access 4 different back end systems through my separate Data Access Layer
What should i do:
1) Instantiate 4 separate objects with different constructor?
2) Instantiate one object and change the public property every time?
As i am now in my HomeController i have the following:
var obj = new BarcodeBLL(new ERPConfig
{
AS400ControlLibrary = ConfigurationManager.AppSettings["ControlLibrary"],
AS400Library = ConfigurationManager.AppSettings["DataLibrary"],
ConnectionString = ConfigurationManager.ConnectionStrings["AS400"].ConnectionString
});
To me it would seem obvious to follow #2 but i would like to know if i am correct and why
If you have 4 identical systems, it would seem logical to have a single class representing such systems. When you need access to one of these systems, you instantiate this type, passing the correct connection string to the constructor.
You may want to hide the details of which connection string is actually being used behind a factory or in the configuration of a DI container.
I am trying to create an index agent service for a multi-instance Solr install using SolrNet. I have created the service, which will use an interface to create multiple agents to index with. These agents are specified in an external configuration file and instantiated dynamically. There can be 0-n of each agent type, for instance (note the url differences):
PersonAgent http://localhost:8080/solr
ProductAgent http://localhost:8080/solr
ProductAgent http://localhost:9999/solr
This of course needs to map to something like this:
ISolrOperations<Person>
ISolrOperations<Product>
ISolrOperations<Product>
Based on my needs and the fact that SolrNet does not support multiple instances for its default container, I am trying to use Castle Windsor for this. According to the SolrNet wiki at http://code.google.com/p/solrnet/wiki/MultiCoreAccess this is pretty straightforward.
var solrFacility = new SolrNetFacility("http://localhost:8983/solr/defaultCore");
solrFacility.AddCore("core0-id", typeof(Product), "http://localhost:8983/solr/product");
solrFacility.AddCore("core1-id", typeof(Product), "http://localhost:8983/solr/product2");
solrFacility.AddCore(typeof(Person), "http://localhost:8983/solr/person"); // no need to set an explicit ID since it's the only core for Person
container.AddFacility("solr", solrFacility);
ISolrOperations<Person> solrPerson = container.Resolve<ISolrOperations<Person>>();
ISolrOperations<Product> solrProduct1 = container.Resolve<ISolrOperations<Product>>("core0-id"); // use proper Windsor service overrides instead of resolving like this
ISolrOperations<Product> solrProduct2 = container.Resolve<ISolrOperations<Product>>("core1-id");
I'm not completely lost with the idea of IoC, but I am unsure what the wiki author meant with the comment to "use proper Windsor service overrides instead of resolving like this" as stated in the code sample. Obviously the example explicitly identifies the core via an id, but is there a better/more flexible way?
What I meant is that you normally don't resolve ISolrOperations<T> directly from the container.
Instead, you use service overrides or other Windsor mechanisms to define which ISolrOperations<T> component (which core) to pass to other components, especially when you have multiple cores with the same document type, e.g. in this example there are two components registered under the service type ISolrOperations<Product>.