Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 77050

Dependency Injection best practice ?

$
0
0

I am trying to use Dependency Injection in my project but its still new to me. I've read quite a lot of tutorials but I still don't what is the best practice to create pages or viewmodels..

It seems like everyone is saying, that Service Locator is a bad practice or "anti-pattern" and then they still proceed to do something like this inside of code behind:

_viewModel = IocContainer.Resolve<SomeViewModel>();

Isn't that killing purpose of IoC ?

I have been suggested to inject view model in page's constructor and then instantiate it somewhere else with factory. I should also mention, that I want to pass a parameter to a view model (apart from other injected services).

I'll give you example:

// Order detail
public class OrderDetailViewModel : BaseViewModel
{
public Order Order { get; set; }

public ICommand UpdateOrderCommand => new Command(UpdateOrder);

// I just made that up, so I have at least one service in a constructor
// because it makes things more complicated for me (but I need it), when I have something, that is injected (order manager)
// along with something, thats is passed (order)
private readonly IOrderManager _orderManager;

    public OrderDetailViewModel(Order order, IOrderManager orderManager)
    {
        Title = "Detail";
        Order = order;

    _orderManager = orderManager;
    }

private void UpdateOrder()
{
    _orderManager.Update(Order);
}

}

// This class holds list of orders and when I click on some order, order detail is displayed so I have to pass that order to an orderdetail view model
public class OrdersViewModel : BaseViewModel
{
public ObservableCollection Orders { get; set; }
public ICommand SelectOrderCommand => new Command(async (orderInfo) => await SelectOrder(orderInfo));

    private readonly IApiService _apiService;
private readonly INavigationService _navigation;
private readonly IViewModelFactory _factory;

// These services are injected as I would expect
public OrdersViewModel(INavigationService navigation, IApiService apiService, IViewModelFactory factory)
    {
    Title = "Orders";
    Orders = new ObservableCollection<OrderRowDto>();

    _navigation= navigation;
    _apiService = apiService;
    _factory = factory;
    }

private async Task SelectOrder(OrderRowDto orderInfo)
    {
    var order = await _apiService.GetOrderAsync(orderInfo.Id);

    // THIS IS WHERE I AM UNSURE. IF ITS OK TO DO IT THIS WAY
    var viewModel = _factory.CreateOrderDetailViewModel(order);
    await _navigation.PushAsync(new OrderDetailPage(viewModel));
}

}

//Factory
public class ViewModelFactory : IViewModelFactory
{
    // this will be injected
    private readonly IOrderManager _orderManager;

    public ViewModelFactory(IOrderManager orderManager)
    {
        _orderManager = orderManager;
    }

    public OrderDetailViewModel CreateOrderDetailViewModel(Order order)
    {
        return new OrderDetailViewModel(order, _orderManager);
    }
}

So I removed creation of view model from code behind, because this

_viewModel = IocContainer.Resolve<OrderDetailViewModel>();

would not allow me to pass that "Order" in constructor.

I know I could add this, If I would passed that order in page's constructor

_viewModel.Order = Order;

but it doesnt seems very nice.

So my question is, if that approach with factory is a good idea or not..
Because I dont want it to backfire later on
I was also wondering, if creating pages manually (new OrderDetailPage(..)) is good practice as well when attempting to use DI

Thank you. (sorry about code formating.. `` doesnt seems to do, what I want it to do)


Viewing all articles
Browse latest Browse all 77050

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>