gpt4 book ai didi

c# - 在 C# 中使用反射创建菜单

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

我正在尝试使用 WPF TreeView 控件创建菜单。为此,我创建了一个接口(interface),它只公开几个只读属性(一个用于菜单标题,一个用于实际菜单项),我可以将 TreeView 控件绑定(bind)到这些属性。

我创建的每个 ViewModel 都将实现这个接口(interface),并且两个属性的值都将硬编码在属性的 getter 中。

是否可以使用反射来获取这些属性的值(在它们被实例化之前),并将它们放入我的 TreeView 控件可以绑定(bind)到的某种形式的列表或数组中?

目的是不必将所有菜单项硬编码到 TreeView,而是用我迄今为止编写的所有 ViewModel 填充控件(即,每次创建 View 模型时,它只会“出现”在菜单中,当然是在重新编译程序集之后!)。

我可以使用以下方法获取实现接口(interface)的类的名称:

foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype.GetInterfaces().Contains(typeof(IInterfaceName))))
{
c.Add(mytype);

}

此代码用于获取实现接口(interface)的类的名称,但在此之后我卡住了。

我想要做的甚至可能吗?如果我不在正确的轨道上,我也将不胜感激任何其他方法来实现相同的结果。我不想在 WPF 中硬编码值,也不想在创建新 View 模型时将记录添加到数据库中。

这是我正在尝试创建的模型:
Mockup

最佳答案

我强烈建议您查看 Managed Extensibility Framework (MEF)。 MVVM 和 MEF 非常适合,因为 MVVM 的目标最终是解耦单独的关注点,而 MEF 是一种使松散耦合变得非常容易的技术。 MVVM 关注分离单独的层,但将不同的 View 模型彼此分离也有一个优势(这基本上是您所要求的)。这是一个非常基本的示例,说明如何开始使用 MEF 来解决您的特定问题。

首先,您需要为 subview 模型制作一个界面:

public interface ISubViewModel
{
string Name { get; }
IView View { get; }
//... whatever else you need
}

现在,您将拥有某种父 View 或主视图:
[Export]
public class ParentViewModel
{
[ImportMany] // <- this attribute tells MEF to look for all exports of type ISubViewModel
public IEnumerable<ISubViewModel> ViewModels { get; set; }

//... whatever else you need
}

现在您可以简单地删除任意数量的 subview 模型,它们都会自动显示在 ParentViewModel 的 ViewModels 属性中:
[Export(typeof(ISubViewModel))]
public class MySubViewModel1 : ISubViewModel { /* ... */ }

[Export(typeof(ISubViewModel))]
public class MySubViewModel2 : ISubViewModel { /* ... */ }

[Export(typeof(ISubViewModel))]
public class MySubViewModel3 : ISubViewModel { /* ... */ }

唯一剩下的就是设置 MEF 容器。对于 [ImportMany]ParentViewModel 中工作的属性,我们必须让 MEF 构造它。我们将设置容器并要求它提供 ParentViewModel (也许这会出现在您的 App.xaml.cs 中)
public void Startup()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
var container = new CompositionContainer(catalog);
var parentViewModel = container.GetExportedValue<ParentViewModel>();
parentViewModel.Show();
}

在幕后,MEF 基本上以与您在示例中尝试的方式相同的方式使用反射,但 MEF 使它变得更容易并隐藏了所有反射的丑陋,您所要做的就是添加适当的 [Import][Export]属性。

使用 MEF 有点像 async/await,它倾向于“侵入”整个代码库。您制作的任何类(class)都可以使用 [Import][ImportMany] (或者构造函数注入(inject),参见文档),只要它是 [Export] -ed 并且它的实例由 MEF 检索。有关使用 MEF 的完整 MVVM 样式应用程序的一个很好的示例,请查看 WAF示例(还有其他使用 MEF 或其他类型 DI 的 MVVM 框架,但我个人最熟悉 WAF)。

像这样在整个应用程序中使用 MEF 的结果将是一个极其模块化和松耦合的应用程序,这对于可测试性来说绝对是非常棒的。

关于c# - 在 C# 中使用反射创建菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48697732/

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