Dependency injection and interfaces

Topics: CAB & Smart Client Software Factory
Dec 1, 2005 at 3:13 PM
originally posted by: ajvar2

Wondering is there a way of using the dependency injection in CAB to inject objects based on an interface.

For example if I had an interface IMyInterface and a View had property of type IMyInterface.
How could I inject different implementations of that interface at run time using the workitem?
Dec 2, 2005 at 6:09 AM
originally posted by: DLorenz

Well, you can inject non-cab objects into the WorkItem by doing theWorkItem.Items.AddNew(Of SomeClass).
Dec 2, 2005 at 8:09 AM
originally posted by: nidgir

that doesn't resolve the problem though ...
if you'd want to use the mvp pattern, the view (ie smartpart) should implement an interface and the controller (ie presenter) should receive in it's constructor automatically a reference to the view

view ...

public class SomeView : Control, IMyView
{ ... }

controller

public class SomeViewPresenter : Controller
{
InjectionConstructor
public SomeViewPresenter(Dependency IMyView, .... other dependencies (services)
{...

workitem

void foo()
{
Items.AddNew<SomeView>("mysomeView");
Items.AddNew<SomeViewPresenter>("mypresenter");
...
workspace.Show(Items"someView")
...


currently this doesn't work - or am i wrong ??
}
Dec 2, 2005 at 1:27 PM
originally posted by: BradWilsonMSFT

Injecting objects by interface is done through the services collection.

WorkItem.Services.AddNew can take a registration type (as does Add).
Dec 2, 2005 at 4:36 PM
originally posted by: ajvar2

Thanks Brad, ServiceDependancy works, able to change type of the controller at run time.

workitem.Services.Add<IControllerInterface>(new ConcreteController());


// and in the view
ServiceDependency()
public IControllerInterface Controller
{
set { controller = value; }
}
Dec 3, 2005 at 12:21 AM
originally posted by: nidgir

that might work, if not that smartparts (and the views in the mvp model are still smartparts) should have a name.

for example i've written an explore orders workitem, which opens a view, that contains two smartpart placeholders - they go for the name "search" and "detail".

then i have two views. one is SearchOrderView - thats a smartpart control, which implements ISearchOrderView ... this control has a presenter, with the name SearchOrderViewPresenter ... the presenter of course should use an instance of an object, that implements ISearchOrderView and some services (OrderService, CustomerService, etc.)

now i have a costructor in my presenter which looks like that:

public SearchOrderViewPresenter (ISearchOrderView searchView, IOrderService orderService, IShipperService shipperService, ICustomerService customerService)
{ ... }

and in my workitem i have to write that:

_searchView = Items.AddNew<SearchOrderView>("search");
_detailView = Items.AddNew<OrderDetailView>("detail");
_exploreView = Items.AddNew<ExploreOrderView>(); // contains the smartpart place holders
OrderDetailViewPresenter detailPresenter = new OrderDetailViewPresenter ((IOrderView) _detailView);
Items.Add(detailPresenter );
SearchOrderViewPresenter searchPresenter = new SearchOrderViewPresenter ((ISearchOrderView)_searchView, GetService<IOrderService>(), GetService<IShipperService>(), GetService<ICustomerService>());
searchPresenter OrderSelectionChanged += delegate(int orderId) { detailPresenter.ShowOrder(orderId); };
Items.Add(searchPresenter);

what i would expect to be able to write is that instead:

_searchView = Items.AddNew<SearchOrderView, ISearchOrderView>("search");
_detailView = Items.AddNew<OrderDetailView, IOrderDetailView>("detail");
_exploreView = Items.AddNew<ExploreOrderView>(); // contains the smartpart place holders
OrderDetailViewPresenter detailPresenter = Items.AddNew<OrderDetailViewPresenter>();
SearchOrderViewPresenter searchPresenter = Items.AddNew<SearchOrderViewPresenter>();
searchPresenter OrderSelectionChanged += delegate(int orderId) { detailPresenter.ShowOrder(orderId); };


this is how dependency injection in an mvp - model should work (at least that's my opinion)
Dec 3, 2005 at 7:46 AM
originally posted by: BradWilsonMSFT

Since non-services are found by name, rather than by type, there's no need to register with a separate type. This will work:

Items.AddNew<MyConcreteType>("Name");

...

IMyInterface itf = Items.Get<IMyInterface>("Name");

As long as MyConcreteType implements IMyInterface, this will succeed. You can see the implementation of the generic version of Get in ManagedObjectCollection simply does a cast for you of the result of the non-generic version of Get.
Dec 3, 2005 at 1:45 PM
originally posted by: nidgir

I knew that ...

I wanted to have constructor dependency injection of non services based upon interfaces in the controller - the workitem creates the view and the controller - the view will be injected into the controller using the interface it implements. As this does not seem possible, i will continue to instantiate the controller using it's constructor directly (passing all dependencies by hand). This is anyway better, because in this way i can test my controllers without any dependency on the cab

thx for your patience