【问题标题】:C# Set Dictionary<String, Object> Values using ReflectionC# 使用反射设置 Dictionary<String, Object> 值
【发布时间】:2015-04-21 18:21:34
【问题描述】:

我有以下工作代码,它使用程序集从加载的 .dll 中打开一个表单

Form main = (Form)CommandFacade.IModuleHandler.IHost as Form;
Assembly Assembly = (Assembly)IArticles.Assembly;
Type Type = Assembly.GetType("DAMS.Module.ARTICLES.Articles_Search", true);
Form Articles_Search = (Form)Activator.CreateInstance(Type) as Form;        
Articles_Search.MdiParent = main;
Articles_Search.StartPosition = FormStartPosition.CenterScreen;
Articles_Search.Show();

但我已经在此表单中声明了 1 个字典 (FormBehavior) 和 1 个列表 (HiddenColumns),我需要为此字典设置值并使用反射将项目添加到列表中。 通常我使用这段代码,但我如何使用反射来做到这一点?

Articles_Search.FormBehavior["Control"] = "Value";
Articles_Search.HiddenColumns.Add("article_cost");

这是 Article_Search 类:

public partial class Articles_Search : Form
{
    // Actions Vars
    public List<String> HiddenColumns = new List<String>();
    public Dictionary<String, Object> FormBehavior = new Dictionary<String, Object> { "Control", null } };
}

【问题讨论】:

  • HiddenColumns 不是字典?那么您是否也在询问如何使用反射将元素添加到列表中?
  • @MartinLiversage 抱歉,我需要在字典FormBehavior 中更改此键Control 的值并将项目添加到List&lt;String&gt; HiddenColumns,两者都使用反射。谢谢。

标签: c# winforms dictionary reflection mef


【解决方案1】:

您要使用反射设置的属性名为Item

var itemPropertyInfo = dictionary.GetType().GetProperty("Item");

SetValue 方法有一个重载,该方法接受 Item 属性所需的参数:

itemPropertyInfo.SetValue(dictionary, value, new[] { key });

按照说明使用反射相当于执行以下代码:

dictionary[key] = value;

以上是关于如何使用反射在字典中设置值的一般答案。为了回答您还涉及列表和可能是私有字段的具体问题,我提供了以下代码:

var formBehaviorFieldInfo = Articles_Search
  .GetType()
  .GetField("FormBehavior", BindingFlags.NonPublic | BindingFlags.Instance);
var formBehavior = formBehaviorFieldInfo.GetValue(Articles_Search);
var itemPropertyInfo = formBehavior.GetType().GetProperty("Item");
itemPropertyInfo.SetValue(formBehavior, "Control", new[] { "Value" });

var hiddenColumnsFieldInfo = Articles_Search
  .GetType()
  .GetField("HiddenColumns", BindingFlags.NonPublic | BindingFlags.Instance);
var hiddenColumns = hiddenColumnsFieldInfo.GetValue(Articles_Search);
var addMethodInfo = hiddenColumns.GetType().GetMethod("Add");
addMethodInfo.Invoke(hiddenColumns, new[] { "article_cost" });

【讨论】:

  • 感谢您的回复,但假设变量FormBehaviorHiddenColumnsArticles_Search 表单中声明;我如何访问它们以使用反射更改它们。因为我也通过反射访问表单:Form Articles_Search = (Form)Activator.CreateInstance(Type) as Form;
  • @JonathanEdgardo:通过Articles_Search 表单实例访问字典和列表。这假定字典和列表字段是公共的。否则,您需要使用反射来访问私有字段,但您没有提到这是您问题中的问题。
  • 感谢您的耐心等待,是的,如果您看到我正在使用 Assembly 访问表单 Articles_Search,因为它存储在 .dll Type Type = Assembly.GetType("DAMS.Module.ARTICLES.Articles_Search", true); 中,但我真正的问题是修改变量(字典和List) 在实例化的表单中。
  • 谢谢你正是我需要做的我只需将BindingFlags.NonPublic更改为BindingFlags.Public
  • @progLearner 我的答案并不特定于值类型(相对于引用类型)。您必须按照说明使用PropertyInfovalue 的类型必须与字典中值的类型相匹配,因此如果字典的类型为 Dictionary&lt;int, Customer&gt;,那么 value 应该是 Customer 对象实例
【解决方案2】:

在这种情况下,以下答案是不正确的。我错过了在编译时没有引用程序集。


我完全不明白你为什么需要反思。您已经拥有所需类的实例,因此您可以直接访问公共字段和属性。但是您没有“看到”这些字段或属性,因为您的变量是Form 类型。试试这个:

Form main = (Form)CommandFacade.IModuleHandler.IHost;
Assembly Assembly = (Assembly)IArticles.Assembly;
Type Type = Assembly.GetType("DAMS.Module.ARTICLES.Articles_Search", true);
Articles_Search searchForm = (Articles_Search)Activator.CreateInstance(Type);        
searchForm.MdiParent = main;
searchForm.StartPosition = FormStartPosition.CenterScreen;
searchForm.FormBehavior["Control"] = "Value";
searchForm.HiddenColumns.Add("article_cost");
searchForm.Show();

旁注:如果您已经在使用强制转换运算符,则不需要 as 运算符。

【讨论】:

  • 我假设在编译时没有引用带有表单的程序集,因此需要反射来创建以及访问和使用表单。
猜你喜欢
  • 2012-03-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多