strucutreMap Dependency injection is not working - asp.net

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.

Related

Error in CreateInstance() while dynamically creating object of concrete type in Factory Pattern

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.

Dependency injection for non controller classes and calling them

Trying to wrap my head around dependency injection, coming from the world of static classes and instantiated classes. Here is what I currently have:
[SomeFilter]
public class AController : Controller
{
private readonly IOptions<AppSettings> _appSettings;
public AController(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings;
}
// GET: /characters/
public IActionResult Index()
{
//do something
}
SomeFilter gets called immediately, and does this:
public class SomeFilter: ActionFilterAttribute, IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
OtherClass.RunMe();
}
}
OtherClass looks like this:
public class OtherClass
{
private readonly IOptions<AppSettings> _appSettings;
public OtherClass(IOptions<AppSettings> appSettings)
{
_appSettings = appSettings;
}
public RunMe()
{
//do something
}
I also have OtherClass registered as a service.Singleton in the Startup.cs.
I get an error stating:
"An object reference is required for a non-static field"
for the OtherClass.RunMe(); call.
I was under the assumption that I can call this class from anywhere within my code instead of having to create a new instance of it? Essentially, how do I call methods from other classes using dependency injection?
You can't constructor injection on filters. It's all about run time order. When you try injection on constructor, your IoC container not reachable at the moment. You should be use property/setter injection.
I prefer using structuremap container for to do this. Because structuremap has very easy to apply any type injection. For example when you have a filter registry like this
public class ActionFilterRegistry : Registry
{
public ActionFilterRegistry(Func<IContainer> containerFactory)
{
For<IFilterProvider>().Use(
new StructureMapFilterProvider(containerFactory));
Policies.SetAllProperties(x =>
x.Matching(p =>
p.DeclaringType.CanBeCastTo(typeof(ActionFilterAttribute)) &&
p.DeclaringType.Namespace.StartsWith("YourNameSpace") &&
!p.PropertyType.IsPrimitive &&
p.PropertyType != typeof(string)));
}
}
And you register it on your global.asax(prefer) or one of your startup class.
Example app_Start method.
DependencyResolver.SetResolver(new StructureMapDependencyResolver(() => Container ?? ObjectFactory.Container));
ObjectFactory.Container.Configure(cfg =>
{
cfg.AddRegistry(new StandardRegistry());
cfg.AddRegistry(new ControllerRegistry());
cfg.AddRegistry(new ActionFilterRegistry(() => Container));
cfg.AddRegistry(new MvcRegistry());
});
Then you can use any filter with injection. But pay attention you shouldn't be use contructor injection like you do.
I found a way to inject into the filter by using
[ServiceFilter(typeof(MyFilter))]
instead of just
[MyFilter]
and within the filter's
(ActionExecutingContext context)
{
var controller = context.Controller as Controller.
controller.whateverIneed
}
This now provides me with what I need within the filter. What I also realized is that I can't remove the need for creating references to other classes using new, as I was under the impression Core's dependency was all about "no more new". This gets into fundamentals with Core which I'm still grasping with.
What I ended up doing was creating new classes that do some work, but they are setup as services and registered in the startup.cs. I'm still grappling on how to intermingle registered services (which I can inject) and new instances of worker classes (which usually hold static information), and passing information between them all.

How do I Inject Dependencies with Ninject, where instances are deserialised from json

This is my first try using DI, I've chosen ninject for it's reportedly easy learning curve, and have this question.
I'm creating objects like this:
var registrants = JsonConvert.DeserializeObject<List<Registrant>>(input);
I currently have this constructor for Registrant
[Inject]
public Registrant(IMemberRepository memberRepository)
{
_memberRepository = memberRepository;
}
What is the best way to have the repository dependency be injected into the deserialized object(s) using Ninject?
You can't use constructor injection with objects that are not created by Ninject (e.g. deserialized objects). But you can use property injection. Just call kernel.Inject(obj)
One question that remains is why you want to inject those objects. Normally, you don't want to use depedency injection on data container objects. In a proper design they don't have any dependency on services. The operations that need to be done on the services are done by the owner of the data container objects. I recommend to consider a refactoring of your design.
Assuming you're using Ninject V2, and you're using it in the context of an ASP.NET app, you should be using Ninject.Web to do the hookups.
Then you set up a Global class with the Factory Method support hooked in:
public class Global : NinjectHttpApplication
{
protected override Ninject.IKernel CreateKernel()
{
var kernel = new StandardKernel( new Module() );
kernel.Components.Add( new FuncModule( ) );
return kernel;
}
}
that registers the module that will Bind IMemberRepository to something:
public class Module : NinjectModule
{
public override void Load()
{
Bind<IMemberRepository>().To<MemberRepository>();
}
}
and the page wires up like this:
public class ThePage : PageBase
{
readonly Func<Registrant> _createRegistrant;
public ThePage( Func<Registrant> createRegistrant )
{
_createRegistrant = createRegistrant;
}
private void OnCreateRegistrant()
{
var newRegistrant = _createRegistrant();
}
}
NB not 100% sure if constructor injection is supported for Web Forms pages or wheter the above needs to drop to property injection... anyone?
(assuming the classes you have are as follows:)
public class MemberRepository : IMemberRepository
{
}
public interface IMemberRepository
{
}
public class Registrant
{
private readonly IMemberRepository _memberRepository;
public Registrant( IMemberRepository memberRepository )
{
_memberRepository = memberRepository;
}
}

WCF Runtime Error while using Constructor

I am new to WCF i am using constructor in my WCF service.svc.cs file....It throws this error when i use the constructor
The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor.
To fix the problem, add a default constructor to the type, or pass an instance of the type to the host.
When i remove the constructor its working fine....But its compulsory that i have to use constructor...
This is my code
namespace UserAuthentication
{
[ServiceBehavior(InstanceContextMode=System.ServiceModel.InstanceContextMode.Single)]
public class UserAuthentication : UserRepository,IUserAuthentication
{
private ISqlMapper _mapper;
private IRoleRepository _roleRepository;
public UserAuthentication(ISqlMapper mapper): base(mapper)
{
_mapper = mapper;
_roleRepository = new RoleRepository(_mapper);
}
public string EduvisionLogin(EduvisionUser aUser, int SchoolID)
{
UserRepository sampleCode= new UserRepository(_mapper);
sampleCode.Login(aUser);
return "Login Success";
}
}
}
can anyone provide ideas or suggestions or sample code hw to resolve this issue...
You could add something like (if possible):
public UserAuth() : this(SqlMapperFactory.Create())
{
}

How can you inject an asp.net (mvc2) custom membership provider using Ninject?

OK, so I've been working on this for hours. I've found a couple of posts here, but nothing that actually resolves the problem. So, let me try it again...
I have an MVC2 app using Ninject and a custom membership provider.
If I try and inject the provider using the ctor, I get an error: 'No parameterless constructor defined for this object.'
public class MyMembershipProvider : MembershipProvider
{
IMyRepository _repository;
public MyMembershipProvider(IMyRepository repository)
{
_repository = repository;
}
I've also been playing around with factories and Initialize(), but everything is coming up blanks.
Any thoughts/examples?
The Membership provider model can only instantiate a configured provider when it has a default constructor. You might try this using the Service Locator pattern, instead of using Dependency Injection. Example:
public class MyMembershipProvider : MembershipProvider
{
IMyRepository _repository;
public MyMembershipProvider()
{
// This example uses the Common Service Locator as IoC facade, but
// you can change this to call NInject directly if you wish.
_repository = ServiceLocator.Current.GetInstance<IMyRepository>;
}
This is how I was able to do this:
1) I created a static helper class for Ninject
public static class NinjectHelper
{
public static readonly IKernel Kernel = new StandardKernel(new FooServices());
private class FooServices : NinjectModule
{
public override void Load()
{
Bind<IFooRepository>()
.To<EntityFooRepository>()
.WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings["FooDb"].ConnectionString);
}
}
}
2) Here is my Membership override:
public class FooMembershipProvider : MembershipProvider
{
private IFooRepository _FooRepository;
public FooMembershipProvider()
{
NinjectHelper.Kernel.Inject(this);
}
[Inject]
public IFooRepository Repository
{
set
{
_FooRepository = value;
}
}
...
With this approach it doesn't really matter when the Membership provider is instantiated.
I had the same problem at the exact same spot in the book. It wasn't until later on in the book that I noticed there were two separate web.config files. I initially placed my connectionString key in the wrong web.config file. It wasn't until I placed the connectionString in the correct web.config file that the 'no parameterless constructor' error went away.

Resources