1. 程式人生 > >C# 利用函式反射、XML序列化/反序列化儲存函式執行與輸入引數列表

C# 利用函式反射、XML序列化/反序列化儲存函式執行與輸入引數列表

最近在寫工業機械臂控制的程式碼,需要實現如下的一個功能:
將機械臂需要執行的函式與輸入引數按照順序儲存成檔案,載入檔案後能夠直接命令機械手進行動作。
介面使用winform進行開發。函式名與引數的儲存、載入的部分,考慮到日後函式的增刪,使用了函式反射+XML序列化/反序列一個方案。

這部分用Console模擬一下。

先編寫一個類 Coordinate 來表示座標,類中有三個屬性X,Y,Z分別代表X,Y,Z座標值。

    public class Coordinate
    {
        /// <summary>
        /// X座標值
        /// </summary>
public double X { get; set; } /// <summary> /// Y座標值 /// </summary> public double Y { get; set; } /// <summary> /// Z座標值 /// </summary> public double Z { get; set; } public override string ToString() { return
"X:" + X + "|Y:" + Y + "|Z:" + Z; } public void SetCoordinate(double x , double y, double z) { X = x; Y = y; Z = z; } public static Coordinate operator +(Coordinate coor1 , Coordinate coor2) { return new
Coordinate() { X = coor1.X + coor2.X, Y = coor1.Y + coor2.Y, Z = coor1.Z + coor2.Z }; } public static Coordinate operator -(Coordinate coor1, Coordinate coor2) { return new Coordinate() { X = coor1.X - coor2.X, Y = coor1.Y - coor2.Y, Z = coor1.Z - coor2.Z }; } private static readonly Coordinate _originalCoordinate = new Coordinate { X = 0, Y = 0, Z = 0 }; /// <summary> /// 原點座標 /// </summary> public static Coordinate OriginalCoordinate { get { return _originalCoordinate; } } }

編寫一個類 Person 來模擬機械手臂,類中有如下幾種方法:

    public class Person
    {
        /// <summary>
        /// 當前座標點
        /// </summary>
        public Coordinate CurrentCoordinate { get; private set; }

        public Person()
        {
            CurrentCoordinate = Coordinate.OriginalCoordinate;
        }

        /// <summary>
        /// 以指定移動到目標地點
        /// </summary>
        /// <param name="coorDst"> 目的座標點 </param>
        /// <param name="speed"> 速度 </param>
        public void MoveToDestination(Coordinate coorDst , int speed)
        {
            Console.WriteLine("以速度:" + speed + "移動到點:" + coorDst.ToString());
            CurrentCoordinate = coorDst;
            Console.WriteLine("當前位置:" + CurrentCoordinate.ToString());
        }

        /// <summary>
        /// 移動一定偏移座標
        /// </summary>
        /// <param name="coorOffset">座標偏移量</param>
        /// <param name="speed">速度</param>
        public void MoveOffset(Coordinate coorOffset , int speed)
        {
            Console.WriteLine("以速度:" + speed + "移動偏移座標:" + coorOffset.ToString());
            CurrentCoordinate += coorOffset;
            Console.WriteLine("當前位置:" + CurrentCoordinate.ToString());
        }

        /// <summary>
        /// 退回原點
        /// </summary>
        /// <param name="speed">速度</param>
        public void BackToOriginalPoint(int speed)
        {
            CurrentCoordinate = Coordinate.OriginalCoordinate;
            Console.WriteLine("以速度:" + speed + "回到原點");
        }
    }

編寫一個類 Parameter 用來儲存函式的單個輸入引數,類中有兩個屬性 Type : ParamType 與 Object : Value 。ParamType 表示引數值的型別,Value 表示輸入引數的值。因為Xml序列化/反序列化需要引數值的型別,所以需要儲存輸入引數的型別 ParamType。並且為了降低耦合度,使用Object物件來儲存引數值。實現IXmlSerializable介面來自定義序列化的過程(object物件無法自行實現序列化/反序列化)。

    public class Parameter :  IXmlSerializable
    {
        /// <summary>
        /// 引數型別
        /// </summary>
        public Type ParamType { get; set; }

        /// <summary>
        /// 引數值
        /// </summary>
        public object Value { get; set; }

        XmlSchema IXmlSerializable.GetSchema()
        {
            return null;
        }

        void IXmlSerializable.ReadXml(XmlReader reader)
        {
            if (reader.IsEmptyElement)
                return;
            reader.Read();

            XmlSerializer xs = new XmlSerializer(typeof(string));
            reader.ReadStartElement("ParamType");
            string strType = (string)xs.Deserialize(reader);
            string strAssembly = strType.Split('.')[0];
            //如果是.net裡面包含的Type 直接使用Type.GetType介面
            if (strAssembly == "System") 
            {
                ParamType = Type.GetType(strType);
            }
            else
            { 
                //如果是其他程式集內的型別,需要載入程式集,然後利用反射獲取引數型別
                Assembly assembly = Assembly.Load(strAssembly);
                ParamType = assembly.GetType(strType);
            }

            xs = new XmlSerializer(ParamType);
            reader.ReadStartElement("Value");
            Value = xs.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadEndElement();
        }

        void IXmlSerializable.WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("ParamType");
            //這邊需要將Type儲存成字串,直接序列化 Type 會有異常(暫時不清楚為什麼)
            XmlSerializer xs = new XmlSerializer(typeof(string));
            xs.Serialize(writer, ParamType.ToString());
            writer.WriteEndElement();

            writer.WriteStartElement("Value");
            xs = new XmlSerializer(ParamType);
            xs.Serialize(writer, Value);
            writer.WriteEndElement();
        }
    }

編寫一個類 FunctionInfo ,類中有兩個屬性 string : FunctionName 與 Parameter[]:Parameters ,分別用來儲存函式名與函式的輸入引數。

    public class FunctionInfo
    {
        /// <summary>
        /// 函式名稱
        /// </summary>
        public string FunctionName { get; set; }

        /// <summary>
        /// 引數
        /// </summary>
        [XmlArray]
        public Parameter[] Parameters { get; set; }
    }

最後再編寫一個類,用來儲存整個函式事務列表

    public class Actions
    {
        [XmlArray]
        public FunctionInfo[] FunctionInofs { get; set; }
    }

下面是Main函式的執行程式碼:

        static void Main(string[] args)
        {
            //新建一個事務列表
            Actions actions = new Actions();
            actions.FunctionInofs = new FunctionInfo[3];
            //函式1 MoveToDestination
            actions.FunctionInofs[0] = new FunctionInfo()
            {
                FunctionName = "MoveToDestination",
                Parameters = new Parameter[]
                {
                    new Parameter { Value = new Coordinate { X = 1, Y = 2, Z = 3}, ParamType = typeof(Coordinate) },
                    new Parameter {  Value = 10, ParamType = typeof(int)},
                }
            };

            //函式2 MoveOffset
            actions.FunctionInofs[1] = new FunctionInfo()
            {
                FunctionName = "MoveOffset",
                Parameters = new Parameter[]
                {
                    new Parameter { Value = new Coordinate { X = 1, Y = 2, Z = 3}, ParamType = typeof(Coordinate) },
                    new Parameter {  Value = 5, ParamType = typeof(int)},
                }
            };

            //函式3 BackToOriginalPoint
            actions.FunctionInofs[2] = new FunctionInfo()
            {
                FunctionName = "BackToOriginalPoint",
                Parameters = new Parameter[]
                {
                    new Parameter {  Value = 2, ParamType = typeof(int)},
                }
            };

            //儲存到Xml檔案
            using (XmlWriter writer = XmlWriter.Create(System.Environment.CurrentDirectory + "\\functions.xml"))
            {
                XmlSerializer xs = new XmlSerializer(typeof(Actions));
                xs.Serialize(writer, actions);
            }

            //從Xml檔案反序列化
            using (XmlReader reader = XmlReader.Create(System.Environment.CurrentDirectory + "\\functions.xml"))
            {
                XmlSerializer xs = new XmlSerializer(typeof(Actions));
                actions = (Actions)xs.Deserialize(reader);
            }

            //定義一個Person
            Person person = new Person();
            //獲取型別
            Type type = typeof(Person); //這裡需要根據Person程式集的位置適當修改獲取Type的方式
            //依次執行函式
            foreach (var action in actions.FunctionInofs)
            {
                var mi = type.GetMethod(action.FunctionName, BindingFlags.Public | BindingFlags.Instance);
                mi.Invoke(person, action.Parameters.Select(x => x.Value).ToArray());
            }
            Console.ReadLine();
        }
    }

相關推薦

C# 利用函式反射XML序列/序列儲存函式執行輸入引數列表

最近在寫工業機械臂控制的程式碼,需要實現如下的一個功能: 將機械臂需要執行的函式與輸入引數按照順序儲存成檔案,載入檔案後能夠直接命令機械手進行動作。 介面使用winform進行開發。函式名與引數的儲存、載入的部分,考慮到日後函式的增刪,使用了函式反射+XML

C# XML序列/序列參考

.NET提供了很不錯的XML序列化/反序列化器,(它們所在的名稱空間為System.Xml.Serialization)這是很方便的,下面對它的使用做一些總結,以供參考。 1,簡單序列化 public static string SerializeXml(object data) { usi

C# 利用FTP自動下載xml文件後利用 FileSystemWatcher 監控目錄下文件變化並自動更新數據庫

use img div 進行 ssa reg c# col without using FtpLib; using System; using System.Collections.Generic; using System.ComponentModel;

.NET Core protobuf-netMessagePackJson.NET序列/序列性能測試

img alt int 序列化 james 最優 5.1 out mar 測試代碼Zonciu/SerializationTest.cs, 源自neuecc/ZeroFormatterBenchmark.cs。 NuGet包及其版本 mgravell/protobuf-ne

把物件序列化為xml格式和序列

using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text;

二進位制流序列(序列)和XML序列(序列)

序列化(Serialization):序列化是將物件狀態轉換為可儲存或傳輸的其它資料格式的過程。 反序列化(Deserialization) :與序列化相對的是反序列化,將其它資料格式轉換為物件的過程。 作用:將物件中的資料轉換成其它檔案,方便資訊的儲存與交換。  .NET

hive的三板斧:內部表和外部表分割槽和分桶以及序列/序列(SerDe)

hive的三板斧:內部表和外部表、分割槽和分桶以及序列化/反序列化(SerDe)   Hive是Hadoop生態圈中實現資料倉庫的一項技術。雖然Hadoop和HDFS的設計侷限了Hive所能勝任的工作,但是Hive仍然是目前網際網路中最適合資料倉庫的應用技術。 不論從“品相還是舉止

21.Java語言緩衝流轉換流序列序列更改列印流

緩衝流 緩衝流的基本原理,是在建立流物件時,會建立一個內建的預設大小的(8k)緩衝區陣列,通過緩衝區讀寫,減少系統IO次數,從而提高讀寫的效率。 1.位元組緩衝流:        1).輸出流:OutputStream               |--FileOut

Python_基礎_(模組,time,random,os,sys,json,shelve,xml序列序列)

一,Import的基本用法 import 1.執行對應的檔案 2.引入變數名 3.當一個檔案被import,索貝import中的程式碼會被執行一遍,例如當 import cal  ##cla中有inport("xxx"),則會輸出   ## Import引用方法

C# Dictionary序列/序列

1.說明:Dictionary物件本身不支援序列化和反序列化,需要定義一個繼承自Dictionary, IXmlSerializable類的自定義類來實現該功能。感覺完全可以把這樣的類封裝到C#庫中,很具有通用性嘛,至今沒有遇到不能用的情況的說,或許出於其他方面的考慮mic

C#對操作“××”的回覆訊息正文進行序列時出錯

主要原因webservice返回值的長度超過readerQuotas中的了maxStringContentLength值,造成返回值截斷,不完整,反序列化時出錯。 解決方案,在appconfig中,

c#-序列序列-1.1

1.右鍵點選專案,“管理NuGet程式包”,搜尋“Json.Net”,安裝,成功後Bin資料夾下多“Newtonsoft.Json.dll” 2.引用 using Newtonsoft.Json; 3.     序列化   JsonConv

Python(檔案讀取序列序列)

借鑑菜鳥教程 一、讀取 open() 將會返回一個 file 物件,基本語法格式如下: open(filename, mode)(filename, mode) filename:包含了你要訪問的檔名稱的字串值。 mode:決定了開啟檔案的模式:只讀,寫入,追加

Unity3d 實現物件的XML格式化和序列

  但是網頁平臺不支援(如果資料庫放在服務端,就沒有這個問題了), 所以想到用XML格式來儲存資料,資料量也不大,操作也簡單,可以直接將物件存為xml檔案,而且玩家本地存檔也會用到。using UnityEngine;using System.Collections;using System.Collecti

C++優雅的實現物件到檔案的序列/序列

需求 .  在寫程式碼的過程中,經常會需要把程式碼層面的物件資料儲存到檔案,而這些資料會以各種格式儲存.例如:json,xml,二進位制等等.最近恰好就需要把物件以二進位制儲存到硬碟.這是一個很簡單的需求,相比json,xml格式,二進位制是直接把位元組copy到硬碟,沒有中間商賺差價,所以這實現起來相對容易

MessagePack 新型序列序列方案

only program next sel ges new sys adf 簡介 進入在學習redis的時候,在文中看到了關於MessagePack的簡介,發現非常有意思,於是就花了點時間大致了解了下。 MessagePack介紹: MessagePack is an ef

10.8-全棧Java筆記:序列/序列的步驟和實例

java 本節我們詳細講解10.3節中提到的序列化和反序列化操作。序列化和反序列化是什麽當兩個進程遠程通信時,彼此可以發送各種類型的數據。 無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。比如,我們可以通過http協議發送字符串信息;我們也可以在網絡上直接發送JAVA對象。發送方需要把這個Java對

測試了下boost的序列序列功能

con != bar lan class try hat out ora [cpp] view plain copy // testSerialization.cpp : Defines the entry point for the console

深入JAVA序列序列

轉換 zed 一個 源代碼 () bili 什麽 知識點 dom 前言 java序列化與反序列化應該是非常基本的知識點,但細想起來還是一頭霧水, 不知道序列化與反序列化到底底層是如何實現的,所以特意花了些時間整理這篇文章。 所以你如果還只是停留在使用和知道這麽一個知

文件操作,路徑操作,StringIO和BytesIO,序列序列,正則表達式python中使用

基於 關系 判斷目錄 java、 優先 errors 情況下 water des 文件操作 打開操作open(file, mode=‘r‘, buffering=-1, encoding=None, errors=None, newline=None, closefd=Tr