C#中dynamic和ExpandoObject的认识

在C#(.net)中给dynamic对象属性取值赋值 

 MSDN原文

dynamic对象是什么

MSDN上说:

提供用于在运行时指定动态行为的基类。 必须继承此类;不能直接对其进行实例化。

 dynamic的意义

dynamic的出现不同凡响,它在.net里在相当程度上取代了“反射”的机制,有了它,你就不用写复杂的反射代码了!

 dynamic类的属性取值赋值

MSDN中提到一点:“必须继承此类;不能直接对其进行实例化。

所以我们经常用到的是它的“继承类”ExpandoObject,而我们的问题“给dynamic对象属性取值赋值”可以变成“给ExpandoObject对象属性取值赋值”。

当然,dynamic 跟 dynamicObject没有直接联系。实际上还有 dynamicMetaObject 等等新的类,不能把名称看错。dynamic 关键字是个“语法糖”,它可以用来引用 ExpandoObject对象,DynamicObject 对象,也可以引用其它成千上万种对象。它就是用来避免你写反射代码的。

……

以ExpandoObject 对象来讲,“一句话”就能说明功能要点:ExpandoObject 对象实现了 IDictionary<string,object> 接口,通过它进行属性的动态处理(包括增加、删除属性等等操作)

还不知道是什么吧?那直接以代码来说明吧:


dynamic o = new ExpandoObject();
o.name="yes";
var dic = (IDictionary<string,object>)o;
dic["name"]="ok";

怎么样,是不是很简单?

ExpandoObject

MSDN上说:

可在运行时动态添加和删除其成员的对象

public sealed class ExpandoObject : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<string,object>>, System.Collections.Generic.IDictionary<string,object>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string,object>>, System.ComponentModel.INotifyPropertyChanged, System.Dynamic.IDynamicMetaObjectProvider

注解

ExpandoObject类使你能够在运行时添加和删除其实例的成员,还可以设置和获取这些成员的值。 此类支持动态绑定,使你可以使用类似的标准语法, sampleObject.sampleMember 而不是更复杂的语法 sampleObject.GetAttribute("sampleMember") 。

ExpandoObject类实现 (DLR) 接口的标准动态语言运行时 IDynamicMetaObjectProvider ,这使你能够在 ExpandoObject 支持 DLR 互操作性模型的语言之间共享类的实例。 例如,可以使用 c # 创建类的实例 ExpandoObject ,然后将其传递给 IronPython 函数。 有关详细信息,请参阅 c # 常见问题网站上的 动态语言运行时概述 和 介绍 ExpandoObject 。

ExpandoObject类是动态对象概念的实现,它允许获取、设置和调用成员。 如果要定义具有其自己的动态调度语义的类型,请使用 DynamicObject 类。 如果希望定义动态对象如何参与互操作性协议并管理 DLR 快速动态调度缓存,请创建自己的 IDynamicMetaObjectProvider 接口实现。

创建实例

在 c # 中,若要为类的实例启用后期绑定 ExpandoObject ,必须使用 dynamic 关键字。 有关更多信息,请参见使用类型 dynamic

在 Visual Basic 中,后期绑定支持动态操作。 有关详细信息,请参阅 Visual Basic) 的早期和后期绑定 (

下面的代码示例演示如何创建类的实例 ExpandoObject 。

dynamic sampleObject = new ExpandoObject();

添加新成员

可以向类的实例添加属性、方法和事件 ExpandoObject 。

下面的代码示例演示如何将新属性添加到类的实例 ExpandoObject 。

sampleObject.test = "Dynamic Property";
Console.WriteLine(sampleObject.test);
Console.WriteLine(sampleObject.test.GetType());
// This code example produces the following output:
// Dynamic Property
// System.String

 方法表示存储为委托的 lambda 表达式,这些表达式可在需要时调用。 下面的代码示例演示如何添加递增动态属性值的方法。

sampleObject.number = 10;
sampleObject.Increment = (Action)(() => { sampleObject.number++; });

// Before calling the Increment method.
Console.WriteLine(sampleObject.number);

sampleObject.Increment();

// After calling the Increment method.
Console.WriteLine(sampleObject.number);
// This code example produces the following output:
// 10
// 11

 下面的代码示例演示如何将事件添加到类的实例 ExpandoObject 。

class Program  
{  
    static void Main(string[] args)  
    {  
        dynamic sampleObject = new ExpandoObject();  

        // Create a new event and initialize it with null.  
        sampleObject.sampleEvent = null;  

        // Add an event handler.  
        sampleObject.sampleEvent += new EventHandler(SampleHandler);  

        // Raise an event for testing purposes.  
        sampleObject.sampleEvent(sampleObject, new EventArgs());  
   }  

    // Event handler.  
    static void SampleHandler(object sender, EventArgs e)  
    {  
        Console.WriteLine("SampleHandler for {0} event", sender);  
    }  
}  
// This code example produces the following output:  
// SampleHandler for System.Dynamic.ExpandoObject event.

 

作为参数传递

可以将类的实例 ExpandoObject 作为参数传递。 请注意,在 Visual Basic 中,这些实例被视为 c # 中的动态对象和后期绑定的对象。 这意味着你没有对象成员的 IntelliSense,因此,当你调用不存在的成员时,不会收到编译器错误。 如果调用的成员不存在,则会出现异常。

下面的代码示例演示如何创建和使用方法来打印属性的名称和值。

 

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.

枚举和删除成员

ExpandoObject 类实现 IDictionary<String, Object> 接口。 这样就可以在运行时枚举添加到类的实例的成员 ExpandoObject 。 如果在编译时不知道实例可能具有哪些成员,则这会很有用。

下面的代码示例演示如何将类的实例转换 ExpandoObject 为 IDictionary<TKey,TValue> 接口并枚举实例的成员。

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;

foreach (var property in (IDictionary<String, Object>)employee)
{
    Console.WriteLine(property.Key + ": " + property.Value);
}
// This code example produces the following output:
// Name: John Smith
// Age: 33

 在不具有删除成员 (如 c # 和 Visual Basic) 的语法的语言中,可以通过将的实例隐式强制转换 ExpandoObject 为 IDictionary<String, Object> 接口,然后将该成员作为键/值对删除,来删除成员。 下面的示例说明了这一点。

dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
((IDictionary<String, Object>)employee).Remove("Name");

 

接收属性更改的通知

ExpandoObject类实现 INotifyPropertyChanged 接口,并可 PropertyChanged 在添加、删除或修改成员后引发事件。 这使 ExpandoObject 类与 Windows Presentation Foundation (WPF) 数据绑定和其他需要通知对象内容更改的环境。

下面的代码示例演示如何为事件创建事件处理程序 PropertyChanged 。

// Add "using System.ComponentModel;" line
// to the beginning of the file.
class Program
{
    static void Test()
    {
        dynamic employee = new ExpandoObject();
        ((INotifyPropertyChanged)employee).PropertyChanged +=
            new PropertyChangedEventHandler(HandlePropertyChanges);
        employee.Name = "John Smith";
    }

    private static void HandlePropertyChanges(
        object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("{0} has changed.", e.PropertyName);
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 可以使用 `dynamic` 关键字来实现动态生成类,具体步骤如下: 1. 使用 `ExpandoObject` 类创建一个动态对象: ```csharp dynamic obj = new ExpandoObject(); ``` 2. 为动态对象添加属性和方法: ```csharp obj.MyProperty = "Hello"; obj.MyMethod = new Action(() => Console.WriteLine(obj.MyProperty)); ``` 3. 使用 `dynamic` 对象调用动态方法: ```csharp obj.MyMethod(); // 输出 "Hello" ``` 4. 如果需要动态生成类,可以使用 `TypeBuilder` 类: ```csharp AssemblyName assemblyName = new AssemblyName("MyAssembly"); AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MyModule"); TypeBuilder typeBuilder = moduleBuilder.DefineType( "MyClass", TypeAttributes.Public); typeBuilder.DefineField("myField", typeof(string), FieldAttributes.Private); MethodBuilder methodBuilder = typeBuilder.DefineMethod( "MyMethod", MethodAttributes.Public, null, null); ILGenerator ilGen = methodBuilder.GetILGenerator(); ilGen.Emit(OpCodes.Ldstr, "Hello, world!"); ilGen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); ilGen.Emit(OpCodes.Ret); Type type = typeBuilder.CreateType(); dynamic instance = Activator.CreateInstance(type); instance.MyMethod(); // 输出 "Hello, world!" ``` 以上代码使用 `TypeBuilder` 动态生成了一个名为 `MyClass` 的类,该类包含一个私有字段 `myField` 和一个公共方法 `MyMethod`,`MyMethod` 方法输出字符串 "Hello, world!"。最后使用 `Activator.CreateInstance` 创建了该类的一个实例,并调用了 `MyMethod` 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值