本篇內容介紹了“C#反射怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
C#反射技術主要基于System.Type類和System.Reflection.Assemble類,通過Type類可以訪問關于任何數據類型的信息,Assemble類用于訪問給定程序集的相關信息,或把這個程序集加載到程序中。
Type類是一個抽象類。只要實例化了一個Type對象,實際上就實例化了Type的一個派生類。盡管一般情況下派生類只提供各種Type方法和屬性的不同重載,但是這些方法和屬性返回對應數據類型的正確數據,Type有與每種數據類型對應的派生類。它們一般不添加新的方法或屬性
通常,獲取指向任何給定的Type引用有三種常用方式:
*使用typeof運算符,這個運算符的參數是類型的名稱,但不放在引號中:
Type t =typeof(double);
*使用GetType()方法,所以類都會從System.Object繼承這個方法:
double d =10; Type t = d.GetType();
在一個變量上調用GetType()方法,返回的Type對象只與該數據類型相關,不包含該類型實例的任何信息。
*調用Type類的靜態方法GetType():
Type t =Type.GetType("System.Double");Type是很多反射功能的入口,它實現很多方法和屬性,可用的屬性都是只讀的:可以使用Type確定數據的類型,但不能使用它修改該類型。
由Type實現的屬性分為3類。
*包含與類相關的各種名稱的字符串:
Name:數據類型名
FullName:數據類型的完全限定名(包含名稱空間)
Namespace:在其中定義數據類型的名稱空間名
*獲取Type對象的引用的屬性:
BaseType:該對象的直接基本類型
UnderlyingSystemType:該Type在.NET運行庫中映射到的類型
*布爾屬性
IsAbstract,IsArray,IsClass,IsEnum等判斷Type是什么類型的屬性。
System.Type的大多數方法都用于獲取對應數據類型的成員信息:構造函數,屬性,方法和事件等。它有許多方法,但它們都有相同的模式。例如,獲取數據類型的方法的信息:GetMethod()和GetMethods()。GetMethod()方法返回MethodInfo對象的一個引用,其中包含一個指定方法的細節信息;而GetMethods()返回這種引用的一個數組。

Assembly類允許訪問給定程序集的元數據,它也包含可以加載和執行程序集(假定該程序集是可執行的)的方法。與Type類一樣,Assembly類包含非常多的方法和屬性,這里只介紹與特性(//www.dadijd.cn/article/244250.htm)有關的成員,其它成員可以去MSDN(https://msdn.microsoft.com/zh-cn/library/system.reflection.assembly(v=vs.100).aspx)查看。



在使用Assembly實例做一些工作前,需要把相應的程序集加載到正在運行的進程中??梢允褂渺o態方法Assembly.Load()或Assembly.LoadFrom()。Load()方法的參數程序集的名稱,運行庫會在各個位置上搜索該程序集,這些位置包括本地目錄和全局程序集緩存。而LoadFrom()方法的參數是程序集的完整路徑名,它不會在其它位置搜索該程序集:
Assembly assembly1 = Assembly.Load(“WhatsNewAttributes"); Assembly assembly2 = Assembly.LoadFrom(“E:\WhatsNewAttributes\bin\Debug\WhatsNewAttributes");
這兩個方法都有許多其它重載版本。
Assembly類調用GetType()方法可以獲得相應程序集中定義的所有類型的詳細信息,它返回一個包含所有類型的詳細信息的System.Type引用數組:
Type[] types = assembly1.GetType();
foreach(Type t in types)
{
}如果需要確定程序集關聯了什么自定義特性,就需要調用Attribute類的一個靜態方法GetCustomAttributes():
Assembly assembly1 = Assembly.Load(“WhatsNewAttributes"); Attribute[] attribs = Attribute.GetCustomAttributes(assembly1);
GetCustomAttributes方法用于獲取程序集的特性,他有兩個重載方法:如果在調用它時,除了程序集的引用外,沒有其它參數,該方法就會返回這個程序集定義的所以自定義特性;如果指定第二個參數,第二個參數表示特性類的一個Type對象,GetCustomAttributes方法返回指定特性類型的特性數組。
所有的特性都作為一般的Attribute引用來獲取。如果需要調用為自定義特性定義的任何方法或屬性,就需要把這些引用顯示轉換為自定義特性類。
如果要獲得與方法,構造函數和字段等的特性,就需要調用MethodInfo,ConstructorInfo,FieldInfo等類的GetCustomAttributes()方法。
下面通過一個例子演示,自定義特性和反射
namespace WhatsNewAttributes
{
[AttributeUsage(
AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = true, Inherited = false)]
public class LastModifiedAttribute : Attribute
{
private readonly DateTime _dateModified;
private readonly string _changes;
public LastModifiedAttribute(string dateModified, string changes)
{
_dateModified = DateTime.Parse(dateModified);
_changes = changes;
}
public DateTime DateModified
{
get { return _dateModified; }
}
public string Changes
{
get { return _changes; }
}
public string Issues { get; set; }
}
[AttributeUsage(AttributeTargets.Assembly)]
public class SupportsWhatsNewAttribute : Attribute
{
}
} [assembly: SupportsWhatsNew]
namespace VectorClass
{
[LastModified("14 Feb 2010", "IEnumerable interface implemented " +
"So Vector can now be treated as a collection")]
[LastModified("10 Feb 2010", "IFormattable interface implemented " +
"So Vector now responds to format specifiers N and VE")]
class Vector : IFormattable, IEnumerable
{
public double x, y, z;
public Vector(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
[LastModified("10 Feb 2010", "Method added in order to provide formatting support")]
public string ToString(string format, IFormatProvider formatProvider)
{
if (format == null)
return ToString();
string formatUpper = format.ToUpper();
switch (formatUpper)
{
case "N":
return "|| " + Norm().ToString() + " ||";
case "VE":
return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
case "IJK":
StringBuilder sb = new StringBuilder(x.ToString(), 30);
sb.Append(" i + ");
sb.Append(y.ToString());
sb.Append(" j + ");
sb.Append(z.ToString());
sb.Append(" k");
return sb.ToString();
default:
return ToString();
}
}
public Vector(Vector rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
[LastModified("14 Feb 2010", "Method added in order to provide collection support")]
public IEnumerator GetEnumerator()
{
return new VectorEnumerator(this);
}
public override string ToString()
{
return "( " + x + " , " + y + " , " + z + " )";
}
public double this[uint i]
{
get
{
switch (i)
{
case 0:
return x;
case 1:
return y;
case 2:
return z;
default:
throw new IndexOutOfRangeException(
"Attempt to retrieve Vector element" + i);
}
}
set
{
switch (i)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default:
throw new IndexOutOfRangeException(
"Attempt to set Vector element" + i);
}
}
}
public static bool operator ==(Vector lhs, Vector rhs)
{
if (System.Math.Abs(lhs.x - rhs.x) < double.Epsilon &&
System.Math.Abs(lhs.y - rhs.y) < double.Epsilon &&
System.Math.Abs(lhs.z - rhs.z) < double.Epsilon)
return true;
else
return false;
}
public static bool operator !=(Vector lhs, Vector rhs)
{
return !(lhs == rhs);
}
public static Vector operator +(Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
}
public static Vector operator *(double lhs, Vector rhs)
{
return new Vector(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z);
}
public static Vector operator *(Vector lhs, double rhs)
{
return rhs * lhs;
}
public static double operator *(Vector lhs, Vector rhs)
{
return lhs.x * rhs.x + lhs.y + rhs.y + lhs.z * rhs.z;
}
public double Norm()
{
return x * x + y * y + z * z;
}
#region enumerator class
[LastModified("14 Feb 2010", "Class created as part of collection support for Vector")]
private class VectorEnumerator : IEnumerator
{
readonly Vector _theVector; // Vector object that this enumerato refers to
int _location; // which element of _theVector the enumerator is currently referring to
public VectorEnumerator(Vector theVector)
{
_theVector = theVector;
_location = -1;
}
public bool MoveNext()
{
++_location;
return (_location > 2) ? false : true;
}
public object Current
{
get
{
if (_location < 0 || _location > 2)
throw new InvalidOperationException(
"The enumerator is either before the first element or " +
"after the last element of the Vector");
return _theVector[(uint)_location];
}
}
public void Reset()
{
_location = -1;
}
}
#endregion
}
}namespace LookUpWhatsNew
{
internal class WhatsNewChecker
{
private static readonly StringBuilder outputText = new StringBuilder(1000);
private static DateTime backDateTo = new DateTime(2010, 2, 1);
private static void Main()
{
Assembly theAssembly = Assembly.Load("VectorClass");
Attribute supportsAttribute =
Attribute.GetCustomAttribute(
theAssembly, typeof (SupportsWhatsNewAttribute));
string name = theAssembly.FullName;
AddToMessage("Assembly: " + name);
if (supportsAttribute == null)
{
AddToMessage(
"This assembly does not support WhatsNew attributes");
return;
}
else
{
AddToMessage("Defined Types:");
}
Type[] types = theAssembly.GetTypes();
foreach (Type definedType in types)
DisplayTypeInfo(definedType);
MessageBox.Show(outputText.ToString(),
"What\'s New since " + backDateTo.ToLongDateString());
Console.ReadLine();
}
private static void DisplayTypeInfo(Type type)
{
// make sure we only pick out classes
if (!(type.IsClass))
return;
AddToMessage("\nclass " + type.Name);
Attribute[] attribs = Attribute.GetCustomAttributes(type);
if (attribs.Length == 0)
AddToMessage("No changes to this class");
else
foreach (Attribute attrib in attribs)
WriteAttributeInfo(attrib);
MethodInfo[] methods = type.GetMethods();
AddToMessage("CHANGES TO METHODS OF THIS CLASS:");
foreach (MethodInfo nextMethod in methods)
{
object[] attribs2 =
nextMethod.GetCustomAttributes(
typeof (LastModifiedAttribute), false);
if (attribs2 != null)
{
AddToMessage(
nextMethod.ReturnType + " " + nextMethod.Name + "()");
foreach (Attribute nextAttrib in attribs2)
WriteAttributeInfo(nextAttrib);
}
}
}
private static void WriteAttributeInfo(Attribute attrib)
{
LastModifiedAttribute lastModifiedAttrib =
attrib as LastModifiedAttribute;
if (lastModifiedAttrib == null)
return;
// check that date is in range
DateTime modifiedDate = lastModifiedAttrib.DateModified;
if (modifiedDate < backDateTo)
return;
AddToMessage(" MODIFIED: " +
modifiedDate.ToLongDateString() + ":");
AddToMessage(" " + lastModifiedAttrib.Changes);
if (lastModifiedAttrib.Issues != null)
AddToMessage(" Outstanding issues:" +
lastModifiedAttrib.Issues);
}
private static void AddToMessage(string message)
{
outputText.Append("\n" + message);
}
}
}“C#反射怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。