Передача объектов массива параметров как out

Как мне потребовать, чтобы все объекты в массиве параметров передавались как выходные? В моем следующем коде я знаю, что он терпит неудачу, потому что мои исходные параметры никогда не назначаются и, следовательно, равны нулю. Несмотря на то, что я думаю, что они будут переданы в качестве ссылки без явного указания на это, похоже, это не так. В результате мне пришлось попытаться передать все это как выходной параметр.

Вот части моего кода, которые я считаю важными.

ChatController(некоторые элементы удалены)

class ChatController : ControllerBase
{
    #region Views

    ChatAreaView viewChatArea;
    UserListView viewUserArea;
    MessageView viewMessageArea;
    LoginPromptView viewLoginPrompt;

    #endregion

    #region ViewModels

    ChatAreaViewModel viewModelChatArea;
    UserAreaViewModel viewModelUserArea;
    MessageAreaViewModel viewModelMessageArea;
    LoginPromptViewModel viewModelLoginPrompt;

    #endregion
    public override void CreateViewsAndViewModels()
    {
        //InitializeViewAndViewModel(out viewChatArea, out viewModelChatArea);
        //InitializeViewAndViewModel(out viewMessageArea, out viewModelMessageArea);
        //InitializeViewAndViewModel(out viewUserArea, out viewModelUserArea);
        //InitializeViewAndViewModel(out viewLoginPrompt, out viewModelLoginPrompt);

        InitializeViewsAndViewModels(new FrameworkElement[] { viewChatArea, viewUserArea, viewMessageArea, viewLoginPrompt },
                                     new object[] { viewModelChatArea, viewModelUserArea, viewModelMessageArea, viewModelLoginPrompt });
    }
}

ControllerBase (некоторые элементы удалены)

public abstract class ControllerBase : PrismBase
{
    public void InitializeViewAndViewModel<TView, TViewModel>(out TView view, out TViewModel viewModel)
        where TView : FrameworkElement, new()
        where TViewModel : new()
    {
        view = new TView();
        viewModel = new TViewModel();

        view.DataContext = viewModel;
    }

    public void InitializeViewsAndViewModels(FrameworkElement[] views, object[] viewModels)
    {
        if (views.Length != viewModels.Length)
            throw new ArgumentOutOfRangeException("views and viewModels must have the same number of elements.");

        for (int i = 0; i < views.Length -1 ; i++)
            InitializeViewAndViewModel(out views[i], out viewModels[i]);
    }
}

Проблемная зона здесь

public void InitializeViewsAndViewModels(FrameworkElement[] views, object[] viewModels)
{
}

Все эти объекты, которые я передаю методу, остаются нулевыми, когда метод возвращается.

InitializeViewsAndViewModels(new FrameworkElement[] { viewChatArea, viewUserArea, viewMessageArea, viewLoginPrompt },
                             new object[] { viewModelChatArea, viewModelUserArea, viewModelMessageArea, viewModelLoginPrompt });

Я хочу потребовать передачи всех объектов массива views и viewModels как исходящих, но я могу только потребовать, чтобы весь массив передавался как исходящий.

Что я могу здесь сделать?

РЕДАКТИРОВАТЬ: Вся проблема, кажется, связана с формой множественного числа метода, как я описал выше. Если бы я избавился от этого и просто сделал это...

public override void CreateViewsAndViewModels()
{
    InitializeViewAndViewModel(out viewChatArea, out viewModelChatArea);
    InitializeViewAndViewModel(out viewMessageArea, out viewModelMessageArea);
    InitializeViewAndViewModel(out viewUserArea, out viewModelUserArea);
    InitializeViewAndViewModel(out viewLoginPrompt, out viewModelLoginPrompt);

    //InitializeViewsAndViewModels(new FrameworkElement[] { viewChatArea, viewUserArea, viewMessageArea, viewLoginPrompt },
    //                             new object[] { viewModelChatArea, viewModelUserArea, viewModelMessageArea, viewModelLoginPrompt });
}

все работает просто плавно.


person Cowman    schedule 05.09.2012    source источник


Ответы (2)


У вас не может быть массивов значений out в C#.

Теперь то, что вы пытаетесь сделать, очень странно, и даже если массивы out будут поддерживаться, вы все равно столкнетесь с проблемами - вы теряете типы переменных в своих массивах, поэтому нет разумного способа правильно их обновить.

Ваши текущие универсальные методы имеют несколько реализаций в производных классах - по одной на пару типов (т.е. ваши ChatController имеют то, что вы можете рассматривать как 4 отдельные реализации InitializeViewAndViewModel для каждой конкретной пары представлений). Ваш недавно предложенный код должен был бы каким-то образом найти эту отсутствующую информацию о типе...

person Alexei Levenkov    schedule 05.09.2012
comment
Если я избавлюсь от метода InitializeViewsAndViewModels (множественное число) и вместо этого вызову метод InitializeViewAndviewModel (единственное число) для каждой пары представлений и ViewModels, как вы видите в закомментированной области, все будет работать нормально. Причина, по которой мне нужна форма множественного числа, заключается в том, что я могу еще больше уменьшить объем кода в моем классе контроллера, чтобы это была одна строка вместо числа x для каждой пары представления/модели представления, которая у меня есть. Как я могу это сделать? Единственное число работает достаточно хорошо, так почему бы и множественное число? В конце концов, это просто вызов единственного метода. - person Cowman; 05.09.2012
comment
@Cowman, я пытался объяснить, почему метод единственного числа работает и не может быть преобразован в метод единственного множественного числа, который вы хотите, но я не силен в этом ... так что читайте дженерики, чтобы увидеть, как на самом деле 4 логических метода в вашем текущем сорт. Что касается инициализации, я думаю, что проще всего было бы использовать отражение для установки всех полей определенного базового типа (или с определенными атрибутами). Обратите внимание, что то, что вы пытаетесь сделать, может не иметь практической ценности для улучшения/удобства использования (если вы действительно пытаетесь реализовать класс контроллера MVC). - person Alexei Levenkov; 05.09.2012
comment
Я не совсем понимаю, о чем вы говорите... но я думаю, что немного уловил суть. Вы говорите, что моя идея использовать дженерики для создания и инициализации моих различных представлений и моделей представления — плохая идея? Я подумал, что это хорошо, потому что это помогло мне избежать дублирования кода, который у меня был раньше, при обновлении и назначении контекста данных для представления. - person Cowman; 06.09.2012
comment
@Cowman, нет, использование дженериков - хорошая и эффективная идея. Это просто не подходит для случая, когда у вас нет информации о типе. В чем я не вижу ценности, так это в инициализации (или даже сохранении) нескольких ViewModel и Views на контроллере, но это может быть совершенно правильным для вашего конкретного случая. - person Alexei Levenkov; 06.09.2012
comment
Ну... Я делаю это, потому что не знаю ничего лучшего. Я использую подход MVVM с контроллерами, который я узнал от HiTechMagic в stackoverflow. За исключением... Я недостаточно знаю об этом в исполнении. Я решил, что мой контроллер должен знать обо всех представлениях и моделях представления... поскольку он несет ответственность за их создание и назначение их свойств. Для представления w он назначает контекст данных (модель представления), а для модели представления назначает все свойства и команды. И в ходе выполнения он продолжает обновлять свойства модели представления. Я просто не знаю лучше. - person Cowman; 06.09.2012
comment
Вы находитесь в MVVM/WPF... нужно больше кофе :) забудьте все, что я сказал о моделях представления - почему-то я думал, что вы находитесь в ASP.Net MVC, где это будет выглядеть странно... - person Alexei Levenkov; 06.09.2012
comment
давайте продолжим обсуждение в чате - person Cowman; 06.09.2012

Используйте исх. Смотри ниже:

class ChatController : ControllerBase
    {
        #region Views

        ChatAreaView viewChatArea;
        //UserListView viewUserArea;
        //MessageView viewMessageArea;
        //LoginPromptView viewLoginPrompt;

        #endregion

        #region ViewModels

        ChatAreaViewModel viewModelChatArea;
        //UserAreaViewModel viewModelUserArea;
        //MessageAreaViewModel viewModelMessageArea;
        //LoginPromptViewModel viewModelLoginPrompt;

        #endregion
        public void CreateViewsAndViewModels()
        {
            //InitializeViewAndViewModel(out viewChatArea, out viewModelChatArea);
            //InitializeViewAndViewModel(out viewMessageArea, out viewModelMessageArea);
            //InitializeViewAndViewModel(out viewUserArea, out viewModelUserArea);
            //InitializeViewAndViewModel(out viewLoginPrompt, out viewModelLoginPrompt);
            var a  = new FrameworkElement[] { viewChatArea };
            var b = new object[] { viewModelChatArea};
            InitializeViewsAndViewModels(a,
                                         b);
        }
    }

public abstract class ControllerBase 
    {
        public void InitializeViewAndViewModel<TView, TViewModel>(ref TView view, ref TViewModel viewModel)
            where TView : FrameworkElement, new()
            where TViewModel : new()
        {
            view = new TView();
            viewModel = new TViewModel();

            view.DataContext = viewModel;
        }

        public void InitializeViewsAndViewModels(FrameworkElement[] views, object[] viewModels)
        {
            if (views.Length != viewModels.Length)
                throw new ArgumentOutOfRangeException("views and viewModels must have the same number of elements.");

            for (int i = 0; i < views.Length; i++)
                InitializeViewAndViewModel(ref views[i], ref viewModels[i]);
        }
    }
person ncfuncion    schedule 05.09.2012
comment
Я пробовал это, но результат тот же. Во всех методах представление и ViewModel назначаются как соответствующие им типы. См. i.imgur.com/nAie8.jpg Однако, когда метод возвращается... Это происходит i.imgur.com/5GdBd.jpg Но подождите... Кажется, я вижу проблему . На самом деле он возвращает все значения правильно, кроме одного из них... Позвольте мне посмотреть, смогу ли я понять, почему. - person Cowman; 05.09.2012
comment
Оказывается, я не удалял свои представления. Длина - 1, чтобы отразить ваши... Но тем не менее представления и модели представлений отображаются правильно, но фактические вспомогательные поля по-прежнему пусты... См. следующее i.imgur.com/WhF10.jpg Так что мне пришлось бы вернуться и вручную назначить все мои поля соответствующим элементам массивов. Почему это? Разве это не должно быть передано по ссылке? - person Cowman; 05.09.2012