gpt4 book ai didi

c# - 如何通过动态反射在运行时创建 RelayCommand 的实例?

转载 作者:行者123 更新时间:2023-12-03 10:39:17 25 4
gpt4 key购买 nike

我正在 WPF 中构建一个 MVVM 应用程序,并将一个 Menu 绑定(bind)到一个 MenuItem 模型。我的 MenuItem 类具有以下属性:

public class MenuItem
{
private List<MenuItem> _Items;

public MenuItem(string header, ICommand command)
{
Header = header;
Command = command;
}

public MenuItem()
{

}

public string Header { get; set; }

public List<MenuItem> Items
{
get { return _Items ?? (_Items = new List<MenuItem>()); }
set { _Items = value; }
}

public ICommand Command { get; set; }
public string CommandName { get; set; }
public object Icon { get; set; }
public bool IsCheckable { get; set; }
public bool IsChecked { get; set; }
public bool Visible { get; set; }
public bool IsSeparator { get; set; }
public string ToolTip { get; set; }
public int MenuHierarchyID { get; set; }
public int ParentMenuHierarchyID { get; set; }
public string IconPath { get; set; }
}

此 MenuItem 模型类由来自数据库的数据填充。在这个
在这种情况下,从 DB 填充的唯一属性是 CommandName。

假设它用字符串“OpenFile”填充它

编辑
这是我的 MenuViewModelConstructor:
    public MenuViewModel(MainViewModel _MainViewModel)
{
....
}

它依赖于 MainViewModel,因为这是 OpenFile 和 CanOpenFile 方法所在的地方。

我的 MenuViewModel 有一个注册命令的方法,如下所示:
        private void RegisterMenuCommand(MenuItem item)
{
if(!string.IsNullOrEmpty(item.CommandName))
{
//How can I create a new RelayCommand instance from
//my CommandName string????
//e.g. item.Command = new RelayCommand(_MainViewModel.<item.CommandNameHere>, _MainViewModel."Can" + <item.CommandNameHere>
item.Command = new RelayCommand(_MainViewModel.OpenFile, _MainViewModel.CanOpenFile);
}

foreach(MenuItem child in item.Items)
{
RegisterMenuCommand(child);
}
}

顺便说一下,R​​elayCommand 的签名是:
public RelayCommand(Action execute, Func<bool> canExecute)

是否可以使用反射或动态 lambda 或类似的东西实例化我的 RelayCommand,以便我可以在运行时动态使用来自数据库的命令字符串?什么是最优化的方式?

编辑:解决方案
感谢@Nathan 为我指出了正确的解决方案,这是我的工作方法:
    private void RegisterMenuCommand(MenuItem item)
{
if(!string.IsNullOrEmpty(item.CommandName))
{
MethodInfo method1 = _MainViewModel.GetType().GetMethod(item.CommandName);
Delegate d1 = Delegate.CreateDelegate(typeof(Action),_MainViewModel, method1);

MethodInfo method2 = _MainViewModel.GetType().GetMethod("Can" + item.CommandName);
Delegate d2 = Delegate.CreateDelegate(typeof (Func<bool>),_MainViewModel, method2);

item.Command = new RelayCommand((Action)d1, (Func<bool>)d2);
}

foreach(MenuItem child in item.Items)
{
RegisterMenuCommand(child);
}
}

我正在使用 .NET 4.0

谢谢!

最佳答案

我在 Google 上快速搜索了有关使用反射创建代表的内容,发现这篇非常不错的文章 How to: Hook Up a Delegate Using Reflection

我在本地机器上创建了一个快速测试并让它工作

MethodInfo miHandler = typeof(MainWindow).GetMethod("OpenCommandHandler", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
Delegate d = Delegate.CreateDelegate(typeof(Action<object>), this, miHandler);
btnTest.Command = new DelegateCommand((Action<object>)d);

在哪里 thisCreateDelegate是我正在使用的 View (MainWindow)

你必须稍微调整一下才能让你的工作,但我想它会是这样的:
var obj = <object containing your method>

MethodInfo miHandler = typeof(obj).GetMethod(item.CommandName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
Delegate openDelegate = Delegate.CreateDelegate(typeof(Action), obj, miHandler);
item.Command = new RelayCommand((Action)openDelegate, ...);

关于c# - 如何通过动态反射在运行时创建 RelayCommand 的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11127377/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com