天天看點

擴充方法

例如存在下列代碼:

1

2

3

4

5

6

7

8

9

10

namespace

ExtensionMethods

{

public

static

class

MyExtensions

{

public

static

int

zzyhost(

this

String str)

{         

return

0;

}

}   

}

那麼在其他類下隻需要 using ExtensionMethods;,所有 string 類型的對象就都擁有了 zzyhost() 這個方法,而無需你重寫一個 string 類,比如:

string

s = 

"Hello zzyhost"

;

int

i = s.zzyhost();

像題主這段代碼就是使得 Bitmap 這個類型多了一個 function() 方法。

C#動态調用泛型類、泛型方法

      在制作一個批量序列化工具時遇到了如下問題,在此記錄一下,僅供參考。

      主程式加載另一個程式集,将其中的所有類取出,然後對這些類分别調用泛型類或泛型方法。控制台程式解決方案如下:

  • Main工程:提供Worker類進行資料操作,XMLTool<T>泛型類将資料集序列化為.xml文檔,RootCollection<T>類封裝資料集
    • Worker類
           提供成員方法void DoWork<T>()、List<T> GetList<T>()、靜态成員方法StaticDoWork<T>(),代碼如下:
    1 public class Worker
     2     {
     3         public Worker()
     4         {
     5         }
     6 
     7         public void DoWork<T>()
     8         {
     9             Type t = typeof(T);
    10             Console.WriteLine("Get Class: {0}", t.Name);
    11             PropertyInfo[] properties = t.GetProperties();
    12             foreach (PropertyInfo property in properties)
    13             {
    14                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);
    15             }
    16         }
    17 
    18         public static void StaticDoWork<T>()
    19         {
    20             Type t = typeof(T);
    21             Console.WriteLine("Get Class: {0}", t.Name);
    22             PropertyInfo[] properties = t.GetProperties();
    23             foreach (PropertyInfo property in properties)
    24             {
    25                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);
    26             }
    27         }
    28 
    29         public List<T> GetList<T>()
    30         {
    31             Console.WriteLine("Generate List for [{0}]", typeof(T).Name);
    32             return new List<T>() 
    33             { 
    34                 Activator.CreateInstance<T>(), 
    35                 Activator.CreateInstance<T>() 
    36             };
    37         }
    38     }      
    • XMLTool<T>類
      1publicclass XMLTool<T>
       2     {
       3publicstaticvoid XmlSerialize_Save(List<T> needSerializedList, string xmlDirPath, string xmlFileName)
       4         {
       5             RootCollection<T> collection = new RootCollection<T>();
       6             collection.ItemList = needSerializedList;
       7if (!Directory.Exists(xmlDirPath))
       8                 Directory.CreateDirectory(xmlDirPath);
       9using (System.IO.FileStream stream = new System.IO.FileStream(xmlFileName, System.IO.FileMode.Create))
      10             {
      11                 System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(collection.GetType());
      12                 serializer.Serialize(stream, collection);
      13             }
      14         }
      15     }      
    • RootCollection<T>類:
      1     [Serializable]
       2     public class RootCollection<T>
       3     {
       4         public RootCollection()
       5         {
       6             itemList = new List<T>();
       7         }
       8 
       9         private List<T> itemList;
      10 
      11         public List<T> ItemList
      12         {
      13             get { return itemList; }
      14             set { itemList = value; }
      15         }
      16     }      
  • MockClassLib工程:提供BaseEntity、Apple、Cat和Person類
    • BaseEntity類:抽象類,負責初始化類成員
      1     public abstract class BaseEntity
       2     {
       3         public BaseEntity()
       4         {
       5             InitiaWithNull();
       6         }
       7
       8         private void InitiaWithNull()
       9         {
      10             Type type = this.GetType();
      11             PropertyInfo[] properties = type.GetProperties();
      12             string[] PropNames = new string[properties.Length];
      13             Dictionary<string, PropertyInfo> PropNameToInfo = new Dictionary<string, PropertyInfo>();
      14             for (int i = 0; i < properties.Length; i++)
      15             {
      16                 PropNames[i] = properties[i].Name;
      17                 PropNameToInfo.Add(PropNames[i], properties[i]);
      18             }
      19
      20             foreach (string propname in PropNames)
      21             {
      22                 string proptype = PropNameToInfo[propname].PropertyType.Name;
      23
      24                 object value = null;
      25                 if (NullValue.Keys.Contains(proptype))
      26                     value = NullValue[proptype];
      27
      28                 type.GetProperty(propname).SetValue(this, value, null);
      29             }
      30         }
      31
      32         private static readonly Dictionary<string, object> NullValue = new Dictionary<string, object>() 
      33             { 
      34                 { "String", String.Empty }, 
      35                 { "DateTime", DateTime.MinValue},
      36                 { "Decimal", Decimal.MinValue}
      37             };
      38     }      
    • Apple、Cat和Person類:測試類,繼承于BaseEntity
      1     public class Apple : BaseEntity
       2     {
       3        public string Color { get; set; }
       4     }
       5
       6     public class Cat : BaseEntity
       7     {
       8        public string Type { get; set; }
       9     }
      10
      11     public class Person : BaseEntity
      12     {
      13        public int ID { get; set; }
      14        public string Name { get; set; }
      15     }      

      Main工程的Program的Main方法中,一般情況下,調用Worker的泛型方法來處理測試類的話,可以寫為:

      Worker worker = new Worker();

      worker.DoWork<Apple>();

      worker.DoWork<Cat>();

      worker.DoWork<Person>();

      但是,如果MockClassLib中需要處理的類型非常多時,這樣顯示調用必然是不靈活的,應當怎樣向泛型方法DoWork<T>()的尖括号中動态傳入類型呢?

      考慮代碼:

//Load assembly
            Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll");
            Type[] typeArray = mockAssembly.GetTypes();

            //Create instance of Worker          
            Worker worker = new Worker();
            foreach(Type curType in typeArray)
            {
                  worker.DoWork<curType>();   //Error
            }      

      可以看到,Type類型的執行個體是無法直接傳入泛型方法的尖括号中的,T要求顯式指明類型名。

      下面通過反射方式來擷取泛型方法,并建立特定類型的泛型方法。

  • 對于非靜态方法:public void DoWork<T>()

          對于非靜态方法,調用MethodInfo.Invoke(object, object[])時,第一個參數需要指明泛型方法的所有者(即這裡建立的worker對象),第二個參數為泛

          型方法的參數清單,DoWork<T>()沒有輸入參數,是以設為null

//Create an instance of Worker
Worker worker = new Worker();       

//Get type of Worker
Type workerType = typeof(Worker);

 //Get Generic Method
MethodInfo doWorkMethod = workerType.GetMethod("DoWork");

//Invoke DoWork<T> with different Type
foreach (Type curType in typeArray)
{
    if (curType.IsClass && !curType.IsAbstract)//Filter BaseEntity
    {
        MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);
        curMethod.Invoke(worker, null);//Member method,use instance
    }
}      
擴充方法
  • 對于靜态方法:public static void StaticDoWork<T>()

          不同于非靜态方法,這裡直接反射的類靜态方法,是以Invoke()的第一個參數設為null

//Get type of Worker
Worker worker = new Worker();

//Get Generic Method
MethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");

//Invoke StaticDoWork<T>
foreach (Type curType in typeArray)
{
    if (curType.IsClass && !curType.IsAbstract)
    {
        MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);
        curMethod.Invoke(null, null);//Static method
    }
}      
  • 對于有傳回值的非靜态方法:public List<T> GetList()

          如同動态調用DoWork<T>()方法一樣,隻是在處理傳回值時,可以使用下面的方法

1 IList tempList = (IList)curMethod.Invoke(worker, null);
2 //Or
3 IEnumerable tempList = (IEnumerable)curMethod.Invoke(worker, null);      
  • 對于泛型類:XMLTool<T>

          下面要使用泛型類XMLTool<T>的靜态方法public static void XmlSerialize_Save(List<T> list, string dirPath, string fileName)方法。

          首先應通過反射構造出指定類型的泛型類XMLTool<T>,再反射出其中的XmlSerialize_Save方法并使用。

1 //Use Generic Class
 2 Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);
 3 
 4 //Get method
 5 MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");
 6 
 7 //Invoke
 8 saveMethod.Invoke
 9 (
10     null, //Static method
11     new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }

12 );      

       Program-->Main()方法的全部代碼:

1 namespace RetrieveUnknownClass
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             //Load assembly
 8             Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll");
 9             Type[] typeArray = mockAssembly.GetTypes();
10 
11             //Create instance of Worker          
12             Type workerType = typeof(Worker);
13             Worker worker = new Worker();
14 
15             #region Member method
16 
17             Console.WriteLine(">>>>>>>>>Use Generic Method:");
18             MethodInfo doWorkMethod = workerType.GetMethod("DoWork");
19 
20             //Invoke DoWork<T>
21             foreach (Type curType in typeArray)
22             {
23                 if (curType.IsClass && !curType.IsAbstract)
24                 {
25                     MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);
26                     curMethod.Invoke(worker, null);//Member method,use instance
27                 }
28             }
29 
30             #endregion
31 
32             #region Static method
33 
34             Console.WriteLine("\r\n>>>>>>>>>Use Static Generic Method:");
35             MethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");
36 
37             //Invoke StaticDoWork<T>
38             foreach (Type curType in typeArray)
39             {
40                 if (curType.IsClass && !curType.IsAbstract)
41                 {
42                     MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);
43                     curMethod.Invoke(null, null);//Static method
44                 }
45             }
46 
47             #endregion
48 
49             #region Get A List & Serialize It to Xml File With Generic 
50 
51             Console.WriteLine("\r\n>>>>>>>>>Get List By Generic Method:");
52             MethodInfo getListMethod = workerType.GetMethod("GetList");
53 
54             foreach (Type curType in typeArray)
55             {
56                 if (curType.IsClass && !curType.IsAbstract)
57                 {
58                     MethodInfo curMethod = getListMethod.MakeGenericMethod(curType);
59                     //Generate List
60                     IList resultList = (IList)curMethod.Invoke(worker, null);
61                     //Show List
62                     ShowList(resultList);
63                     //Use Generic Class
64                     Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);
65                     MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");
66 
67                     saveMethod.Invoke
68                         (
69                             null, //Static method
70                             new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }
71                         );
72                 }
73             }
74             
75             Console.WriteLine("Serialization Completed...\r\n");
76             #endregion
77         }
78 
79         public static void ShowList(IList list)
80         {
81             Console.WriteLine("Type of list: {0}\r\nCount of current list: {1}\r\nType of item in list: {2}\r\n", 
82                 list.GetType(), 
83                 list.Count, 
84                 list[0].GetType());
85         }
86     }
87 }      
    1 public class Worker
     2     {
     3         public Worker()
     4         {
     5         }
     6 
     7         public void DoWork<T>()
     8         {
     9             Type t = typeof(T);
    10             Console.WriteLine("Get Class: {0}", t.Name);
    11             PropertyInfo[] properties = t.GetProperties();
    12             foreach (PropertyInfo property in properties)
    13             {
    14                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);
    15             }
    16         }
    17 
    18         public static void StaticDoWork<T>()
    19         {
    20             Type t = typeof(T);
    21             Console.WriteLine("Get Class: {0}", t.Name);
    22             PropertyInfo[] properties = t.GetProperties();
    23             foreach (PropertyInfo property in properties)
    24             {
    25                 Console.WriteLine("\tproperty.Name: " + property.Name + "\tproperty.MemberType: " + property.PropertyType);
    26             }
    27         }
    28 
    29         public List<T> GetList<T>()
    30         {
    31             Console.WriteLine("Generate List for [{0}]", typeof(T).Name);
    32             return new List<T>() 
    33             { 
    34                 Activator.CreateInstance<T>(), 
    35                 Activator.CreateInstance<T>() 
    36             };
    37         }
    38     }      
    • 1publicclass XMLTool<T>
       2     {
       3publicstaticvoid XmlSerialize_Save(List<T> needSerializedList, string xmlDirPath, string xmlFileName)
       4         {
       5             RootCollection<T> collection = new RootCollection<T>();
       6             collection.ItemList = needSerializedList;
       7if (!Directory.Exists(xmlDirPath))
       8                 Directory.CreateDirectory(xmlDirPath);
       9using (System.IO.FileStream stream = new System.IO.FileStream(xmlFileName, System.IO.FileMode.Create))
      10             {
      11                 System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(collection.GetType());
      12                 serializer.Serialize(stream, collection);
      13             }
      14         }
      15     }      
    • 1     [Serializable]
       2     public class RootCollection<T>
       3     {
       4         public RootCollection()
       5         {
       6             itemList = new List<T>();
       7         }
       8 
       9         private List<T> itemList;
      10 
      11         public List<T> ItemList
      12         {
      13             get { return itemList; }
      14             set { itemList = value; }
      15         }
      16     }      
    • 1     public abstract class BaseEntity
       2     {
       3         public BaseEntity()
       4         {
       5             InitiaWithNull();
       6         }
       7
       8         private void InitiaWithNull()
       9         {
      10             Type type = this.GetType();
      11             PropertyInfo[] properties = type.GetProperties();
      12             string[] PropNames = new string[properties.Length];
      13             Dictionary<string, PropertyInfo> PropNameToInfo = new Dictionary<string, PropertyInfo>();
      14             for (int i = 0; i < properties.Length; i++)
      15             {
      16                 PropNames[i] = properties[i].Name;
      17                 PropNameToInfo.Add(PropNames[i], properties[i]);
      18             }
      19
      20             foreach (string propname in PropNames)
      21             {
      22                 string proptype = PropNameToInfo[propname].PropertyType.Name;
      23
      24                 object value = null;
      25                 if (NullValue.Keys.Contains(proptype))
      26                     value = NullValue[proptype];
      27
      28                 type.GetProperty(propname).SetValue(this, value, null);
      29             }
      30         }
      31
      32         private static readonly Dictionary<string, object> NullValue = new Dictionary<string, object>() 
      33             { 
      34                 { "String", String.Empty }, 
      35                 { "DateTime", DateTime.MinValue},
      36                 { "Decimal", Decimal.MinValue}
      37             };
      38     }      
    • 1     public class Apple : BaseEntity
       2     {
       3        public string Color { get; set; }
       4     }
       5
       6     public class Cat : BaseEntity
       7     {
       8        public string Type { get; set; }
       9     }
      10
      11     public class Person : BaseEntity
      12     {
      13        public int ID { get; set; }
      14        public string Name { get; set; }
      15     }      
//Load assembly
            Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll");
            Type[] typeArray = mockAssembly.GetTypes();

            //Create instance of Worker          
            Worker worker = new Worker();
            foreach(Type curType in typeArray)
            {
                  worker.DoWork<curType>();   //Error
            }      
//Create an instance of Worker
Worker worker = new Worker();       

//Get type of Worker
Type workerType = typeof(Worker);

 //Get Generic Method
MethodInfo doWorkMethod = workerType.GetMethod("DoWork");

//Invoke DoWork<T> with different Type
foreach (Type curType in typeArray)
{
    if (curType.IsClass && !curType.IsAbstract)//Filter BaseEntity
    {
        MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);
        curMethod.Invoke(worker, null);//Member method,use instance
    }
}      
//Get type of Worker
Worker worker = new Worker();

//Get Generic Method
MethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");

//Invoke StaticDoWork<T>
foreach (Type curType in typeArray)
{
    if (curType.IsClass && !curType.IsAbstract)
    {
        MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);
        curMethod.Invoke(null, null);//Static method
    }
}      
1 IList tempList = (IList)curMethod.Invoke(worker, null);
2 //Or
3 IEnumerable tempList = (IEnumerable)curMethod.Invoke(worker, null);      
1 //Use Generic Class
 2 Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);
 3 
 4 //Get method
 5 MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");
 6 
 7 //Invoke
 8 saveMethod.Invoke
 9 (
10     null, //Static method
11     new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }

12 );      
1 namespace RetrieveUnknownClass
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             //Load assembly
 8             Assembly mockAssembly = Assembly.LoadFrom("MockClassLibrary.dll");
 9             Type[] typeArray = mockAssembly.GetTypes();
10 
11             //Create instance of Worker          
12             Type workerType = typeof(Worker);
13             Worker worker = new Worker();
14 
15             #region Member method
16 
17             Console.WriteLine(">>>>>>>>>Use Generic Method:");
18             MethodInfo doWorkMethod = workerType.GetMethod("DoWork");
19 
20             //Invoke DoWork<T>
21             foreach (Type curType in typeArray)
22             {
23                 if (curType.IsClass && !curType.IsAbstract)
24                 {
25                     MethodInfo curMethod = doWorkMethod.MakeGenericMethod(curType);
26                     curMethod.Invoke(worker, null);//Member method,use instance
27                 }
28             }
29 
30             #endregion
31 
32             #region Static method
33 
34             Console.WriteLine("\r\n>>>>>>>>>Use Static Generic Method:");
35             MethodInfo staticDoWorkMethod = workerType.GetMethod("StaticDoWork");
36 
37             //Invoke StaticDoWork<T>
38             foreach (Type curType in typeArray)
39             {
40                 if (curType.IsClass && !curType.IsAbstract)
41                 {
42                     MethodInfo curMethod = staticDoWorkMethod.MakeGenericMethod(curType);
43                     curMethod.Invoke(null, null);//Static method
44                 }
45             }
46 
47             #endregion
48 
49             #region Get A List & Serialize It to Xml File With Generic 
50 
51             Console.WriteLine("\r\n>>>>>>>>>Get List By Generic Method:");
52             MethodInfo getListMethod = workerType.GetMethod("GetList");
53 
54             foreach (Type curType in typeArray)
55             {
56                 if (curType.IsClass && !curType.IsAbstract)
57                 {
58                     MethodInfo curMethod = getListMethod.MakeGenericMethod(curType);
59                     //Generate List
60                     IList resultList = (IList)curMethod.Invoke(worker, null);
61                     //Show List
62                     ShowList(resultList);
63                     //Use Generic Class
64                     Type xmlToolType = typeof(XMLTool<>).MakeGenericType(curType);
65                     MethodInfo saveMethod = xmlToolType.GetMethod("XmlSerialize_Save");
66 
67                     saveMethod.Invoke
68                         (
69                             null, //Static method
70                             new object[] { resultList, @"c:\", @"c:\Test_" + curType.Name + ".xml" }
71                         );
72                 }
73             }
74             
75             Console.WriteLine("Serialization Completed...\r\n");
76             #endregion
77         }
78 
79         public static void ShowList(IList list)
80         {
81             Console.WriteLine("Type of list: {0}\r\nCount of current list: {1}\r\nType of item in list: {2}\r\n", 
82                 list.GetType(), 
83                 list.Count, 
84                 list[0].GetType());
85         }
86     }
87 }