【问题标题】:Passing parameter array objects as out将参数数组对象作为 out 传递
【发布时间】:2012-09-05 04:54:00
【问题描述】:

如何要求参数数组中的所有对象都作为 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 });

我想要求将所有 viewsviewModels 数组对象作为 out 传递,但我似乎只能要求整个数组本身作为 out 传递。

我可以在这里做什么?

编辑:正如我上面所描述的,整个问题似乎源于该方法的复数形式。如果我摆脱了它,我只是这样做了......

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

一切都很顺利。

【问题讨论】:

    标签: c# wpf generics parameters out


    【解决方案1】:

    在 C# 中不能有 out 值的数组。

    现在您要做的事情很奇怪,即使支持out 的数组,您仍然会遇到麻烦-您正在丢失数组中的变量类型,因此没有合理的方法来新它们正确起来。

    您当前的泛型方法在派生类中有多个实现 - 每对类型一个(即您的 ChatController 具有您可以将其视为特定一对视图的 InitializeViewAndViewModel 的 4 个不同实现)。您新提出的代码必须以某种方式找到丢失的类型信息......

    【讨论】:

    • 如果我摆脱 InitializeViewsAndViewModels(plural) 方法,而是为每对视图和 ViewModel 调用 InitializeViewAndviewModel(singular) 方法,就像您在注释掉的区域中看到的那样,一切正常。我想要复数形式的原因是我可以进一步减少我的 Controller 类中的代码量,以便它是单行而不是我拥有的每对视图/视图模型的 x 数。我怎样才能做到这一点?单数的效果很好,为什么不复数呢?毕竟只是调用了单数方法。
    • @Cowman,我试图解释为什么单数方法有效并且不能转换为你想要的单一“复数”方法,但我不擅长那个......所以请阅读泛型看看它实际上是如何在您当前的课程中使用 4 个逻辑方法的。至于初始化 - 我认为最简单的方法是使用反射来设置特定基本类型(或具有特定属性)的所有字段。旁注,您尝试做的事情在使事情变得更好/更可用方面可能没有实际价值(如果您确实正在尝试实现 MVC 控制器类)。
    • 我不是很清楚你在说什么......但我想我有点明白它的要点了。你是说我使用泛型来创建和初始化我的不同视图和视图模型的想法是个坏主意?我认为这很好,因为它帮助我避免了之前在更新和将数据上下文分配给视图时遇到的一堆重复代码。
    • @Cowman,不,使用泛型是一个不错且有效的想法。它只是不能很好地转化为您没有类型信息的情况。我看不到的价值是在控制器上初始化(甚至存储)多个 ViewModel 和 View,但它可能对您的特定情况完全有效。
    • 嗯...我这样做是因为我不知道更好。我正在采用带有控制器的 MVVM 方法,这是我从 Stackoverflow 上的 HiTechMagic 学到的。除了......我对它的执行了解不够。我认为我的控制器需要了解所有视图和视图模型......因为它有责任创建它们并分配它们的属性。对于视图,它分配数据上下文(视图模型),对于视图模型,它分配所有属性和命令。在执行过程中,它会不断更新视图模型的属性。我只是不知道更好。
    【解决方案2】:

    使用参考。见下文:

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

    【讨论】:

    • 我试过这个,但结果相同。在所有方法中,视图和 ViewModel 被分配为它们各自的类型。请参阅i.imgur.com/nAie8.jpg 但是当方法返回时......这会发生i.imgur.com/5GdBd.jpg 但是等等......我想我看到了一个问题。它实际上正确地返回了所有值,除了其中一个......让我看看我是否能找出原因。
    • 原来是我没有删除我的意见。长度 - 1 以反映你的......但是,意见和 viewModels 显示正确,但实际的支持字段仍然为空......请参阅关注i.imgur.com/WhF10.jpg 所以我必须返回并手动将我的所有字段分配给数组的适当元素。这是为什么?不应该都是引用传递吗?
    猜你喜欢
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 2016-08-28
    • 2012-07-13
    • 2023-04-02
    相关资源
    最近更新 更多