首页 > 代码库 > 扩展方法的几个实例,扩展基本类型、接口、通过反射让扩展方法使用私有成员等

扩展方法的几个实例,扩展基本类型、接口、通过反射让扩展方法使用私有成员等

.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);            }        }    }

1

 

  扩展接口

有这样的一个产品模型。

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();        }    }
              

2

  扩展包含私有字段的类 使用反射获取类的私有字段

扩展一个类的时候,有时候会用到该类的私有字段,我们可以通过反射拿到类的私有字段。

 

有这样的一个类,包含私有字段和公共方法。

{        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();        }    }

3

 

  扩展一个类的私有嵌套类 通过反射

当一个类有嵌套私有类的时候,扩展该类的时候,有时候会用到该类的嵌套私有类,我们可以通过反射扩展私有嵌套类。

 

有这样的一个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();

4