Castle windsor: how to pass arguments to deep dependencies? - castle-windsor

I have the following dependency chain:
IUserAppService
IUserDomainService
IUserRepository
IUserDataContext - UserDataContextImpl(string conn)
All interfaces above and implementations are registered in a Windsor Castle container. When I use one connection string, everything works fine.
Now we want to support multiple databases, In UserAppServiceImpl.cs, we want to get different IUserRepository (different IUserDatabaseContext) according to userId as below:
// UserAppServiceImpl.cs
public UserInfo GetUserInfo(long userId)
{
var connStr = userId % 2 == 0 ? "conn1" : "conn2";
//var repo = container.Resolve<IUserRepository>(....)
}
How can I pass the argument connStr to UserDataContextImpl?

Since the connection string is runtime data in your case, it should not be injected directly into the constructor of your components, as explained here. Since however the connection string is contextual data, it would be awkward to pass it along all public methods in your object graph.
Instead, you should hide it behind an abstraction that allows you to retrieve the proper value for the current request. For instance:
public interface ISqlConnectionFactory
{
SqlConnection Open();
}
An implementation of the ISqlConnectionFactory itself could depend on a dependency that allows retrieving the current user id:
public interface IUserContext
{
int UserId { get; }
}
Such connection factory might therefore look like this:
public class SqlConnectionFactory : ISqlConnectionFactory
{
private readonly IUserContext userContext;
private readonly string con1;
private readonly string con2;
public SqlConnectionFactory(IUserContext userContext,
string con1, string con2) {
...
}
public SqlConnection Open() {
var connStr = userContext.UserId % 2 == 0 ? "conn1" : "conn2";
var con = new SqlConnection(connStr);
con.Open();
return con;
}
}
This leaves us with an IUserContext implementation. Such implementation will depend on the type of application we are building. For ASP.NET it might look like this:
public class AspNetUserContext : IUserContext
{
public string UserId => int.Parse(HttpContext.Current.Session["UserId"]);
}

You have to start from the beginning of your dependency resolver and resolve all of your derived dependencies to a "named" resolution.
Github code link:https://github.com/castleproject/Windsor/blob/master/docs/inline-dependencies.md
Example:
I have my IDataContext for MSSQL and another for MySQL.
This example is in Unity, but I am sure Windsor can do this.
container.RegisterType(Of IDataContextAsync, dbEntities)("db", New InjectionConstructor())
container.RegisterType(Of IUnitOfWorkAsync, UnitOfWork)("UnitOfWork", New InjectionConstructor(New ResolvedParameter(Of IDataContextAsync)("db")))
'Exceptions example
container.RegisterType(Of IRepositoryAsync(Of Exception), Repository(Of Exception))("iExceptionRepository",
New InjectionConstructor(New ResolvedParameter(Of IDataContextAsync)("db"),
New ResolvedParameter(Of IUnitOfWorkAsync)("UnitOfWork")))
sql container
container.RegisterType(Of IDataContextAsync, DataMart)(New HierarchicalLifetimeManager)
container.RegisterType(Of IUnitOfWorkAsync, UnitOfWork)(New HierarchicalLifetimeManager)
'brands
container.RegisterType(Of IRepositoryAsync(Of Brand), Repository(Of Brand))
controller code:
No changes required at the controller level.
results:
I can now have my MSSQL context do its work and MySQL do its work without any developer having to understand my container configuration. The developer simply consumes the correct service and everything is implemented.

Related

Implementing with both Adapter Design Pattern and Facade Design pattern

I'm new to design patterns.
I'm implementing a tool which can connect to different databases as user need.
this is my code structure.
in controllers I have my API calls. Below I paste post APi call for get all databases in server
#PostMapping("/allDatabases")
public List<String> getDatabases(#RequestBody DatabaseModel db)
throws IOException, SQLException {
return migrationInterface.getAllDatabases(db);
}
for now I'm getting response by calling a method in interface inside service package.
But when database server is change(ex: postgres,mysql) I have to use different queries.
Ex:
public class PostgresPreparedStatements {
public PreparedStatement getAllDbs(Connection con) throws SQLException {
return con.prepareStatement(
"SELECT datname FROM pg_database
WHERE datistemplate = false;");
}
}
This query is not working in MySQL database. So I'll keep deferent prepared statements for deferent databases. My idea is calling to a BaseAdapter from controller and check server type like below.
public class BaseAdapter {
public void checkServerType(String server) {
switch(server) {
case "postgres" :
// postgres functions
break;
case "mysql" :
// mysql functions
break;
default:
break;
}
}
}
I want to call PostgresConnector.java if server is postgres. from Connector I want to call Facade to call functions and related queries.
Any idea how to do this?
please note: For now I'm implementing this for postgres and MySQL,but in future this should work with any database.
Adapter pattern is not used when you want to add new behaviour such as new databases in your case. The goal of adapter class is to allow other class to access the existing functionality. Adapter converts the interface of one class into something that may be used by another class.
It looks like BaseAdapter has a responsibility to choose SQL statement for different databases. We can paraphraze this responsibility like we want to have generated SQL query based on database. So it looks like
we can replace this switch statement with HashTable(Java) or Dictionary(C#). And this HashTable(Java) or Dictionary(C#) can be a simple factory that creates SQL queries. And our generated SQL queries can be strategies for concrete database.
So let's dive in code.
It looks like this is a place where Strategy pattern can be used:
Strategy pattern is a behavioral software design pattern that enables
selecting an algorithm at runtime. Instead of implementing a single
algorithm directly, code receives run-time instructions as to which in
a family of algorithms to use.
Let me show an example via C#. I am sorry I am not Java guy, however I provided comments about how code could look in Java.
We need to have some common behaviour that will be shared across all strategies. In our case, it would be just one GetAllDbs() method from different data providers:
public interface IDatabaseStatement
{
IEnumerable<string> GetAllDbs();
}
And its concrete implementations. These are exchangeable strategies:
public class PostgresDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new [] { "PostgresDatabaseStatement" };
}
}
public class MySQLDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new[] { "MySQLDatabaseStatement" };
}
}
public class SqlServerDatabaseStatement : IDatabaseStatement // implements in Java
{
public IEnumerable<string> GetAllDbs()
{
return new[] { "SqlServerDatabaseStatement" };
}
}
We need a place where all strategies can be stored. And we should be able to get necessary strategy from this store. So this is a place where simple factory can be used. Simple factory is not Factory method pattern and not Abstract factory.
public enum DatabaseName
{
SqlServer, Postgres, MySql
}
public class DatabaseStatementFactory
{
private Dictionary<DatabaseName, IDatabaseStatement> _statementByDatabaseName
= new Dictionary<DatabaseName, IDatabaseStatement>()
{
{ DatabaseName.SqlServer, new SqlServerDatabaseStatement() },
{ DatabaseName.Postgres, new PostgresDatabaseStatement() },
{ DatabaseName.MySql, new MySQLDatabaseStatement() },
};
public IDatabaseStatement GetInstanceByType(DatabaseName databaseName) =>
_statementByDatabaseName[databaseName];
}
and then you can get instance of desired storage easier:
DatabaseStatementFactory databaseStatementFactory = new();
IDatabaseStatement databaseStatement = databaseStatementFactory
.GetInstanceByType(DatabaseName.MySql);
IEnumerable<string> allDatabases = databaseStatement.GetAllDbs(); // OUTPUT:
// MySQLDatabaseStatement
This design is compliant with the open/closed principle.

.NET Core 2.1 - Accessing Config/usermanager in a static helper

I've recently moved from MVC5 over to .NET Core 2.1 (MVC). Can anyone help me with this please.
I have my ApplicationUser and I've extended the model/table to store the user's FirstName.
In the View, I want to be able to output the current user firstname value.
User in the view is a ClaimsPrincipal so I need to go off to the DB to grab the value I need or access UserManager to get it.
Now, I know I can get that in the controller but I don't want to have to create a JQuery call to grab it every time I need it.
What I do want is to be able to access it server side, ideally via a static helper class.
In the MVC5 I'd have a helper to do the job no problem. Something like this for example:
public static string GetCurrentUserFirstName()
{
string _usrRef = HttpContext.Current.User.Identity.GetUserId();
var user = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(_usrRef);
return user.FirstName;
}
However, .NET Core doesn't work that way.
In a controller I could say:
var user = await _userManager.GetUserAsync(User);
string firstName = user.FirstName;
or I could go off to the DB via a call using Dapper w/ my connection string.
I can't inject the UserManager or ConnectionStrings into the helper via the constructor as it is static.
Is there a way to access either of those in this static helper?
It's the little changes that get you the most!
Thanks to #Kirk Larkin - I've found the solution.
I have to admit, it feels a little more convoluted having to pass things around to gain access to them but this is a good, working solution.
The View:
#using Microsoft.AspNetCore.Identity
#using MyApplication.Helpers
#inject UserManager<ApplicationUser> UserManager
<div>
#await MyHelper.GetLoggedInUserFirstName(UserManager, User)
</div>
The MyHelper file:
public static async Task<string> GetLoggedInUserFirstName(UserManager<ApplicationUser> userManager, ClaimsPrincipal user)
{
string output = "";
try
{
var currentUser = await userManager.GetUserAsync(user);
if(currentUser!=null)
{
output = currentUser.FirstName ?? currentUser.Email;
}
}
catch(Exception e) { }
return output;
}

Changing database type at runtime using EntityFramework

Is it possible to change database type at runtime? If yes, how it can be done? I am using EntityFramework 6.
Background about the question:
I have an application that initially does not have database access. A user first has to go through "installation" process and provide information about the database(including database type eg. MySql or MsSql).
I would like to avoid having 2 contexts if possible. If necessary I can provide more details.
You can specify the connection string at runtime using the following...
DbContext has a constructor that can be overloaded with the name of the connection string, or the connection string itself.
public partial class EntityName: DbContext {
public EntityName(): base("name=EntityName") {}
public EntityName(string connectionString): base(connectionString) {}
}
var connString = "PopulateConnString";
Using (var ctx = new EntityName(EntityConnectionStringBuilder)
{
// Do stuff
}

Automapper map to existing object stack overflow exception

i'm coding a restService who can update some datas in a database via Nhibernate.
The service receive DTO objects from a client.
I'm using Automapper to map my Dto to NhibernateObject.
The problem is my DTO class reference itself. here an example :
public class UserDto
{
public String Name{get;set;}
public string Lastname{get;set;}
public UserDto UserOwner{get;set;}
}
here's my BusinessClass
public class User
{
public String Name{get;set;}
public string Lastname{get;set;}
public String Adress{get;set;}
public User UserOwner{get;set;}
}
Sometimes User object and UserOwner properties references the same object.
So when i do that
User usr = Automapper.Mapper.Map<UserDto,User>(myUserDtoObject); // this works fine
but when i do
Automapper.Mapper.Map(myUserdtoObject,MyUserNhibernateObject); // i've got a stackoverflowexception
I can use the first option but if i do that, when my new UserEntity returned by Map function is created the value of "Adress" properties is not set (UserDto does not contains it).
You need to use MaxDepth - AutoMapper doesn't know how far to go down your rabbit hole.
ForMember(dest => dest.UserOwner, opt => opt.MaxDepth(1))
This is important for NHibernate, which uses proxy objects to load indefinitely. The other option is to ignore the UserOwner member, but that's likely not your intent here.

UNITY: passing in a new datacontext each time?

I am trying to use unity to automatically inject a datacontext on my repository using a new instance each time.., my idea is the ensure that each time a new datacontext is injected
Currently its failing on creating the repository, i think it can't resolve MyDataContext
Before creating a constructor on "the repository" (see below) to take in the DataContext on my repository everything worked but now its failing..
I currently have this setup in my unity container which i create in global.asax, i have also registered the type MyDataContext which is standard DataContext
container = new UnityContainer();
Container.RegisterType<MyDataContext, MyDataContext>()
.RegisterType<IOfficeRepository, OfficeRepository>()
.RegisterType<IOfficeService, OfficeService>();
basically i have a service that calls the repository like so
public class OfficeService : IOfficeService
{
IOfficeRepository repository = null;
public OfficeService(IOfficeRepository repository)
{
this.repository = repository;
if (this.repository == null)
throw new InvalidOperationException("Repository cannot be null");
}
here is my repository
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db;
public OfficeRepository (MyDataContext dataContext)
{
this.db = dataContext;
}
EDIT
I almost forgot i am doing this to create the service
officeService = Bootstrapper.Container.Resolve<IOfficeService>();
EDIT - THE ERROR BEING GENERATED
Resolution of the dependency failed, type = "MarkSmith.IOfficeService", name = "".
Exception message is: The current build operation (build key Build
Key[MarkSmith.OfficeService, null]) failed: The parameter repository could not be
resolved when attempting to call constructor
MarkSmith.OfficeService(MarkSmith.IOfficeRepository repository). (Strategy type BuildPlanStrategy, index 3)
EDIT - REMOVING Constructor on repository works
It is something to do with the datacontext because if i remove the constrcutor on the repository that takes a DataContext then all works, but of course i need it to accept a DataContext to be able to inject a "NEW" datacontext each time
public class OfficeRepository : IOfficeRepository
{
private MyDataContext db new MyDataContext(); // CHANGE
//public OfficeRepository (MyDataContext dataContext)
//{
//this.db = dataContext;
//}
EDIT - ACTUAL ERROR
After digging deeper i have found this error ....
The type MyDataContext has multiple constructors of length 2.
Unable to disambiguate. (Strategy type DynamicMethodConstructorStrategy, index 0)
(Strategy type BuildPlanStrategy, index 3)
EDIT - TEST TO RESOLVE THE DATACONTEXT with 1 line of code
This also fails with the same error as above - multiple constructors
MyDataContext test = Bootstrapper.Container.Resolve<MyDataContext >();
EDIT - ALL CONSTRUCTORS ON MY DATACONTEXT
These were created by an exernal util but all should be well..
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext()
: base(ConnectionString, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection)
: base(connection, mappingCache)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(string connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
[System.Diagnostics.DebuggerNonUserCode]
public MyDataContext(System.Data.IDbConnection connection, System.Data.Linq.Mapping.MappingSource mappingSource)
: base(connection, mappingSource)
{
OnCreated();
}
EDIT - To demonstrate creating the DataContext in code without Unity works 100% without issue
MyDataContext tes2t = new MyDataContext ();
I'm not sure this works, but have you tried to register MyDataContext as a component rather than a type mapping?
container.RegisterType<MyDataContext>();
instead of
container.RegisterType<MyDataContext, MyDataContext>();
EDIT based on new information
The culprit seems to be that MyDataContext has more than one constructor. This is a common issue with most DI Containers, because they need to pick and use only one. If you can remove the ambiguity by constraining MyDataContext to have only one constructor, that will probably be the simplest solution.
Otherwise, you should be able to use an InjectionConstructor instance to identify the constructor when you register the repository. Let's assume you want to use a constructor that takes a connection string as an argument:
string connectionString =
ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
var injectedConnectionString = new InjectionConstructor(connectionString);
container.RegisterType<MyDataContext>(injectedConnectionString);
With multiple constructors to choose from, Unity doesn't know which one to use. It will choose the one with the most arguments that can all be satisfied, but in this case there are two constructors each with two resolvable arguments.
If you don't want to couple your MyDataContext class to Unity and use the InjectionConstructor attribute as suggested by Scott (upvoted :)), you can specify the constructor that should be used at the time of registration using the fluent interface. See Configuring Constructor, Property, and Method Injection for details.
I don't see your MyDataContext constructors; but try to add the [InjectionConstructor] attribute to the one you want to use.