程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 擴展方法的幾個實例,擴展基本類型、接口、通過反射讓擴展方法使用私有成員等,實例私有

擴展方法的幾個實例,擴展基本類型、接口、通過反射讓擴展方法使用私有成員等,實例私有

編輯:C#入門知識

擴展方法的幾個實例,擴展基本類型、接口、通過反射讓擴展方法使用私有成員等,實例私有


.net擴展方法可以擴展很多類型,包括:基本數據類型、接口、類,等等。如果,需要擴展的類型包含私有成員,擴展方法如何運用這些私有成員呢?本篇逐一體驗,包括:

 

■ 擴展基本數據類型
■ 擴展接口
■ 擴展包含私有字段的類 使用反射獲取類的私有字段
■ 擴展一個類的私有嵌套類 通過反射

 

擴展方法有幾個必要前提:
● 擴展方法所在的類必須是靜態類
● 擴展方法本身必須是靜態方法
● 擴展方法參數中,對類型的擴展參數前必須加this關鍵字

 

  擴展基本數據類型

針對DateTime類型寫一個擴展方法。

public static class CalculateAge
    {
        public static int Age(this DateTime date, DateTime birthDate)
        {
            int birthYear = birthDate.Year;
            int currentYear = DateTime.Now.Year;
            if (birthYear >= currentYear)
            {
                throw new Exception("請輸入正確的出生日期~~");
            }
            else
            {
                return currentYear - birthYear - 1;
            }
        }
    }

 

客戶端調用。

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("請輸入您的出生年份");
                DateTime d = Convert.ToDateTime(Console.ReadLine());
                DateTime dateInstance = new DateTime();
                int age = dateInstance.Age(d);
                Console.WriteLine("您當前的年齡是:{0}", age);
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

 

  擴展接口

有這樣的一個產品模型。

public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

 

接口提供獲取產品集合的方法。

public interface IProductService
    {
        IEnumerable<Product> GetProducts();
    }

 

接口有2個實現類。

public class FoodProducts : IProductService
    {
        public IEnumerable<Product> GetProducts()
        {
            return new List<Product>
            {
                new Product(){Id = 1, Name = "餅干"},
                new Product(){Id = 2, Name = "牛奶"}
            };
        }
    }

    public class ElectronicProducts : IProductService
    {
        public IEnumerable<Product> GetProducts()
        {
            return new List<Product>
            {
                new Product(){Id = 3, Name = "電風扇"},
                new Product(){Id = 4, Name = "空調"}
            };
        }
    }

 

針對接口擴展方法。

public static class ProductServiceExtension
    {
        public static IEnumerable<Product> GetProductsById(this IProductService productService, int id)
        {
            return productService.GetProducts().Where(p => p.Id == id);
        }
    }

 

客戶端調用。

class Program
    {
        static void Main(string[] args)
        {
            IProductService productService = new FoodProducts();
            Console.WriteLine("食物類別下總數量是;{0}", productService.GetProducts().Count());
            try
            {
                Console.WriteLine("找到的產品名稱是:{0}", (productService.GetProductsById(1).SingleOrDefault()).Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadKey();
        }
    }
              


  擴展包含私有字段的類 使用反射獲取類的私有字段

擴展一個類的時候,有時候會用到該類的私有字段,我們可以通過反射拿到類的私有字段。

 

有這樣的一個類,包含私有字段和公共方法。

{
        private DateTime _currentTime;

        public void SetTime()
        {
            _currentTime = DateTime.Now;
        }

        public string GetMsg()
        {
            if (_currentTime.Hour < 12)
            {
                return "上午好~~";
            }
            else
            {
                return "下午好~~";
            }
        }
    }

 

我們希望擴展出一個顯示英文信息的問候。

public static class DisplayMessageExtensions
    {
        public static string GetLocalMsg(this DisplayMessage message, string country)
        {
            //通過反射拿到私有字段
            var privateField = typeof (DisplayMessage).GetField("_currentTime",
                BindingFlags.Instance | BindingFlags.NonPublic);

            //獲取該私有字段的值
            var currentDateTime = (DateTime)privateField.GetValue(message);
            if (country == "USA" && currentDateTime.Hour < 12)
            {
                return "Good Morning";
            }
            else
            {
                return "Good Evening";
            }
        }
    }

 

客戶端調用。

class Program
    {
        static void Main(string[] args)
        {
            DisplayMessage displayMessage = new DisplayMessage();
            displayMessage.SetTime();
            Console.WriteLine("來自中國的問候是:{0}", displayMessage.GetMsg());
            Console.WriteLine("美國人怎麼問候?");
            Console.WriteLine("來自美國的問候是:{0}", displayMessage.GetLocalMsg("USA"));
            Console.ReadKey();
        }
    }

 

  擴展一個類的私有嵌套類 通過反射

當一個類有嵌套私有類的時候,擴展該類的時候,有時候會用到該類的嵌套私有類,我們可以通過反射擴展私有嵌套類。

 

有這樣的一個ParentClass類,包含一個私有嵌套類ChildClass.

public class ParentClass
    {
        public string MessageFromParent()
        {
            return "from parent~~";
        }

        private class ChildClass
        {
            public string MessageFromChild()
            {
                return "from child~";
            }
        }
    }

 

現在要擴展這個私有嵌套類,為其添加一個轉換成大寫的方法,通過反射來完成。

public static class NestedClassExtension
    {
        public static string ToUppeerCaseParentMessage(this ParentClass parent)
        {
            return parent.MessageFromParent().ToUpper();
        }

        public static string ToUpperCaseChildMessage(this object o)
        {
            var childUpper = "";

            //通過反射獲取父類中的私有嵌套類
            var privateClass = typeof (ParentClass).GetNestedType("ChildClass", BindingFlags.NonPublic);

            if (o.GetType() == privateClass)
            {
                //通過反射獲取嵌套私有類的方法
                var callMethod = privateClass.GetMethod("MessageFromChild");
                childUpper = (callMethod.Invoke(o, null) as string).ToUpper();
            }
            return childUpper;
        }
    }

 

客戶端,首先通過反射獲取私有嵌套類的type類型,然後運用私有嵌套類的擴展方法。

try
            {
                ParentClass p = new ParentClass();

                //通過反射獲取父類私有嵌套類
                var privateClass = typeof (ParentClass).GetNestedType("ChildClass", BindingFlags.NonPublic);

                //通過反射創建父類私有嵌套類的實例
                var c = Activator.CreateInstance(privateClass);

                //通過反射獲取父類私有嵌套類的方法
                //var callMethod = privateClass.GetMethod("MessageFromChild");
                Console.WriteLine(c.ToUpperCaseChildMessage());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);   
            }
            Console.ReadKey();


問怎通過反射調用擴展方法?

var mi=list.GetType().GetMethod("Cast");
我是先把他的代碼黏貼到控制台下運行,結果報錯找不到這個方法後來想想,對了:
接著,我馬不停蹄趕到MSDN上查閱擴展方法定義在哪個類中在System.Linq命名空間下的Enumerable靜態類中。
找到了,OK!既然這個方法對於List是擴展,那麼對於這個Enumerable類而言不等於是普通的靜態方法嗎?好,既然如此,我就直接對你靜態類中的這個靜態方法進行反射了,出工了
List<string strings = new List<string { "1", "2", "3" };
MethodInfo mi = typeof(Enumerable).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static);
var list = (IEnumerable<string)mi.Invoke(null, new object[]{strings}); //這裡出錯
哦,上網問問好友們,使用了一個方法:
var list = (IEnumerable<string)mi.
MakeGenericMethod(typeof(string)).
Invoke(null, new object[]{strings});
這個方法會將方法的泛型傳入反射裝置。然後進行反射調用。
 

JAVA 反射

你為啥要把類名設置為Class呢,那後面的Class clazz申明的就是你所寫的這個Class,不錯才怪。改一個類名吧
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved