欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# 表達式目錄樹Expression的實現(xiàn)

 更新時間:2021年09月26日 12:46:47   作者:如果我來了6  
本文主要介紹了C# 表達式目錄樹Expression的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

表達式目錄樹

表達式目錄樹:語法樹,或者說是一種數(shù)據(jù)結構
1.表達式目錄樹Expression:System.Linq.Expressions;
2.描述了多個變量或者和常量之間的關系,按照一定的規(guī)則進行組裝!

  • 可以向委托一樣使用lambd表達式快捷聲明;
  • 不能有語句體,聲明只能有一行代碼;
  • 可以通過Compile(),編譯成一個委托;
Func<int, int, int> func = (m, n) =>
{
    int i = 0;
    return m * n + 2;
};  //委托  拉姆達表達式其實是作為委托的一個參數(shù),本質是一個方法(匿名方法)
Expression<Func<int, int, int>> exp = (m, n) => m * n + 2; //數(shù)據(jù)結構--就像對一個計算做了一個精確的描述,展開之后發(fā)現(xiàn),分為左邊,右邊,每個元素都可以把值都獲取出來,二叉樹
var erpPlu= exp.Compile();//表達式目錄樹可以通過compile 轉換成一個委托

//表達式目錄樹:語法樹,或者說是一種數(shù)據(jù)結構
int iResult1 = func.Invoke(12, 23);
int iResult2 = exp.Compile().Invoke(12, 23);

在這里插入圖片描述

在這里插入圖片描述

表達式目錄樹的拼裝

手動拼裝表達式目錄樹,不是用的lambda的快捷方式

//表達式目錄樹的拼裝
Expression<Func<int>> expression = () => 123 + 234;  //兩個常量相加-----表達式目錄樹的快捷聲明

Expression constant123 = Expression.Constant(123);
Expression constant234 = Expression.Constant(234);
Expression expressionAdd = Expression.Add(constant123, constant234);
var exp = Expression.Lambda<Func<int>>(expressionAdd);
var func = exp.Compile();
int iResult = func.Invoke();
Expression<Func<int, int, int>> exp = (m, n) => m * n + m + n + 2; //快捷聲明--其實編譯器提供的便捷功能---語法糖--具體實現(xiàn)可通過反編譯工具查看

//具體實現(xiàn)可通過反編譯工具查看
ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "m");
ParameterExpression parameterExpression2 = Expression.Parameter(typeof(int), "n");
Expression expContant2 = Expression.Constant(2, typeof(int));

Expression multipley = Expression.Multiply(parameterExpression, parameterExpression2);
Expression expAdd = Expression.Add(multipley, parameterExpression);

Expression expAdd1 = Expression.Add(expAdd, parameterExpression2);
Expression expAdd2 = Expression.Add(expAdd1, expContant2);
Expression<Func<int, int, int>> expression = Expression.Lambda<Func<int, int, int>>(expAdd2, new ParameterExpression[]
{
parameterExpression,
parameterExpression2
});
Func<int, int, int> fun = expression.Compile();
int iResult = fun.Invoke(10, 11);
var peopleQuery = new List<People>().AsQueryable();
Expression<Func<People, bool>> lambda = x => x.Id.ToString().Equals("5");
peopleQuery.Where(lambda);

ParameterExpression parameterExpression = Expression.Parameter(typeof(People), "x");
FieldInfo idfield = typeof(People).GetField("Id");
var idExp = Expression.Field(parameterExpression, idfield);

MethodInfo toString = typeof(int).GetMethod("ToString", new Type[0]);
var toStringExp = Expression.Call(idExp, toString, Array.Empty<Expression>()); 
var Equals = typeof(string).GetMethod("Equals", new Type[] { typeof(string) });
Expression expressionConstant5 = Expression.Constant("5", typeof(string));
var equalsExp = Expression.Call(toStringExp, Equals, new Expression[]
 {
    expressionConstant5
 });
Expression<Func<People, bool>> expression = Expression.Lambda<Func<People, bool>>(equalsExp, new ParameterExpression[]
{
 parameterExpression
});
Func<People, bool> func = expression.Compile();
var bResult = func.Invoke(new People()
{
    Id = 5,
    Name = "海貝"
});

new List<People>().AsQueryable().Where(expression);

應用

Linq to SQL

var dbSet = new List<People>().AsQueryable();//EF DbSet 
dbSet.Where(p => p.Age == 25 & p.Name.Contains("陽光下的微笑"));

Expression<Func<People, bool>> exp = null;
Console.WriteLine("用戶輸入個名稱,為空就跳過");
string name = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(name))
{
    exp = p => p.Name.Contains(name);
}
Console.WriteLine("用戶輸入個最小年紀,為空就跳過");
string age = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(age) && int.TryParse(age, out int iAge))
{
    exp = p => p.Age > iAge;
}

上面的玩法是不是只有最后一個條件才生效?如果需要多個條件都滿足;怎么辦? 當然是拼裝??;
拼裝可以從最小粒度來組裝表達式目錄樹;如果有一個封裝,你把各種條件給我,我從最小粒度開始一個一個的拼裝起來,不就是一個長的表達式目錄樹了嗎?

解決方案:
調用方可以組裝一個很長的表達式目錄樹傳遞過來;
表達式目錄樹傳遞過來以后,在這里應該做什么?應該解析;
所有信息都在表達式目錄樹里面,自然也可以把他解析(找出來)
解析就可以通過ExpressionVisitor解析----生成對應的Sql語句;

ExpressionVisitor

表達式目錄樹的訪問者----訪問者模式;
1.Visit方法–訪問表達式目錄樹的入口—分辨是什么類型的表達式目錄
2.調度到更加專業(yè)的方法中進一步訪問,訪問一遍之后,生成一個新的表達式目錄 —有點像遞歸,不全是遞歸;
3.因為表達式目錄樹是個二叉樹,ExpressionVisitor一直往下訪問,一直到葉節(jié)點;那就訪問了所有的節(jié)點;
4.在訪問的任何一個環(huán)節(jié),都可以拿到對應當前環(huán)節(jié)的內容(參數(shù)名稱、參數(shù)值。。),就可以進一步擴展;

為什么要使用表達式目錄樹來拼裝解析呢:
1.可以提高重用性;
2.如果封裝好一個方法,接受一個表達式目錄樹,在解析的時候,其實就是不斷的訪問,訪問有規(guī)則;
3.任何一個表達式目錄樹都可以調用當前方法來解析;
4.表達式目錄樹可以支持泛型;

            {
                Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Id > 5
                                                         && x.Name.StartsWith("1") //  like '1%'
                                                         && x.Name.EndsWith("1") //  like '%1'
                                                         && x.Name.Contains("1");//  like '%1%'

                //string sql = string.Format("Delete From [{0}] WHERE [Age]>5 AND [ID] >5"
                    , typeof(People).Name
                    , " [Age]>5 AND [ID] >5" ); 

                ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
                vistor.Visit(lambda);
                Console.WriteLine(vistor.Condition());
            }
            { 
               // ((( [Age] > '5') AND( [Name] =  [name] )) OR( [Id] > '5' )) 
               string name = "AAA"; 
                Expression<Func<People, bool>> lambda = x => x.Age > 5 && x.Name == name || x.Id > 5;
                ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
                vistor.Visit(lambda);
                Console.WriteLine(vistor.Condition());
            }
            {
                Expression<Func<People, bool>> lambda = x => x.Age > 5 || (x.Name == "A" && x.Id > 5);
                ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
                vistor.Visit(lambda);
                Console.WriteLine(vistor.Condition());
            }
            {
                Expression<Func<People, bool>> lambda = x => (x.Age > 5 || x.Name == "A") && x.Id > 5;
                ConditionBuilderVisitor vistor = new ConditionBuilderVisitor();
                vistor.Visit(lambda);
                Console.WriteLine(vistor.Condition());
            }

自己封裝的解析器,這就是EF6的底層原理,根據(jù)表達式樹自動生成相應的sql語句。

    public class ConditionBuilderVisitor : ExpressionVisitor
    {
        private Stack<string> _StringStack = new Stack<string>();

        public string Condition()
        {
            string condition = string.Concat(this._StringStack.ToArray());
            this._StringStack.Clear();
            return condition;
        }

        /// <summary>
        /// 如果是二元表達式
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override Expression VisitBinary(BinaryExpression node)
        {
            if (node == null) throw new ArgumentNullException("BinaryExpression");

            this._StringStack.Push(")");
            base.Visit(node.Right);//解析右邊
            this._StringStack.Push(" " + node.NodeType.ToSqlOperator() + " ");
            base.Visit(node.Left);//解析左邊
            this._StringStack.Push("(");

            return node;
        }

        /// <summary>
        /// 解析屬性
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override Expression VisitMember(MemberExpression node)
        {
            if (node == null) throw new ArgumentNullException("MemberExpression");
            //this._StringStack.Push(" [" + node.Member.Name + "] ");
            return node; 
            if (node.Expression is ConstantExpression)
            {
                var value1 = this.InvokeValue(node);
                var value2 = this.ReflectionValue(node);
                //this.ConditionStack.Push($"'{value1}'");
                this._StringStack.Push("'" + value2 + "'");
            }
            else
            {
                this._StringStack.Push(" [" + node.Member.Name + "] ");
            }
            return node;
        }


        private object InvokeValue(MemberExpression member)
        {
            var objExp = Expression.Convert(member, typeof(object));//struct需要
            return Expression.Lambda<Func<object>>(objExp).Compile().Invoke();
        }

        private object ReflectionValue(MemberExpression member)
        {
            var obj = (member.Expression as ConstantExpression).Value;
            return (member.Member as FieldInfo).GetValue(obj);
        }

        /// <summary>
        /// 常量表達式
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected override Expression VisitConstant(ConstantExpression node)
        {
            if (node == null) throw new ArgumentNullException("ConstantExpression");
            this._StringStack.Push(" '" + node.Value + "' ");
            return node;
        }
        /// <summary>
        /// 方法表達式
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        protected override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m == null) throw new ArgumentNullException("MethodCallExpression");

            string format;
            switch (m.Method.Name)
            {
                case "StartsWith":
                    format = "({0} LIKE {1}+'%')";
                    break;

                case "Contains":
                    format = "({0} LIKE '%'+{1}+'%')";
                    break;

                case "EndsWith":
                    format = "({0} LIKE '%'+{1})";
                    break;

                default:
                    throw new NotSupportedException(m.NodeType + " is not supported!");
            }
            this.Visit(m.Object);
            this.Visit(m.Arguments[0]);
            string right = this._StringStack.Pop();
            string left = this._StringStack.Pop();
            this._StringStack.Push(String.Format(format, left, right));

            return m;
        }
    }
    internal static class SqlOperator
    {
        internal static string ToSqlOperator(this ExpressionType type)
        {
            switch (type)
            {
                case (ExpressionType.AndAlso):
                case (ExpressionType.And):
                    return "AND";
                case (ExpressionType.OrElse):
                case (ExpressionType.Or):
                    return "OR";
                case (ExpressionType.Not):
                    return "NOT";
                case (ExpressionType.NotEqual):
                    return "<>";
                case ExpressionType.GreaterThan:
                    return ">";
                case ExpressionType.GreaterThanOrEqual:
                    return ">=";
                case ExpressionType.LessThan:
                    return "<";
                case ExpressionType.LessThanOrEqual:
                    return "<=";
                case (ExpressionType.Equal):
                    return "=";
                default:
                    throw new Exception("不支持該方法");
            }

        }
    }

表達式目錄擴展

表達式目錄樹動態(tài)拼接的實現(xiàn)方式:

    /// <summary>
    /// 合并表達式 And Or  Not擴展
    /// </summary>
    public static class ExpressionExtend
    {
        /// <summary>
        /// 合并表達式 expr1 AND expr2
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr1"></param>
        /// <param name="expr2"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
        {
            //return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters); 錯誤的寫法,兩個表達式不是同一個參數(shù)
			//將兩個表達式的參數(shù)統(tǒng)一為參數(shù)c
            ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
            NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);
            var left = visitor.Replace(expr1.Body);
            var right = visitor.Replace(expr2.Body); //為了能夠生成一個新的表達式目錄樹
            var body = Expression.And(left, right);
             return Expression.Lambda<Func<T, bool>>(body, newParameter);

        }
        /// <summary>
        /// 合并表達式 expr1 or expr2
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expr1"></param>
        /// <param name="expr2"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
        {

            ParameterExpression newParameter = Expression.Parameter(typeof(T), "c");
            NewExpressionVisitor visitor = new NewExpressionVisitor(newParameter);

            var left = visitor.Replace(expr1.Body);
            var right = visitor.Replace(expr2.Body);
            var body = Expression.Or(left, right);
            return Expression.Lambda<Func<T, bool>>(body, newParameter);
        }
        public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr)
        {
            var candidateExpr = expr.Parameters[0];
            var body = Expression.Not(expr.Body);

            return Expression.Lambda<Func<T, bool>>(body, candidateExpr);
        }
    }
    /// <summary>
    /// 建立新表達式
    /// </summary>
    internal class NewExpressionVisitor : ExpressionVisitor
    {
        public ParameterExpression _NewParameter { get; private set; }
        public NewExpressionVisitor(ParameterExpression param)
        {
            this._NewParameter = param;
        }
        public Expression Replace(Expression exp)
        {
            return this.Visit(exp);
        }
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return this._NewParameter;
        }
    }

調用方如下:

            {
                Expression<Func<People, bool>> lambda1 = x => x.Age > 5;  
                Expression<Func<People, bool>> lambda2 = x => x.Id > 5;

                //Expression<Func<People, bool>> newExpress = x => x.Age > 5 && x.Id > 5;

                Expression<Func<People, bool>> lambda3 = lambda1.And(lambda2); //且
                Expression<Func<People, bool>> lambda4 = lambda1.Or(lambda2);//或
                Expression<Func<People, bool>> lambda5 = lambda1.Not();//非
                Do1(lambda3);
                Do1(lambda4);
                Do1(lambda5);
            }
        
        private static void Do1(Expression<Func<People, bool>> func)
        {
            List<People> people = new List<People>()
            {
                new People(){Id=4,Name="123",Age=4},
                new People(){Id=5,Name="234",Age=5},
                new People(){Id=6,Name="345",Age=6},
            };

            List<People> peopleList = people.Where(func.Compile()).ToList();
        }

對象深拷貝

硬編碼

 PeopleCopy peopleCopy = new PeopleCopy()
 {
     Id = people.Id,
     Name = people.Name,
     Age = people.Age
 };

通過反射實現(xiàn)

    public class ReflectionMapper
    {
        /// <summary>
        /// 反射
        /// </summary>
        /// <typeparam name="TIn"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="tIn"></param>
        /// <returns></returns>
        public static TOut Trans<TIn, TOut>(TIn tIn)
        {
            TOut tOut = Activator.CreateInstance<TOut>();
            foreach (var itemOut in tOut.GetType().GetProperties())
            {
                var propIn = tIn.GetType().GetProperty(itemOut.Name);
                itemOut.SetValue(tOut, propIn.GetValue(tIn)); 
            }

            foreach (var itemOut in tOut.GetType().GetFields())
            {
                var fieldIn = tIn.GetType().GetField(itemOut.Name);
                itemOut.SetValue(tOut, fieldIn.GetValue(tIn)); 
            }
            return tOut;
        }
    }

通過序列化實現(xiàn)

    /// <summary>
    /// 使用第三方序列化反序列化工具
    /// 還有automapper
    /// </summary>
    public class SerializeMapper
    {
        /// <summary>
        /// 序列化反序列化方式
        /// </summary>
        /// <typeparam name="TIn"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        public static TOut Trans<TIn, TOut>(TIn tIn)
        {
            return JsonConvert.DeserializeObject<TOut>(JsonConvert.SerializeObject(tIn));
        }
    }

反射和序列化兩種實現(xiàn)方式性能不太好;

通過表達式目錄樹實現(xiàn)

通過表達式目錄樹動態(tài)的生成硬編碼

Func<People, PeopleCopy> func = p => new PeopleCopy()
{
    Id = p.Id,
    Name = p.Name,
    Age = p.Age
};
PeopleCopy peopleCopy3 = func.Invoke(people);

方法一:普通緩存

    /// <summary>
    /// 生成表達式目錄樹 緩存
    /// </summary>
    public class ExpressionMapper
    {
        /// <summary>
        /// 字典緩存--hash分布
        /// </summary>
        private static Dictionary<string, object> _Dic = new Dictionary<string, object>();

        /// <summary>
        /// 字典緩存表達式樹
        /// </summary>
        /// <typeparam name="TIn"></typeparam>
        /// <typeparam name="TOut"></typeparam>
        /// <param name="tIn"></param>
        /// <returns></returns>
        public static TOut Trans<TIn, TOut>(TIn tIn)
        {
            string key = string.Format("funckey_{0}_{1}", typeof(TIn).FullName, typeof(TOut).FullName);
            if (!_Dic.ContainsKey(key))
            {
                ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
                List<MemberBinding> memberBindingList = new List<MemberBinding>();
                foreach (var item in typeof(TOut).GetProperties())
                {
                    MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                    MemberBinding memberBinding = Expression.Bind(item, property);
                    memberBindingList.Add(memberBinding);
                }
                foreach (var item in typeof(TOut).GetFields())
                {
                    MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                    MemberBinding memberBinding = Expression.Bind(item, property);
                    memberBindingList.Add(memberBinding);
                }
                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
                Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
                {
                    parameterExpression
                });
                Func<TIn, TOut> func = lambda.Compile();//拼裝是一次性的
                _Dic[key] = func;
            }
            return ((Func<TIn, TOut>)_Dic[key]).Invoke(tIn);
        }
    }

方法二:泛型緩存,性能較高

    /// <summary>
    /// 生成表達式目錄樹  泛型緩存
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    public class ExpressionGenericMapper<TIn, TOut>//Mapper`2
    {
        private static Func<TIn, TOut> _FUNC = null;
        static ExpressionGenericMapper()
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
            List<MemberBinding> memberBindingList = new List<MemberBinding>();
            foreach (var item in typeof(TOut).GetProperties())
            {
                MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            foreach (var item in typeof(TOut).GetFields())
            {
                MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
            Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
            {
                    parameterExpression
            });
            _FUNC = lambda.Compile();//拼裝是一次性的
        }
        public static TOut Trans(TIn t)
        {
            return _FUNC(t);
        }
    }

到此這篇關于C# 表達式目錄樹Expression的實現(xiàn)的文章就介紹到這了,更多相關C# 表達式目錄樹Expression內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C# MJPEG 客戶端簡單實現(xiàn)方法

    C# MJPEG 客戶端簡單實現(xiàn)方法

    這篇文章主要介紹了C# MJPEG 客戶端簡單實現(xiàn)的方法,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下
    2021-03-03
  • c# 從IE瀏覽器獲取當前頁面的內容

    c# 從IE瀏覽器獲取當前頁面的內容

    從IE瀏覽器獲取當前頁面內容可能有多種方式,今天我所介紹的是其中一種方法?;驹恚寒斒髽它c擊當前IE頁面時,獲取鼠標的坐標位置,根據(jù)鼠標位置獲取當前頁面的句柄,然后根據(jù)句柄,調用win32的東西進而獲取頁面內容。感興趣的朋友可以參考下本文
    2021-06-06
  • C#11新特性使用案例詳解

    C#11新特性使用案例詳解

    這篇文章主要為大家介紹了C#11新特性的使用案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • C#讀寫文本文件(.txt)的方法實例

    C#讀寫文本文件(.txt)的方法實例

    讀寫文本文件其實是件很簡單的事情,這篇文章主要給大家介紹了關于C#讀寫文本文件(.txt)的相關資料,需要的朋友可以參考下
    2021-05-05
  • winform實現(xiàn)關閉按鈕失效的兩種方法

    winform實現(xiàn)關閉按鈕失效的兩種方法

    這篇文章主要介紹了winform實現(xiàn)關閉按鈕失效的兩種方法,實例分析了WinForm實現(xiàn)關閉按鈕失效的原理與所涉及的相關技巧,需要的朋友可以參考下
    2015-09-09
  • C#/VB.NET創(chuàng)建PDF文檔的示例代碼

    C#/VB.NET創(chuàng)建PDF文檔的示例代碼

    通過代碼創(chuàng)建 PDF 文檔有許多好處,所以本文將為大家詳細介紹一下如何使用 Spire.PDF for .NET 在 C# 和 VB.NET 中從頭開始創(chuàng)建 PDF 文檔,需要的可以參考下
    2023-12-12
  • C#利用PrintDocument定制打印單據(jù)的小例子

    C#利用PrintDocument定制打印單據(jù)的小例子

    這篇文章主要給大家介紹了關于C#利用PrintDocument定制打印單據(jù)的小例子,文中通過示例代碼介紹的非常詳細,對大家學習或者使用C#具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-05-05
  • C#實現(xiàn)身份證實名認證接口的示例代碼

    C#實現(xiàn)身份證實名認證接口的示例代碼

    身份證實名認證,即通過姓名和身份證號校驗個人信息的匹配程度,廣泛應用于金融、互聯(lián)網(wǎng)等多個領域,本文主要介紹了C#實現(xiàn)身份證實名認證接口的示例代碼,感興趣的可以了解一下
    2024-09-09
  • C#之WinForm跨線程訪問控件實例

    C#之WinForm跨線程訪問控件實例

    這篇文章主要介紹了C#之WinForm跨線程訪問控件,實例講述了跨線程訪問控件的簡單實現(xiàn)方法與用法,需要的朋友可以參考下
    2014-10-10
  • 如何使用C#操作幻燈片

    如何使用C#操作幻燈片

    一般大家經(jīng)常會用PPT遙控翻頁筆來遙控幻燈片,本文確為大家介紹了使用C#制作一個遙控幻燈片,感興趣的朋友可以參考下
    2015-07-07

最新評論