Разрешить массив с Ninject - PullRequest
       13

Разрешить массив с Ninject

1 голос
/ 16 августа 2010

В Ninject есть автоматическое неявное самосвязывание для конкретных типов. Поэтому без дальнейшей настройки я могу разрешить каждый тип в моем приложении, например:

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

Теперь, если мне нужен массив Foo, как бы я это сделал?

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

EDIT:

Для пояснения, вот что я на самом деле пытаюсь достичь: В приложении ASP.NET MVC у меня есть AutoMapViewResult (о котором Джимми Богард говорит в этом замечательном (!) Видео: http://www.viddler.com/explore/mvcconf/videos/1/ или ASP.NET MVC 2 в действии ). Разница в том, что мне нужно добавить какой-то сервис в конструктор моей модели представления, прежде чем сопоставить объект с AutoMapper. Если тип источника является массивом, я также должен создать экземпляр массива модели представления.

Итак, вот, наконец, некоторый (упрощенный) код: -)

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
}

и вот мой 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);
        }
    }
}

Это прекрасно работает с EventsEditModel. Мое представление индекса требует EventsListModel[], поэтому мне нужно создать экземпляр массива, который выдает System.ArgumentNullException: значение не может быть нулевым. Имя параметра: источник (в строке var viewModel = IoC...)

Примечание: IoC.Resolve(Type serviceType) - это просто оболочка для Kernel.Get(Type serviceType)

Ответы [ 2 ]

0 голосов
/ 24 августа 2010

Хорошо, наконец-то я нашел обходной путь для моего AutoMapViewResult. Это работает, но мне кажется, что взломать ... Но вот оно:

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>());
        }
    }
}

Общие параметры TSource и TDestination описывают всегда объект sinlge, а не массивы. Итак, чтобы отобразить массив, это код для его использования:

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

Затем AutoMapViewResult проверяет, является ли модель, переданная конструктору, массивом или общим списком, и создает его.

0 голосов
/ 16 августа 2010

Угадай: ты хотел написать это вместо этого?

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

Foo[] foos = Kernel.Get<Foo[]>();
...