Dynamic - ExpandoObject學習心得


1、  今天下午在做開發過程中,遇到了一個問題,要往Xml文件中添加新的節點,做個xml開發的都知道該怎么做,這不是什么難事,我卡卡卡卡把這個問題解決了,但是新問題又來了,要對xml中對應的節點數據添加屬性更改通知功能???我一聽到這個需求就蒙了,我上哪去給xml節點數據整TMD屬性更改通知啊。哎。。。。。沒辦法了,胳膊擰不過大腿啊,只能硬着頭皮上咯。

2、  通過google、bing、百度的搜索,主要讓我發現了有個神奇的玩意,那就是ExpandoObject類型,ExpandoObject歸屬於動態類型,之前只是聽說過動態類型,但是一直都只是停留在聽說階段,今天為了解決這個問題終於可以來接近久仰已久的Dynamic了。要學習.net的新東西,肯定是去MSDN找咯,在msdn上看到關於Dynamic的介紹非常齊全,內容非常之多,今天我主要研究的是ExpandoObject。於是我就從最簡單的用法開始,自己動手一步步寫代碼嘗試。

現在開始我第一段代碼:

 C#代碼:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            dynamic dynObject = new ExpandoObject();
            dynObject.Name = "張益達";
            dynObject.Age = 25;
            dynObject.Time = DateTime.Now;
            this.DataContext = dynObject;
        }
    }

 

 

 xaml代碼:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button Width="80" Height="30" Content="按鈕1" Click="ButtonBase_OnClick"></Button>
            <TextBlock Text="{Binding Path=Name}"></TextBlock>
            <TextBox Text="{Binding Path=Age, Mode=TwoWay}"></TextBox>
            <TextBlock Text="{Binding Path=Time}"></TextBlock>
        </StackPanel>
    </Grid>
</Window>

 

 

效果圖:

說明:

這里就可看出Dynamic的神奇之處了,我沒有定義個類型,也沒有定義Name、Age、Time這些屬性,沒錯,這就是動態類型的功勞了,它能把我的Name、Age、Time在運行時解析成相應的類型,並且通過前台的數據綁定,把數據顯示出來。

 

第二段代碼:

C#代碼:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        dynamic dynObject = new ExpandoObject();

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
           
            dynObject.Name = "張益達";
            dynObject.Age = 25;
            dynObject.Time = DateTime.Now;
            this.DataContext = dynObject;
        }

        private void ButtonBase1_OnClick(object sender, RoutedEventArgs e)
        { 
            string newName = dynObject.Name;
            string age = dynObject.Age; 
        }
    }

 

 xaml代碼:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <Button Width="80" Height="30" Content="按鈕1" Click="ButtonBase_OnClick"></Button>
            <Button Width="80" Height="30" Content="按鈕2" Click="ButtonBase1_OnClick"></Button>
            <TextBlock Text="{Binding Path=Name}"></TextBlock>
            <TextBox Text="{Binding Path=Age, Mode=TwoWay}"></TextBox>
            <TextBlock Text="{Binding Path=Time}"></TextBlock>
        </StackPanel>
    </Grid>
</Window>

 

效果圖:

 

說明:

運行起來先點擊 按鈕1 然后改變Age的值(從25改成100),再點 按鈕2,斷點截圖中可以看到dynObject.Age的值已經自動變成120,!!!!天啊,這是多么神奇的事啊,值就那么輕易的自己改變了,這不就是要想要的屬相自動更改嗎?這倒是是真么發生的呢,其實這一切都是ExpandoObject的功勞,不准確的說應該是INotifyPropertyChanged的功勞,為什么這么說呢,在ExpandoObject上按F12看看究竟把:

有了這幅圖就能說明一切了,ExpandoObject是多么強大啊,它既是動態類,又是字典、集合、最最關鍵的他還有屬性更改通知。

 

第三段代碼

C#代碼:

        ObservableCollection<ExpandoObject> source = new ObservableCollection<ExpandoObject>();
        private void ButtonBase3_OnClick(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 5; i++)
            {
                dynamic dynObj = new ExpandoObject();
                dynObj.Test1 = string.Format("Zhangyida{0}", i);
                dynObj.Test2 = 25 + i;
                dynObj.Test3 = DateTime.Now.ToString();
                dynObj.IsCheck = false;
                source.Add(dynObj);
            }
            this.DataGrid1.ItemsSource = source;
        }

        private void ButtonBase4_OnClick(object sender, RoutedEventArgs e)
        {
            var sourc = source;
            foreach (dynamic item in source)
            {
                item.IsCheck = false;
                if (item.Test1 == "Zhangyida1")
                {
                    item.Test2 = 100;
                }
            }
        }

 

Xaml代碼

  <Button Width="80" Height="30" Content="按鈕3" Click="ButtonBase3_OnClick"></Button>
            <Button Width="80" Height="30" Content="按鈕4" Click="ButtonBase4_OnClick"></Button>
            <DataGrid Name="DataGrid1">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Path=Test1}"></DataGridTextColumn>
                    <DataGridTextColumn Binding="{Binding Path=Test2}"></DataGridTextColumn>
                    <DataGridTextColumn Binding="{Binding Path=Test3}"></DataGridTextColumn>
                    <DataGridCheckBoxColumn Binding="{Binding Path=IsCheck}"></DataGridCheckBoxColumn>
                </DataGrid.Columns>
            </DataGrid>

 

效果圖:

點擊 按鈕3:

點擊按鈕4:

說明:

注意喔,大家看仔細了,看看兩幅圖的區別,這是通過一個集合來進一步使用了ExpandoObject屬性更改通知

 

這時候我突然有個一個想法,既然動態類型可以動態的添加屬性,那么能不能讓我定義的一般實體類也可以有這種功能呢,查看了MSDN發現這個事有搞頭,讓我的實體類來繼承DynamicObject,然后再做並從新實現TrySetMember,大家先看看代碼吧

    public class DynamicUser : DynamicObject
    {
        private IDictionary<string, object> dictionary = new ExpandoObject();

        public int Count
        {
            get { return dictionary.Count; }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            string name = binder.Name;
            return dictionary.TryGetValue(name, out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            dictionary[binder.Name] = value;
            return true;
        }

        public int Age { get; set; }

        public string Name { get; set; }

        public DateTime Time { get; set; }
    }

 

這是我的動態實體類,默認有三個字段Age 、Name、Time字段,其實動態添加的屬性,我都把它放到了一個Dictionary里面,而且這是個ExpandoObject的字典。

C#代碼:

        dynamic dynUser = new DynamicUser();
        private void ButtonBase5_OnClick(object sender, RoutedEventArgs e)
        {
            dynUser.Age = 10;
            dynUser.Name = "張偉";
            dynUser.Time = DateTime.Now;
            dynUser.ABC = "ddddd";
            var ok = dynUser;

            this.DataContext = dynUser;
        }

        private void ButtonBase6_OnClick(object sender, RoutedEventArgs e)
        {
            var user = dynUser;
        }

 

Xaml代碼:

    <Button Width="80" Height="30" Content="按鈕5" Click="ButtonBase5_OnClick"></Button>
    <Button Width="80" Height="30" Content="按鈕6" Click="ButtonBase6_OnClick"></Button>

 

效果圖

說明:大家可以從上圖中看到dynUser已經有了ABC了,而且ABC的用法和屬性的用法一模一樣。

源代碼下載  http://files.cnblogs.com/zwzw/source.rar

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM