I find myself adding dependencies a lot to constructors like so:
public class SomeClass() {
private ISomeService _service;
private IAnotherService _anotherService;
public SomeClass(ISomeService service, IAnotherService anotherService) {
_service = service;
_anotherService = anotherService;
}
}
They're quite tedious to write, I've been looking for code snippets in visual studio to automatically add one to the constructor but haven't found one.
What I want is:
When adding a dependency to a constructor some snippet automatically creates a local variable and assigns to it.
OR
Add a private variable and then some snippet automatically adds it to the constructor and assigns it to the local variable.
If you have R# you can enter the field declarations and then highlight them and hit Alt-Enter which will give you the option to generate the constructor and field assignments.
If you don't have Resharper, you can add the parameter on the constructor, write the assignament to an unexisting property and hit CTRL+. . This will prompt you with the options to automatically create a property or field for you.
For example, you have this class:
public class MyClass
{
public MyClass()
{
}
}
You then add the parameter to the constructor, and the assignament:
public class MyClass
{
public MyClass(IDependency myDependency)
{
this.myDependency = myDependency;
}
}
And hit CTRL+. while on the asignament line, and select create field, and you'll get this:
public class MyClass
{
IDependency myDependency;
public MyClass(IDependency myDependency)
{
this.myDependency = myDependency;
}
}
I don't know about previous versions, but in vanilla Visual Studio 2017, you can actually add a constructor parameter
public SomeClass(ISomeService service)
{
}
Then put your cursor on service and from "Quick actions" you can chose Introduce and initialize field _someService which will do what you want :
private readonly ISomeService _someService;
public SomeClass(ISomeService service)
{
_someService = service;
}
You can easily add code snippets as you like, defining it in XAML and adding it the editior, you can use place holders like "class name" to use it as a constructor for example, and then place your variables in it as static text
I don't want to write the code because it's duplicated
you can check out how to do it here:
https://msdn.microsoft.com/en-us/library/ms242312.aspx?f=255&MSPPError=-2147217396
you can also see this question:
How can I automatically generate a constructor that receives and stores services for free?
what you are trying to do with the ISomeService and IAnotherService is to do dependency inversion.
I would strongly recommend you combine this with a dependency injection framework. There are many available but one i would recommend is MEF. MEF is build into the .net framework. For example your code would look like this with MEF
[Export(typeof(ISomeService))]
public class SomeService : ISomeService {
}
public class SomeClass {
[Import]
public ISomeService SomeService {get; set;}
[Import]
public IAnotherService AnotherService {get; set;}
}
Now MEF will actually ensure your SomeService and AnotherService Properties are filled when your class is created. It will construct (if needed) a instance of SomeService, fill all it's dependencies and put it in the right property. You can even control if you want your services instantiated as singletons or as a new service instance each time you need one.
for more details on MEF you can look here https://msdn.microsoft.com/en-us/library/ee155691(v=vs.110).aspx
This should avoid writing the many constructors that do nothing other than initializing services.
Telerik's JustCode can do exactly what you need.
if you have an unused argument in the constructor you can create a field and initialise it.
http://www.telerik.com/products/justcode/quick-fixes.aspx
I was looking for exactly this when I found this library of snippets. Depending on how many parameters you need, you can use ctor1p, ctor2p.. so on. It creates the constructor with number of params specified and also generates a private field corresponding to each of the injected param.
It works just fine when you're writing the constructor for the first time.
If you have an existing constructor with/without parameters and you'd like to inject a new parameter using these snippets, you will have to rewrite your constructor which will be difficult than just injecting the parameter manually and using ctrl + ..
Related
I'm using a custom JsonConverter and JsonSerializerSettings.TypeNameHandling = TypeNameHandling.Objects to create the required instances during deserialization. The instances are created by resolving the types from an Autofac IOC container. Everything works fine, except...
I have several "core objects" that request a unique Id in the constructor from a service (which is correctly injected into the constructor). When deserializing this should not happen because it is fairly expensive and the Ids will be populated from the Json file anyway once the instance has been created.
Currently, when resolving from within the custom JsonConverter I'm using _scope.Resolve<T>(new TypedParameter(typeof(IIdService), null)); to then - in the called constructor - check for null and act accordingly.
Some people apparently consider multiple constructors worse than a code-smell when using an IOC (which makes me wonder why Autofac offers several features regarding the topic), but in the context of deserialization I think it can make perfect sense.
As far as I can tell Autofac has mechanisms to decide which constructor to use during registration, but not when resolving. My preferred solution would be to add a custom attribute to a constructor (e.g. [CtorForDeserializing]) and use that for deciding. Is that possible?
There are a couple of extension points Autofac has for reflection-based activations but doesn't have well documented yet that may help you out: IConstructorFinder and IConstructorSelector.
IConstructorFinder is used to locate all the available constructors on a type. The core example is the DefaultConstructorFinder which locates only public constructors. If you wanted to, say, hide constructors with particular attributes or start finding internal/private constructors, you could create a custom finder. This really only happens once so you don't get to make runtime choices here.
IConstructorSelector is used to choose, at resolve time, which constructor should be used to instantiate the object. There are a couple of these in core Autofac, but the primary example is the MostParametersConstructorSelector which selects the constructor that has the most available matching parameters at the time. Constructors get found by the IConstructorFinder and then that set of constructors is what is presented to the IConstructorSelector to choose from. This is where you could make more runtime choices since it happens every time the object is resolved.
There are extension methods to help you add your finder/selector to a registration:
builder.RegisterType<MyType>()
.FindConstructorsWith(new MyConstructorFinder())
.UsingConstructor(new MyConstructorSelector());
You don't have to customize both things, you can just do one or the other if you want. I'm just showing you the extensions.
Actually Autofac is able to decide which constructor to use both ways - during registration or resolution. For resolution part here is the quote from documentation: "Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from the container" (see here).
Consider following example.
public interface ISomeService
{
Guid Id { get; }
}
public class SomeService : ISomeService
{
public Guid Id { get; }
public SomeService()
{
Id = Guid.NewGuid();
}
public SomeService(Guid id)
{
Id = id;
}
}
// Startup.cs:
builder.RegisterType<SomeService>().As<ISomeService>().InstancePerLifetimeScope();
// TestController.cs:
[Route("api/[controller]")]
public class TestController : Controller
{
private readonly IComponentContext _context;
public TestController(IComponentContext context)
{
_context = context;
}
[HttpGet]
public IActionResult Get()
{
var service = _context.Resolve<ISomeService>();
return Ok(service.Id);
}
[HttpGet("{id}")]
public IActionResult Get(Guid id)
{
var service = _context.Resolve<ISomeService>(new NamedParameter("id", id));
return Ok(service.Id);
}
}
// GET http://localhost:5000/api/test/e0198f72-6337-4880-b608-68935122cdea
// each and every response will be the same: e0198f72-6337-4880-b608-68935122cdea
// GET http://localhost:5000/api/test
// this way it responds with some random guid each time endpoint is called
Travis Illig sent me in the right direction - thanks!
I ended up implementing a solution around the following details:
Implement custom attributes, e.g.: public class DeserializeCtorAttribute : Attribute { }, which will be used by the (also to be implemented) IConstructorFinder.
Implement an empty generic interface, e.g.: IDeserializable<T>, which will be used for resolving the services/components.
Let relevant component classes implement the interface (MyClass : IDeserializable<MyClass>) and add an extra registration for the component:
_builder.RegisterType<MyClass>().As<IDeserializable<MyClass>>()
.FindConstructorsWith(MyConstructorFinder);
Use the implemented DeserializeCtorAttribute in the desired constructor of MyClass.
Let the JsonConverter create the required instance by calling (MyClass) scope.Resolve(IDeserializable<MyClass>); casting is required, but safe. Due to the registration the instance will be created using the desired constructor.
Using MEF, let's imagine there is a class called FooType and I apply the [Export] attribute on it. Now, I want to import this FooType somewhere else in my code to use it.
I have tried these two solutions :
[Import]
public FooType Foo { get; set; }
private void MyMethod()
{
Foo.DoSomething();
}
and
private void MyMethod()
{
// _container is of type CompositionContainer and comes from the [ImportingConstructor]
_container.GetExportedValue<FooType>().DoSomething();
}
Both of these worked, the DoSomething() method of FooType is correctly called. So it makes me wonder:
Are these two way of resolving an export really similar ? Or is there any difference ?
Is there recommanded solution between the two ?
An [Import] basically causes MEF to call GetExportedValue and assign it to the property or field. That said, most of the time you don't want your objects to have access to your container. In your second example you said you imported the container itself via ImportingConstructor. I would usually only import FooType via the constructor. I also always prefer constructor injection rather then property injection. It makes the pre-requisites of the object totally clear and your imports can be stored in readonly properties.
I'm creating a Web API and I'm using dependency inject wit Ninject.
I have:
IRTWRepository
IModelFactory
I'm injecting those 2 into my controllers like this.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRTWRepository>().To<RTWRepository>();
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
kernel.Bind<IModelFactory>().To<ModelFactory>();
}
My RTWRepository constructor looks like this
public class RTWRepository :IRTWRepository
{
private RTWAPIContext _context;
public RTWRepository(RTWAPIContext context)
{
_context = context;
}}
My ModelFactory constructor looks like this
public class ModelFactory : IModelFactory
{
private IRTWRepository _repo;
public ModelFactory(IRTWRepository repo)
{
_repo = repo;
}
}
I have a Controller that looks like this:
public MaterialsController(IRTWRepository repository,IModelFactory modelFactory)
: base(repository,modelFactory)
{
}
Now, my question is : Is Ninject creating 2 separate contexts when creating an instance of my RTWRepository and also when creating an instance of ModelFactory?.
The reason that I'm asking that is because I'm having a problem when I try to save an entity that has a dependency to another object which was previously retrieve from the db.
I'm saving the entity in my controller but I'm creating it in my model factory along with is dependency.
public class RecycleCenter
{
public RecycleCenter()
{
}
public int MyProperty { get; set; }
[Required]
public virtual Address Address { get; set; }
}
The code above is for the entity Recycle Center which has an Address, this recycle center entity is created in my model factory and then in my controller I try to save it but when my repository execute this line
_context.RecycleCenters.Add(entity);
I'm getting this error
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
So, somewhere in my code I'm using 2 context instead of 1 and I think is when creating the ModelFactory and RTWRepository, is this assumption correct?, if so how do I fix it?
TL;DR;
You probably need to change this line:
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
to
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestContext();
Explanation:
When you define a binding in Ninject, you also specify how that object's lifecycle should be handled.
If you don't explicitly define it, Ninject's default lifecycle is Transient. Transient means that each time an instance is required, it will create a new one. In your case, you need to two instances: one for the RTWRepository of the ModelFactory and one for the RTWRepository of the MaterialsController.
You can modify the lifestyle to one of these options:
Singleton ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InSingleTonScope();
Request ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestScope();
Thread ==> kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InThreadScope();
Named, Call, Parent, Custom
In your case, I think you need InRequestScope, but you have to check the necessary lifecycle as it depends on the application.
For further information please check out the documentation here: https://github.com/ninject/ninject/wiki/Object-Scopes
Most probably, it is. There's no annotation that is telling to Ninject "Hey, stop, when you have created the instance once, reuse it". You should agree that in most cases, you would want multiple instances of an object and that it is a rare case, where you want it only once.
If you want to reuse the instance, use the singleton pattern. Ninject is familiar with it, so you can bind the object mapping to a method
kernel.Bind<RTWAPIContext>().ToMethod(c => RTWAPIContext.GetInstance());
There is also a ToSingleton binding, but I bet you cannot make your context constructor private and implement C# specific singleton due to other ASP.NET problems (e.g. ASP.NET Identity will try to invoke the context's method for object creation).
I have a service class in a module in Orchard CMS that it is dependent on some dependency such as IContentManager and it implemented IDependency interface.
in my controllers i used it by injecting and it works pretty good.
my service:
public class AddressService : IAddressService
{
private readonly IContentManager _contentManager;
private readonly IOrchardServices _orchardService;
private readonly IRepository<StatePartRecord> _stateRepository;
private readonly IContentDefinitionManager _contentDefinitionManager;
public AddressService(IContentManager contentManager, IOrchardServices orchardService, IRepository<StatePartRecord> stateRepository, IContentDefinitionManager contentDefinitionManager)
{
_contentManager = contentManager;
_orchardService = orchardService;
_stateRepository = stateRepository;
_contentDefinitionManager = contentDefinitionManager;
}
...
}
public interface IAddressService : IDependency { ... }
my question is that, in my custom class that is just a simple class how do i resolve and create an object instance of my service class in it?
my simple class:
public class MyClass
{
public SomeMethod()
{
var addressService = // a method to resolve 'AddressService' class from IOC container
// Do somthing with 'addressService' ...
}
}
Edit I already knew that we can use AddressService by injecting way, but i can't use injection in some cases such as static classes or extension method... ,Because of that i need to resolve dynamically AddressService and create instance by some method (that i guess it would be found in Orchard Framework) where i had to use it.
In fact I need a method that takes a Type as argument and create instance of the passed Type and return the created object.
You don't. Your class itself will have to be instantiated by something. It should be instantiated when injected into something else. This question should be modified to present a real example rather than a "hello world what if" scenario.
Why not register your other class into the Autofac container also? Then you could let your container take care of wiring up your class. Its not good idea to have reference to service which is managed by Autofac injected into class that is not. Services should be injected into controllers that are managed. If you need to combine service functionality just make another service where you can do that....
Otherwise, you need a reference to Autofac Container and then call the Resolve method. So, how you get that? You can look at how that is done in DefaultContentManager where componets are resolvet through IComponentContext, but of course DefaultContentManager is managed by Autofac and there is no static method that I could find in Orchard that will let you get the reference to the Autofac container (if there were it would be a static getter in OrchardStarter).
Pass an argument (the service) into the constructor which implements the interface. Then you should be able to access the service (IOC Sorts out instantiation etc):
public class MyClass
{
private IAddressService addressService;
public MyClass(IAddressService service)
{
addressService = service;
}
public SomeMethod()
{
// Do something with 'addressService' ...
}
}
Or is your question not as obvious as what I have understood it to be??
On fifth reading of your question, I think you may be asking how to register your interface so that it uses your implementation?
Not sure how Ioc is done in Orchard but in Windsor (which I use at work) we register dependencies similar to this:
public class MyClass
{
public SomeMethod(IWindsorContainer container)
{
container.Register( Component.For<IAddressService>().ImplementedBy<AddressService>());
}
}
EDIT: Made mistake in code so added constructor, instead of passing the value to the method.
I resolved using IWorkContexAccessor.
You can see code here.
Sorry for the vague title. I'll explain what I'm trying to get working.
My Admin View uses an Admin ViewModel which in turn calls an Admin Service which is a collection of Admin Repositories. For the sake of simplicity lets say that there is only one repository referenced by the Admin Service.
When constructing my Admin View Model the top of my class looks like this
public class adminMenuVM
{
private readonly IAdminMenuService menuService;
public adminMenuVM(IAdminMenuService adminMenuService)
{
this.menuService = adminMenuService;
}
public adminMenuVM()
{
menuItems = getMenuItems();
menuCats = getMenuCats();
}
}
Where getMenuItems and getMenuCats are two methods that use the service to retrieve data which is then set for the view model.
My problem is that when I run the app I get the error "Object Reference not set to instance of an object". Now I know that this is because the adminMenuVM() is called by the viwModel and not the constructor initializing the service.
My question is how can I ensure that the service constructor is called and does its thing when my view model is called?
I've tried using :this on the parameterless constructor but it wont allow me to assign an interface since you can't create a new instance of an interface.
Edit # 18:49
I've had a thought but don't know how to implement it. Can anyone advise on how I could "Constructor Chain" or if it is possible? My thought is to chain the parameterless constructor to service constructor this ensuring it gets called. I may be way off but would be grateful for yer help.
The first constructor looks like it should be used by some Dependency Injection container.
You can use just one constructor to create an instance. When that DI creates an instance with a supplied "IAdminMenuService", then you can create a new instance by using the second constructor, but as that's a new instance, the "menuService" will be empty (null).
You will need to find out how to get tan instance of your adminMenuVM from the DI container (if that is what you use).
Remove that default constructor and put its contents into the constructor with the parameter.
Managed to figure this one out. Its not the cleanest solution but I can't see any other way to do it. I'll stick this in to help anyone else who comes across this issue.
The issue boiled down to passing the current instance of the service interface to the ViewModel. The only place I could find that the instance was being set was the constructor of my controller. So very simply I declared a public global variable of the interface service type and saved the instance to that. The current instance persits and can be passed to the constructor of my viewmodel and satisfy the viewmodel constructors requirement. To clarify I've included an example of the controller and a viewmodel.
Controller:
public class AdminController : Controller
{
private readonly IAdminMenuService lmService;
public IAdminMenuService testService;
public AdminController(IAdminMenuService layoutMarkupService)
{
this.lmService = layoutMarkupService;
testService = lmService;
}
public ActionResult Index()
{
return View();
}
public PartialViewResult menuPartial()
{
return PartialView("_AdminMenuPartial", new adminMenuVM(testService));
}
ViewModel:
public class adminMenuVM
{
private readonly IAdminMenuService menuService;
public adminMenuVM(IAdminMenuService AdminMenuService)
{
this.menuService = AdminMenuService;
menuItems = getMenuItems();
menuCats = getMenuCats();
}
}