I see tons of material on how to inject services using the ControllerBuilder.Current.SetControllerFactory but what if I wanted to resolve my services in the model? Would I have to get them from the Controller layer and pass them up?
Ideally you should not be injecting services into the model as this would require you to register your model with the container.
If you need to use a service within a model instance, pass the service in as a method argument and then you can inject the service into the controller.
Without knowing more about the scenario it is hard to give clearer advice, however the following outline may help:
public interface IService
{
// ... describe the contract the service must fulfill
}
public class Model
{
public void DoSomething( IService service )
{
// ... do the necessary work using the service ...
}
}
public class AController : Controller
{
private readonly IService _injectedService;
public AController( IService injectedService )
{
_injectedService = injectedService;
}
public ActionResult SomeAction( int modelId )
{
// ... get the model from persistent store
model.DoSomething( _injectedService );
// ... return a view etc
}
}
Related
I am using Caliburn.Micro in combination with Xamarin.Forms. Within my App class, I register an interface ILicenseInfo with a class LicenseInfoImplementation via the SimpleContainer's PerRequest method.
CM then injects an object when my view model is created (see ViewModelOne) which is what I want. However, I don't see how I can extend this to a collection of objects. Lets say I would like CM to instantiate ViewModelTwo which expects a collection of object. How would I have to change App.cs and the XAML of ViewModelTwo to make that happen?
public partial class App : FormsApplication
{
private readonly SimpleContainer _container;
public App (SimpleContainer container)
{
InitializeComponent();
this._container = container;
// register interface and class
_container.PerRequest<ILicenseInfo, LicenseInfoImplementation>();
//....
}
}
public ViewModelOne(ILicenseInfo license)
{
// Great, Caliburn.Micro injects an LicenseInfoImplementation object
}
public ViewModelTwo(IEnumerable<ILicenseInfo> licenses)
{
// No idea
}
I finally used the following pattern. Not the most elegant way to do it but the best I found ...
public ViewModelTwo() : base (IoC.GetAll<ILicenseInfo>())
{
}
public ViewModelTwo(IEnumerable<ILicenseInfo> licenses)
{
// Do something with licenses
}
I'm using Unity.MVC for DI in my ASP.NET MVC 4.6 app. I have a service interface passed into the controller and that's working great. Now I want to pass in an interface to the EF context to the service but I'm not sure how to do this. I've read EF has this IObjectContextAdapter that I could pass into my service ctor and that works, but I need to then query the actual tables on inside my service from this context but because it's an IObjectContextAdapter it doesn't know my tables. How do I do this?
public class ContactService : IContactService
{
//private ContactsEntities context;
private IObjectContextAdapter context;
// test ctor
public ContactService(IObjectContextAdapter ctx)
{
context = ctx;
}
// prod ctor
public ContactService()
{
context = new ContactsEntities();
}
List<Contact> GetAllContacts()
{
return (from c in context.ObjectContext.?? // I need to query the Contacts table that would be attached to the actual context I pass in but still keep the decoupling from using an Interface passed into the ctor
}
}
The IObjectContextAdapter is the type of ObjectContext property of DbContext.
You should subclass DbContext e.g. ContactsDatabaseContext
public class ContactsDatabaseContext : DbContext, IContactsDatabaseContext
{
// ...
}
And then just register your ContactsDatabaseContext with your IoC container. Something like this:
container.RegisterType<IContactsDatabaseContext, ContactsDatabaseContext>();
Your ContactsDatabaseContext class and IContactsDatabaseContext interface should have properties of type DbSet<T> that refer to your tables e.g.:
IDbSet<BrandDb> Users { get; set; }
UPDATE:
Since you are using a generated file, then do this:
public partial class ContactsDatabaseContext : IContactsDatabaseContext
{
// Expose the DbSets you want to use in your services
}
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.
On an ASP.NET MVC solution I have a Service layer which contains services for each Model. For example for DocumentModel I have Document Service which is instantiated by a UoW class which acts like a factory and does the save:
public class UnitOfWork : IUnitOfWork
{
private IRepositoryFactory _repositoryFactory;
public UnitOfWork()
: this(new RepositoryFactory())
{
}
public UnitOfWork(IRepositoryFactory repositoryFactory)
{
_repositoryFactory = repositoryFactory;
}
private IDocumentService _DocumentService;
public IDocumentService DocumentService
{
get
{
if (_DocumentService == null)
{
_DocumentService = new DocumentService(_repositoryFactory.DocumentRepository);
}
return _DocumentService;
}
}
}
Now say I need to be able to access 2 or 3 other repositories from DocumentService. What is the best way to inject this new repositories? Add them in the constructor( which if I need to add yet another repository can become cumbersome) or should I just inject the repository factory (IRepositoryFactory) which will allow me to access in DocumentService any repository I may need.
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;
}
}