向 ExpandoObject 添加未知(在设计时)属性

发布于 2024-09-04 09:23:13 字数 355 浏览 7 评论 0原文

只是探索 c# 4。尝试让我的头脑了解所有这些动态的东西。抱歉,如果这个问题很愚蠢,我没有这个领域的经验。

如果我有一个 ExpandoObject 并且想要在运行时向其添加公共属性(使用 get 和 set),我将如何去做呢?

例如,我有一个 documentTemplate 和一个文档,该文档有一个指向 documentTemplate 的属性。该文档模板有一些标签标题(例如学生发展的能力),在制作文档时应解决这些标签标题(例如浓度、记忆力等)。因此,一旦在文档中设置了模板,我想创建一个类,该类具有与模板中的标签标题同名的属性,然后使用一些 UI 元素,例如 PropertyGrid,我可以让用户根据标签标题填写标签值。

感谢您的阅读!

just exploring c# 4. Trying to get my head around all this dynamic stuff. Sorry if this question is silly, no experience in this domain.

If I have an ExpandoObject and want to add public properties (with get and set) to it at runtime, how would I go about doing it?

For example, I have a documentTemplate and a document, which has a property pointing towards the documentTemplate. This documentTemplate has got some tag Titles (eg. Capabilities developed among students), which should be addressed while making the document (eg. Concentration, memory etc.). So as soon as the template is set in the document, I want to create a class, which has properties with same names as the tag titles in the Template, and then using some UI element, such as the PropertyGrid, I can have the user fill in tag values against the tag Titles.

Thanks for reading!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白色秋天 2024-09-11 09:23:13

我想知道如何“动态”地将成员添加到类中,并提出了这个示例:

using System;
using System.Collections.Generic;
using System.Dynamic;

class Program
{
    static void Main()
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;

        p["A"] = "New val 1";
        p["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}

此代码片段的要点是成员 A 和 B 被定义为字符串文字(硬编码/字符串化)并通过 ExpandoObject 的 IDictionary 接口添加。我们通过直接访问键并输出到控制台来测试键的存在和值(并证明这个概念)。

I wondered how it might be possible to add members to a class "on the fly" and came up with this sample:

using System;
using System.Collections.Generic;
using System.Dynamic;

class Program
{
    static void Main()
    {
        dynamic expando = new ExpandoObject();
        var p = expando as IDictionary<String, object>;

        p["A"] = "New val 1";
        p["B"] = "New val 2";

        Console.WriteLine(expando.A);
        Console.WriteLine(expando.B);
    }
}

The point of this code snippet is that the members A and B are defined as string literals (hard coded/stringified) in and added via ExpandoObject's IDictionary interface. We test for the keys' existence and values (and prove the concept) by accessing them directly and outputting to console.

×眷恋的温暖 2024-09-11 09:23:13

可以将委托属性添加到 ExpandoObject,然后它的行为(几乎)就像方法一样。例如,

dynamic obj = new ExpandoObject();
obj.GetDocumentTemplate = () => { ... };
...
obj.GetDocumentTemplate(); // invokes delegate

It's possible to add delegate properties to an ExpandoObject, which then act (almost) just like methods. e.g.,

dynamic obj = new ExpandoObject();
obj.GetDocumentTemplate = () => { ... };
...
obj.GetDocumentTemplate(); // invokes delegate
2024-09-11 09:23:13

是的,ExpandoObject 的设计目的是动态地将属性添加到“属性包”中。然而,不支持为此类属性提供 getter 和 setter 的概念。如果您稍微想一下,也许就很清楚了:如果您已经知道 getter 和 setter 应该做什么,那么它就不再是动态属性了。您可以获得的最接近的是实现 INotifyPropertyChanged 事件,以便您可以检测更改。一些示例代码:

using System;
using System.Dynamic;
using System.ComponentModel;

class Program {
  static void Main(string[] args) {
    dynamic obj = new ExpandoObject();
    obj.test = 42;     // Add a property
    Console.WriteLine(obj.test);

    var inpc = (INotifyPropertyChanged)obj;
    inpc.PropertyChanged += inpc_PropertyChanged;
    obj.test = "foo";
    Console.ReadLine();
  }

  static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    Console.WriteLine("'{0}' property changed", e.PropertyName);
  }

}

Yes, ExpandoObject is very much designed to dynamically add properties to a "property bag". The notion of giving such a property an getter and setter is not supported however. Maybe that's clear if you think about it a bit: it wouldn't be a dynamic property anymore if you already know what the getter and setter should do. The closest you could get is implementing the INotifyPropertyChanged event so you can detect changes. Some sample code:

using System;
using System.Dynamic;
using System.ComponentModel;

class Program {
  static void Main(string[] args) {
    dynamic obj = new ExpandoObject();
    obj.test = 42;     // Add a property
    Console.WriteLine(obj.test);

    var inpc = (INotifyPropertyChanged)obj;
    inpc.PropertyChanged += inpc_PropertyChanged;
    obj.test = "foo";
    Console.ReadLine();
  }

  static void inpc_PropertyChanged(object sender, PropertyChangedEventArgs e) {
    Console.WriteLine("'{0}' property changed", e.PropertyName);
  }

}
浅笑依然 2024-09-11 09:23:13

我刚刚发现了这个有趣的事实:到 ExpandoObject 的 XAML 绑定还将创建该绑定尝试访问的属性

我仍然需要更多的创造力来找出这有什么好处。 UI 上的动态对象创建?听起来很酷:DI会尝试一些东西。

I just discovered this interesting fact: XAML Bindings to an ExpandoObject will also create the properties the binding is trying to access.

I still need more creativity to find out what this could be good for. Dynamic object creation on the UI? sounds cool :D I will try something out.

几味少女 2024-09-11 09:23:13

到目前为止的答案很好地涵盖了基础知识,但我觉得这篇 MSDN 杂志文章也值得分享:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

它涵盖了使用动态 XML 输入动态创建和使用 ExpandoObjects 的一些示例。

The answers so far cover the basics quite well, but I felt this MSDN Magazine article was worth sharing as well:

http://msdn.microsoft.com/en-us/magazine/ff796227.aspx

It covers some examples of using dynamic XML input to dynamically create and use ExpandoObjects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文