Error in CreateInstance() while dynamically creating object of concrete type in Factory Pattern - .net-core

I am actually new to design patterns and trying to implement factory pattern with .NET Core.
I tried to see couple of posts related to factory pattern and trying to implement it, I have added the concrete types in the config and reading it as dictionary in my code -
My Factory Interface -
public interface IEmpFactory
{
public BaseEmployee CreateEmployeeType<EmpType>()
where EmpType : BaseEmployee, new();
}
Implementation -
public class EmpFactoryImpl : IEmpFactory
{
public BaseEmployee CreateEmployeeType<EmpType>()
where EmpType: BaseEmployee, new()
{
return new EmpType();
}
}
Below are my services which are using the Factory as dependency -
public interface IEmpService
{
public string GetEmployeeBonus();
}
public class ContractEmpService : IEmpService
{
IEmpFactory _empFactory;
public ContractEmpService(IEmpFactory empFactory) =>
_empFactory = empFactory;
private BaseEmployee CreateMyEmployee() =>
_empFactory.CreateEmployeeType<ContractEmp>();
public string GetEmployeeBonus() =>
return CreateMyEmployee().GetBonus();
}
public class PermEmpService : IEmpService
{
private readonly IEmpFactory _empFactory;
public PermEmpService(IEmpFactory empFactory) =>
_empFactory = empFactory;
private BaseEmployee CreateMyEmployee() =>
_empFactory.CreateEmployeeType<PermEmp>();
public string GetEmployeeBonus() =>
CreateMyEmployee().GetBonus();
}
Added these concrete types in the config -
"ConfigurationProps": {
"EmpServices": {
"PermEmp": "SimpleFactoryWithoutSwitchCase.Service.PermEmpService",
"ContractEmp": "SimpleFactoryWithoutSwitchCase.Service.ContractEmpService"
}
}
Created the class to create a instance of the concrete type based on the type i.e, PermEmp or ContractEmp dynamically -
public class EmployeeTypeRouter : IEmployeeTypeRouter
{
private readonly ConfigurationProps _props;
public EmployeeTypeRouter(ConfigurationProps props)
{
_props = props;
}
public IEmpService GetInstance(string key)
{
string className = _props.EmpServices
.Where(k => k.Key.Equals(key)).FirstOrDefault().Value;
Type t = Type.GetType(className);
return (IEmpService)Activator.CreateInstance(t);
}
}
This is my calling method -
[HttpGet(Name = "GetEmployeeBonus")]
public string Get()
{
string type = "PermEmp";
IEmpService empService = _empRouter.GetInstance(type);
return empService.GetEmployeeBonus();
}
based on the type passed here i want to fetch the concrete type and call the method.
I am getting the error like this on CreateInstance method -
System.MissingMethodException: `Cannot dynamically create an instance of type 'SimpleFactoryWithoutSwitchCase.Service.PermEmpService'. Reason: No parameterless constructor defined.'
Which is very clear, but I don't want to create a parameterless constructor.
Since I am registering the dependencies in .NET Core, do I need to pass it again here? (which does not make sense for me)
Any help is really appreciated or if you feel I am doing something wrong please let me know.

Your EmployeeTypeRouter class tries to replicate the creation process that your DI Container can do more eloquently. So instead of calling Activator.CreateInstance, forward the resolution to the DI Container.
This means the following things:
Register all known IEmpService at startup.
Resolve the expected type from the IServiceProvider from inside the EmployeeTypeRouter.
In other words, change the startup code to the following:
var dictionary = props.EmpServices
.ToDictionary(p => p.Key, p => Type.GetType(p.Value));
foreach (string pair in dictionary)
{
services.AddTransient(pair.Value);
}
services.AddTransient<IEmployeeTypeRouter, EmployeeTypeRouter>();
services.AddTransient<Func<string, IEmpService>>(sp =>
key => (IEmpService)sp.GetRequiredService(dictionary[key]));
And change EmployeeTypeRouter to the following:
public class EmployeeTypeRouter : IEmployeeTypeRouter
{
private readonly Func<string, IEmpService> _factory;
public EmployeeTypeRouter(Func<string, IEmpService> factory)
{
_factory = factory;
}
public IEmpService GetInstance(string key) =>
_factory.Invoke(key);
}
In the previous code snippet, EmployeeTypeRouter makes use of the Func<string, IEmpService> delegate, which functions as factory. Under the covers the delegate calls back into the IServiceProvider.
There are of course several ways to skin a cat. You could also move some of the startup logic into EmployeeTypeRouter, or even remove the IEmployeeTypeRouter altogether and let application code depend directly on Func<string, IEmpService> delegate.

Related

How to distinguish between multiple databases with the same structure and same context in the URL for an ASP.Net Core Web API

I'm trying to make a web api in asp.net core which can target multiple databases on the same server with the exact same structure. As such they should be able to share the same context and controllers. Making separate contexts and controllers for each database would quickly get out of hand and make it a pain to maintain. As such I should be able to do this in Startup.cs.
services.AddDbContext<DatabaseContext>(opt => opt.UseMySQL(Configuration.GetConnectionString("db1")));
services.AddDbContext<DatabaseContext>(opt => opt.UseMySQL(Configuration.GetConnectionString("db2")));
services.AddDbContext<DatabaseContext>(opt => opt.UseMySQL(Configuration.GetConnectionString("db3")));
The problem I'm running into is how I can distinguish which database is being queried. Ideally I would like to have it such that the url can be ...{database}[controller]... where the database parameter can be used to determine which database is being queried. I've tried looking into the multi-tenant approach however I can't work out how to adapt it to my specific use case.
Any help would be greatly appreciated.
Take a look at this:
https://entityframeworkcore.com/knowledge-base/58123230/connect-multiple-databases-to--net-core-project-via-entity-framework-core
You can do it with multiple DB Contexts from inheriting the principal DB Context where you define the DbSets.
Create base context and including all settings into this, DBSET:
public abstract class BaseContext : DbContext
{
public BaseContext(DbContext options)
: base(options)
{ }
public DbSet<object> FirstDbSet { get; set; }
...
}
inherit from BaseContext for both DBs(Databases):
public class NavaContext : BaseContext
{
public NavaContext (DbContext<NavaContext> options) : base(options)
{
}
}
public class StackContext : BaseContext
{
public StackContext(DbContext<StackContext> options) : base(options)
{
}
}
and register both in Startup.cs:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddDbContext<NavaContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LATAMConnectionString")));
services.AddDbContext<StackContext>(options => options.UseSqlServer(Configuration.GetConnectionString("EUConnectionString")));
// Autofac
var builder = new ContainerBuilder();
// needed only if you plan to inject ICollection<BaseContext>
builder.RegisterType<NavaContext>().As<BaseContext>();
builder.RegisterType<StackContext>().As<BaseContext>();
builder.Populate(services);
return new AutofacServiceProvider(builder.Build());
}
add connection strings in appsettings.json:
"ConnectionStrings": {
"NavaConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true",
"StackConnectionString": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
and now you can inject both contexts:
public class ReportRepository : IReportRepository
{
private readonly NavaContext latamDbContext;
private readonly StackContext euDbContext;
public ReportRepository(NavaContext latamDbContext, StackContext euDbContext)
{
this.latamDbContext = latamDbContext;
this.euDbContext = euDbContext;
}
}
or if you plan to inject collection of contexts:
public class ReportRepository : IReportRepository
{
private readonly ICollection<BaseContext> dbContexts;
public ReportRepository(ICollection<BaseContext> dbContexts)
{
this.dbContexts = dbContexts;
}
}
to access specific context:
var _stackContext= dbContexts.FirstOrDefault(x => x is StackContext) as StackContext;
var _navaContext= dbContexts.FirstOrDefault(x => x is NavaContext) as NavaContext;
The best way to create connection when there are multiple databases in dot net core is with IDesignTimeDbContextFactory
public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
public BloggingContext CreateDbContext(string[] args)
{
// logic to determine which connection string to use
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlite("connectionString");
return new BloggingContext(optionsBuilder.Options);
}
}
Inject BloggingContextFactory using register services and pass args[] for logic to use connection string

Leveraging user context in an IHostedService via DI

I have a series of class libraries that are used in asp.net-core middleware, and in an IHostedService.
To fetch the user context, I can inject IHttpContextAccessor to grab the HttpContext user:
public class MyLibrary
{
public MyLibrary(IHttpContextAccessor accessor)
{
// set the accessor - no problem
}
public async Task DoWorkAsync(SomeObject payload)
{
// get the user from the accessor
// do some work
}
}
To be a little more abstract, I have an IUserAccessor with an HttpUserAccessor implementation:
public class HttpUserAccessor: IUserAccessor
{
IHttpContextAccessor _httpaccessor;
public HttpUserAccessor(IHttpContextAccessor accessor)
{
_httpaccessor = accessor;
}
public string GetUser()
{
// return user from _httpaccessor
}
}
and then MyLibrary does not need an IHttpContextAccessor dependency:
public class MyLibrary
{
public MyLibrary(IUserAccessor accessor)
{
// set the accessor - no problem
}
public async Task DoWorkAsync(SomeObject payload)
{
// get the user from the accessor
// do some work
}
}
My IHostedService is popping message from a queue, where the message includes:
a user context, and
a serialized SomeObject to pass to MyLibrary.DoWorkAsync
So, something like:
public class MyHostedService : IHostedService
{
IServiceScopeProvider _serviceScopeFactory;
public MyHostedService(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = servicesScopeFactory;
}
public Task StartAsync(CancellationToken cancellationToken)
{ ... }
public Task StopAsync(CancellationToken cancellationToken)
{ ... }
public async Task ExecuteAsync(CancellationToken stoppingToken)
{
foreach (var message in queue)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
// todo: tell IUserAccessor what message.User is!
var payload = // create a SomeObject from the queue message
var mylibrary = _services.GetRequiredService<MyLibrary>();
await myLibrary.DoWorkAsync(payload);
}
}
}
}
So, my question is, how does MyHostedService store message.User in such a way that a custom IUserAccessor can access it in a thread-safe manner via DI?
how does MyHostedService store message.User in such a way that a custom IUserAccessor can access it in a thread-safe manner via DI?
The thing you're looking for is AsyncLocal<T> - it's like a thread-local variable but scoped to a (possibly asynchronous) code block instead of a thread.
I tend to prefer a "provider" + "accessor" pairing for this: one type that provides the value, and a separate type that reads the value. This is logically the same thing as a React Context in the JS world, though the implementation is quite different.
One tricky thing about AsyncLocal<T> is that you need to overwrite its value on any change. In this case, that's not really a problem (no message processing will want to update the "user"), but in the general case it's important to keep in mind. I prefer storing immutable types in the AsyncLocal<T> to ensure they aren't mutated directly instead of overwriting the value. In this case, your "user" is a string, which is already immutable, so that's perfect.
First, you'll need to define the actual AsyncLocal<T> to hold the user value and define some low-level accessors. I strongly recommend using IDisposable to ensure the AsyncLocal<T> value is unset properly at the end of the scope:
public static class AsyncLocalUser
{
private static AsyncLocal<string> _local = new AsyncLocal<string>();
private static IDisposable Set(string newValue)
{
var oldValue = _local.Value;
_local.Value = newValue;
// I use Nito.Disposables; feel free to replace with another IDisposable implementation.
return Disposable.Create(() => _local.Value = oldValue);
}
private static string Get() => _local.Value;
}
Then you can define a provider:
public static class AsyncLocalUser
{
... // see above
public sealed class Provider
{
public IDisposable SetUser(string value) => Set(value);
}
}
and the accessor is similarly simple:
public static class AsyncLocalUser
{
... // see above
public sealed class Accessor : IUserAccessor
{
public string GetUser() => Get();
}
}
You'll want to set up your DI to point IUserAccessor to AsyncLocalUser.Accessor. You can also optionally add AsyncLocalUser.Provider to your DI, or you can just create it directly.
Usage would go something like this:
foreach (var message in queue)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var userProvider = new AsyncLocalUser.Provider(); // (or get it from DI)
using (userProvider.SetUser(message.User))
{
var payload = // create a SomeObject from the queue message
var mylibrary = _services.GetRequiredService<MyLibrary>();
await myLibrary.DoWorkAsync(payload);
}
}
}

Unity injection of an instance inside WebAPI action

I am stuck with this and I wonder what is the best way to approach this problem. I have a WebApi controller where I want to inject ICommand instance but I can know what is the instance I need once I inspect the Post request data. I'll give an example to be more clear but my question also applies to Winform events where you receive an event argument and depending of this event arg you want to have different implementation injected.
public class TestController : ApiController
{
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = new Id1Command();
}
else
{
command = new Id2Command();
}
return new object();
}
}
The only thing I can think of is creating a factory that accepts unity container as argument and inside that factory to call container.Resolve with named instance.
My problem with that is that I am taught that you shouldn't register or resolve outside your composition root and that is violation of the good practices (according Mark Seemann). I am looking for the best design for this problem in general.
I would use a CommandFactory and pass it to the TestController:
public class TestController : ApiController
{
private readonly ICommandFactory mCommandFactory;
public TestController(ICommandFactory CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
ICommand command = null;
if(id = 1)
{
command = CommandFactory.CreateId1Command();
}
else
{
command = CommandFactory.CreateId2Command();
}
return new object();
}
}
Now you have to make sure that Unity is creating the TestController. To do so, you have to implement, configure and set an IDependencyResolver. Check Dependency Injection in ASP.NET Web API 2.
Edit to your comment:
For this scenario you can use an autofactory using a functor that takes an int:
public class TestController : ApiController
{
private readonly Func<int, ICommand> mCommandFactory
public TestController(Func<int, ICommand> CommandFactory)
{
mCommandFactory = CommandFactory;
}
public object Post(int id)
{
var command mCommandFactory(id);
return new object();
}
}
The registration should look like this:
container.RegisterType<Func<int, ICommand>>(new InjectionFactory(
c => new Func<int, ICommand>(
id =>
{
if (id == 1)
{
return new Command();
}
else
{
return new Command2();
}
})));
Note: You still have to set the DependencyResolver!

Registration by convention and interception causes ResolutionFailedException

Simple scenario
public interface IFoo
{
int GetData();
}
public class Foo : IFoo
{
[CacheResult]
public int GetData() { .... }
}
public class MyController
{
[Dependency]
IFoo Foo {get; set;}
}
If I register the interface manually, resolving MyController works fine:
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager(),
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
var controller = container.Resolve<MyController>();
If I try to use auto-registration:
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled,
getInjectionMembers: t => new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<PolicyInjectionBehavior>(),
});
var controller = container.Resolve<MyController>();
The resolve fails with a ResolutionFailedException because the Type passed must be an interface. Of course, if I make it an interface, it will work, but only if it is named Controller. If I call it, MyController or SqlController or whatever, then the mapping fails because it cannot resolve the interface.
I was hoping to just do an assembly scan, similar to what the Spring framework does, but I have not been able to figure it out.
What am I missing? Or is this not possible in Unity?
The problem is that AllClasses.FromLoadedAssemblies is matching and registering your controller as well. Then when Unity tries to resolve the controller (not IFoo), it finds that the controller is not registered with an interface.
Here's a helper that will reduce your registrations to only those classes that have a matching interface.
public static class TypeFilters
{
public static IEnumerable<Type> WithMatchingInterface(this IEnumerable<Type> types)
{
return types.Where(type =>
type.GetTypeInfo().GetInterface("I" + type.Name) != null);
}
}
and then you can use this to modify your registration like so...
AllClasses.FromLoadedAssemblies().WithMatchingInterface()

strucutreMap Dependency injection is not working

In my application i configured structuremap like
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public DefaultRegistry() {
Scan(
scan => {
scan.Assembly("Eterp.Data.ErpCore");
scan.Assembly("Eterp.Data.Seed");
scan.Assembly("Eterp.Application.ErpCore");
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
ForConcreteType<AclAuthorizationManager>().Configure.Ctor<IResourceOperationAppService>()
}
#endregion
}
And i have class
public class AclAuthorizationManager : ClaimsAuthorizationManager
{
private readonly IResourceOperationAppService _resourceOperationAppService;
public AclAuthorizationManager(IResourceOperationAppService resourceOperationAppService)
{
_resourceOperationAppService = resourceOperationAppService;
}
public override bool CheckAccess(AuthorizationContext context)
{
var isCurrentUserAuthorized = context.Principal.Identity.IsAuthenticated;
return isCurrentUserAuthorized && _resourceOperationAppService.CanAccessResource(context.Action.FirstOrDefault().Value, context.Principal.Claims);
}
}
This class is custom claim authorization class using in my application, but when i exceuting the application,i am getting an error which related to lack of parameter required by the constructor, ( This class has constructor with parameter type IResourceOperation). but i already configured all the details in structureMap . i am sure that my structuremap configuration is working 100% well expect the creation of this AclAuthorizationManager class.because i am able to to apply DI in other classes.
What is wrong part in my code?
in my experience when you specify the type constructor must say that inherits from the interface.
Therefore, you should replace this line:
ForConcreteType<AclAuthorizationManager>().Configure.Ctor<IResourceOperationAppService>()
By:
ForConcreteType<AclAuthorizationManager>().Configure.Ctor<IResourceOperationAppService>().Is<ResourceOperationAppService>()
Where is the implementation ResourceOperationAppService IResourceOperationAppService.

Resources