views:

104

answers:

2

In Ninject there's automatic implicit self-binding for concrete types. So without further configuration I can resolve every type in my application, like:

Foo foo = Kernel.Get(typeof(Foo));

Now if I need an Array of Foo, how would I do that?

Foo[] foos = Kernel.Get(typeof(Foo[])); // does not work

EDIT:

For clarification, here is, what I'm actually trying to achieve: In an ASP.NET MVC application I have an AutoMapViewResult (like Jimmy Bogard is talking about in this great(!) video: http://www.viddler.com/explore/mvcconf/videos/1/ or in ASP.NET MVC 2 in Action). The difference is, that I need to inject some service to the constructor of my view model before mapping the entity to it with AutoMapper. If the source type is an array I also must instantiate an array of the view model.

So here finally some (simplified) code :-)

public class EventsEditModel
{
    // some properties here
    public Location[] Locations { get; set; }
    public EventsEditModel(ILocationService locationService)
    {
        Locations = locationService.GetAll().ToArray();
    }
}
public class EventsListModel
{
    // some properties here
}

and here my AutoMapViewResult:

public class AutoMapViewResult : ViewResult
{
    public AutoMapViewResult(object model, Type sourceType, Type destinationType)
    {
        if (model != null)
        {
            var viewModel = IoC.Resolve(destinationType);
            ViewData.Model = Mapper.Map(model, viewModel, sourceType, destinationType);
        }
    }
}

This works great with EventsEditModel. My Index view requires an EventsListModel[], so I need to instantiate an array, which throws a System.ArgumentNullException: Value cannot be null. Parameter name: source (in the line var viewModel = IoC...)

Note: IoC.Resolve(Type serviceType) is just a wrapper for Kernel.Get(Type serviceType)

A: 

Guessing: Did you mean to write this instead?

Foo foo = Kernel.Get<Foo>();

Foo[] foos = Kernel.Get<Foo[]>();
Timwi
I need to use the non-generic Get function because the type is not known at compile time. Have a look at my edited question.
Dave
A: 

Ok, finally I found some workaround for my AutoMapViewResult. It works but seems a bit like a hack to me... However, here it is:

public class AutoMapViewResult<TSource, TDestination> : ViewResult
{
    public AutoMapViewResult(string viewName, string masterName, object model)
    {
        ViewName = viewName;
        MasterName = masterName;

        if (model.GetType().IsArray)
        {
            var viewModel = new List<TDestination>();
            foreach (var item in (TSource[])model)
            {
                viewModel.Add(Mapper.Map<TSource, TDestination>((TSource)item, IoC.Resolve<TDestination>()));
            }
            ViewData.Model = viewModel.ToArray();
        }
        else if (model.GetType().IsGenericType)
        {
            var viewModel = new List<TDestination>();
            foreach (var item in (IEnumerable<TSource>)model)
            {
                viewModel.Add(Mapper.Map<TSource, TDestination>((TSource)item, IoC.Resolve<TDestination>()));
            }
            ViewData.Model = viewModel;
        }
        else
        {
            ViewData.Model = Mapper.Map<TSource, TDestination>((TSource)model, IoC.Resolve<TDestination>());
        }
    }
}

The generic parameters TSource and TDestination describe always sinlge object, not arrays. So to map an array, this is the code to use it:

public ActionResult Index()
{
    var list = orderRepository.GetAll();
    return new AutoMapViewResult<Order, OrdersListModel>(null, null, list)
}

The AutoMapViewResult then checks, if the model, that is passed to the constructor is an array or a generic list and builds that up.

Dave
Just one note: Thinking about it, I asked myself if it could even be possible for an IoC container return an array, if I don't specify it's length...
Dave