C# 如何在CompositeCommand上进行控制反转?

C# 如何在CompositeCommand上进行控制反转?,c#,mvvm,inversion-of-control,prism,C#,Mvvm,Inversion Of Control,Prism,我有以下ViewModel,其中我在构造函数中实例化CompositeCommand: public class ViewImportPreviewViewModel:BindableBase { private IEventAggregator eventAggregator; //event aggregator to enable Studio button in different ViewModel private readonly IRe

我有以下ViewModel,其中我在构造函数中实例化CompositeCommand:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand FinalizeImportClick{get;set;}//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            FinalizeImportClick = new CompositeCommand();
            FinalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
公共类ViewImportPreviewViewModel:BindableBase
{
私有IEventAggregator eventAggregator;//事件聚合器,用于在不同的ViewModel中启用Studio按钮
专用只读IRegionManager regionManager;//用于导航到主菜单的区域管理器
public CompositeCommand FinalizeImport单击{get;set;}//composite命令为finalize导入注册多个命令单击
public ViewImportPreviewViewModel(IRegionManager regionManager,IEventAggregator eventAggregator)//构造函数
{
this.eventAggregator=eventAggregator;
this.regionManager=regionManager;
FinalizeImportClick=新建复合命令();
FinalizeImportClick.RegisterCommand(新建DelegateCommand(NavigateToMain));//为FinalizeImport按钮单击注册代理命令
}
//使用finalize按钮注册的firs委托命令的订户方法单击
私有void NavigateToMain(字符串参数)
{
//它在导入后启用studio按钮,并将其发送到主菜单view XAML
eventAggregator.GetEvent().Publish(“ImportDone”);
//导入后,它会导航到主菜单
RequestNavigate(“ScreenNavigationRegion”,参数);
//发布主按钮viewmodel的事件,然后在那里尝试淡入主按钮
eventAggregator.GetEvent().Publish(“ImportDone”);
}
}
现在我想进行控制反转,在类外部实例化CompositeCommand,然后通过Unity容器注入它,如下所示:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            this.finalizeImportClick = finalizeImportClick;
            finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
    //Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
    CompositeCommand SaveAllCommand { get; }
}

public static class GlobalCommands
{
    public static CompositeCommand SaveAllCommand = new CompositeCommand();
}

//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
    public CompositeCommand SaveAllCommand
    {
        get { return GlobalCommands.SaveAllCommand; }
    }
}
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
        // and remove the call to a static class in our VM.  This keeps us testable.
        Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();
公共类ViewImportPreviewViewModel:BindableBase
{
私有IEventAggregator eventAggregator;//事件聚合器,用于在不同的ViewModel中启用Studio按钮
专用只读IRegionManager regionManager;//用于导航到主菜单的区域管理器
public CompositeCommand finalizeImportClick;//复合命令注册多个命令以完成导入按钮单击
public ViewImportPreviewViewModel(IRegionManager区域管理器、IEventAggregator事件聚合器、CompositeCommand和finalizeImportClick)//构造函数
{
this.eventAggregator=eventAggregator;
this.regionManager=regionManager;
this.finalizeImportClick=finalizeImportClick;
finalizeImportClick.RegisterCommand(新建DelegateCommand(NavigateToMain));//为FinalizeImport按钮单击注册代理命令
}
//使用finalize按钮注册的firs委托命令的订户方法单击
私有void NavigateToMain(字符串参数)
{
//它在导入后启用studio按钮,并将其发送到主菜单view XAML
eventAggregator.GetEvent().Publish(“ImportDone”);
//导入后,它会导航到主菜单
RequestNavigate(“ScreenNavigationRegion”,参数);
//发布主按钮viewmodel的事件,然后在那里尝试淡入主按钮
eventAggregator.GetEvent().Publish(“ImportDone”);
}
}
然后在模块初始化时,我执行以下操作:

  CompositeCommand myCommand = new CompositeCommand();
  container.RegisterInstance<CompositeCommand>(myCommand);
CompositeCommand myCommand=新的CompositeCommand();
容器注册状态(myCommand);
我没有得到任何错误,但是
NavigateToMain(字符串参数)
不会被调用,尽管命令已注册


我尝试注册类型,但是CompositeCommand继承了ICommand接口,该接口不包含
RegisterCommand
方法的定义。

实际上,CompositeCommand是单例/静态的是很常见的,因为多个松散耦合的模块将为同一CompositeCommand注册。这是标准的,也是预期的

当然,您希望这样做以保持ViewModel的可测试性。您希望通过ctor了解您的依赖关系。您不想在VM中调用静态方法

您要做的是创建一个像IAApplicationCommand这样的自定义接口,并为要公开的每个CompositeCommand提供属性,然后确保在容器中注册该接口。我还建议您提供一个静态版本,这样您就可以将按钮数据绑定到compositeCommands,而不必引用绑定,这非常好

所以可能是这样的:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            this.finalizeImportClick = finalizeImportClick;
            finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
    //Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
    CompositeCommand SaveAllCommand { get; }
}

public static class GlobalCommands
{
    public static CompositeCommand SaveAllCommand = new CompositeCommand();
}

//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
    public CompositeCommand SaveAllCommand
    {
        get { return GlobalCommands.SaveAllCommand; }
    }
}
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
        // and remove the call to a static class in our VM.  This keeps us testable.
        Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();
然后像这样注册:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            this.finalizeImportClick = finalizeImportClick;
            finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
    //Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
    CompositeCommand SaveAllCommand { get; }
}

public static class GlobalCommands
{
    public static CompositeCommand SaveAllCommand = new CompositeCommand();
}

//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
    public CompositeCommand SaveAllCommand
    {
        get { return GlobalCommands.SaveAllCommand; }
    }
}
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
        // and remove the call to a static class in our VM.  This keeps us testable.
        Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();
//将我们的全局命令facade注册到容器中作为IGlobalCommands接口,以便我们可以在VM构造函数中请求此服务
//并删除对VM中静态类的调用。这使我们可以测试。
Container.RegisterType();

实际上,CompositeCommand通常是单例/静态的,因为多个松散耦合的模块将为同一个CompositeCommand注册。这是标准的,也是预期的

当然,您希望这样做以保持ViewModel的可测试性。您希望通过ctor了解您的依赖关系。您不想在VM中调用静态方法

您要做的是创建一个像IAApplicationCommand这样的自定义接口,并为要公开的每个CompositeCommand提供属性,然后确保在容器中注册该接口。我还建议您提供一个静态版本,这样您就可以将按钮数据绑定到compositeCommands,而不必引用绑定,这非常好

所以可能是这样的:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            this.finalizeImportClick = finalizeImportClick;
            finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
    //Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
    CompositeCommand SaveAllCommand { get; }
}

public static class GlobalCommands
{
    public static CompositeCommand SaveAllCommand = new CompositeCommand();
}

//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
    public CompositeCommand SaveAllCommand
    {
        get { return GlobalCommands.SaveAllCommand; }
    }
}
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
        // and remove the call to a static class in our VM.  This keeps us testable.
        Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();
然后像这样注册:

 public class ViewImportPreviewViewModel:BindableBase
    {
        private IEventAggregator eventAggregator;  //event aggregator to enable Studio button in different ViewModel

        private readonly IRegionManager regionManager; //region manager for navigation to the main menu

        public CompositeCommand finalizeImportClick;//composite command to register multiple command for finalize import button click


        public ViewImportPreviewViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, CompositeCommand finalizeImportClick) //constructor
        {
            this.eventAggregator = eventAggregator;
            this.regionManager = regionManager;

            this.finalizeImportClick = finalizeImportClick;
            finalizeImportClick.RegisterCommand(new DelegateCommand<string>(NavigateToMain)); //register a delegate command for finalize import button click


        }


        //subscriber method to the firs delegate command registered with finalize button click
        private void NavigateToMain(string argument) 
        {
            //it enables the studio button after import and sends it to the main menu view XAML
            eventAggregator.GetEvent<ButtonEnableEvent>().Publish("ImportDone");

            //it navigates to the main menu after import
            regionManager.RequestNavigate("ScreenNavigationRegion", argument); 

            //publish an event for the main buttons viewmodel and then over there try to fade in main buttons
            eventAggregator.GetEvent<FadeinButtonsEvent>().Publish("ImportDone");
        }


    }
    //Create an interface to abstract away the implementation of the static GlobalCommands class
public interface IGlobalCommands
{
    CompositeCommand SaveAllCommand { get; }
}

public static class GlobalCommands
{
    public static CompositeCommand SaveAllCommand = new CompositeCommand();
}

//Create a facade around the static GlobalCommands class
public class GloablCommandsFacade : IGlobalCommands
{
    public CompositeCommand SaveAllCommand
    {
        get { return GlobalCommands.SaveAllCommand; }
    }
}
//register our global commands facade with the container as the IGlobalCommands interface so that we can ask for this service in our VM constructors
        // and remove the call to a static class in our VM.  This keeps us testable.
        Container.RegisterType<IGlobalCommands, GloablCommandsFacade>();
//将我们的全局命令facade注册到容器中作为IGlobalCommands接口,以便我们可以在VM构造函数中请求此服务
//并删除对