這個類是用來處理隱蔽的類或類的隱蔽屬性。說實話,我並不想將它貼出來。但後面的很多處理,都需要它。所以貼了出來。
不想貼出來,並非是它有什麼高深的技術,相反,它非常簡單。不想貼的原因是,它反映的“歪道”思路可能影響你對.Net的理解。
我不是編程或者是真正意義上的IT職員,我學習.NET應用.Net僅僅是用來保持自己的腦袋還處於思索狀態,不至於因生活而麻木。
況且,我只接觸WinForm。我學習.Net的興趣就來源於走“歪道”。切記,僅供參考。
TypeHelper.vb
Imports System.Reflection
Namespace LzmTW.uSystem.uReflection
Public Class TypeHelper
Private gType As Type
Private gCurrentObjct As Object
Public ReadOnly Property CurrentType() As Type
Get
Return gType
End Get
End Property
Public ReadOnly Property CurrentObject() As Object
Get
Return gCurrentObjct
End Get
End Property
Sub New(ByVal referrenceObj As Object)
If Me.IsType(referrenceObj) Then
Me.gType = CType(referrenceObj, Type)
Else
Me.gType = referrenceObj.GetType
Me.gCurrentObjct = referrenceObj
End If
End Sub
Sub New(ByVal assembly As Assembly, ByVal fullTypeName As String)
Me.InternalCreate(assembly, fullTypeName)
Me.InternalCheckIsValid(fullTypeName, True)
End Sub
Sub New(ByVal referrenceType As Type, ByVal typeName As String, Optional ByVal isNestedType As Boolean = False)
Dim mAssembly As Assembly = referrenceType.Assembly
Me.InternalCreate(mAssembly, typeName)
If Me.InternalCheckIsValid(typeName, False) Then Return
Dim mFullTypeName As String = GetFullTypeName(referrenceType, typeName, isNestedType)
Me.InternalCreate(mAssembly, mFullTypeName)
Me.InternalCheckIsValid(mFullTypeName, True)
End Sub
Private Sub InternalCreate(ByVal ass As Assembly, ByVal fulltypename As String)
gType = ass.GetType(fulltypename, False, True)
End Sub
Private Function InternalCheckIsValid(ByVal typename As String, ByVal throwOnError As Boolean) As Boolean
If gType Is Nothing Then
If throwOnError Then
Throw New ArgumentException(String.Format("typeName: {0} 不存在", typename))
Else
Return False
End If
End If
Return True
End Function
Private Function GetFullTypeName(ByVal referrenceType As Type, ByVal typeName As String, ByVal isNestedType As Boolean) As String
Dim mFullName As String = Nothing
Dim mRefFullName As String = referrenceType.FullName
If isNestedType Then
mFullName = String.Concat(mRefFullName, "+", typeName)
Else
Dim mLastIndex As Integer = mRefFullName.LastIndexOf(referrenceType.Name)
mFullName = String.Concat(mRefFullName.Substring(0, mLastIndex), typeName)
End If
Return mFullName
End Function
Private Function IsType(ByVal instance As Object) As Boolean
Return instance.GetType.IsSubclassOf(GetType(Type))
End Function
Public Const Binding As BindingFlags = _
BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic Or _
BindingFlags.Static Or _
BindingFlags.CreateInstance Or _
BindingFlags.IgnoreCase
End Class
End Namespace
TypeHelper.Methods.vb
Imports System.Reflection
Namespace LzmTW.uSystem.uReflection
Partial Class TypeHelper
Public Sub SetCurrentObj(ByVal obj As Object)
If Not obj Is Nothing AndAlso Not Me.CurrentType.IsInstanceOfType(obj) Then
Throw New ArgumentException("實例類型與內部類型不相符")
End If
Me.gCurrentObjct = obj
End Sub
Public Function GetMemberValue(ByVal name As String, ByVal ParamArray args() As Object) As Object
Return Me.CurrentType.InvokeMember( _
name, _
MemberGetBinding, _
Nothing, _
Me.CurrentObject, _
args)
End Function
Public Sub SetMemberValue(ByVal name As String, ByVal ParamArray args() As Object)
Me.CurrentType.InvokeMember( _
name, _
MemberSetBinding, _
Nothing, _
Me.CurrentObject, _
args)
End Sub
Public Function MethodInvoke(ByVal name As String, ByVal ParamArray args() As Object) As Object
Return Me.CurrentType.InvokeMember( _
name, _
MethodBinding, _
Nothing, _
Me.CurrentObject, _
args)
End Function
Public Function NewInstance(ByVal ParamArray args() As Object) As Object
Dim mParaCount As Integer = args.Length
Dim mCtors As ConstructorInfo() = Me.CurrentType.GetConstructors(MethodBinding)
For Each ctro As ConstructorInfo In mCtors
If ctro.GetParameters.Length = mParaCount Then
Return ctro.Invoke(args)
End If
Next
Return Nothing
End Function
'''''' <summary>
'''''' 可以使用*?[abc][!abc],忽略大小寫
'''''' </summary>
Public Function FindMember(ByVal name As String) As MemberInfo()
If String.IsNullOrEmpty(name) OrElse name = "*" Then
Return Me.CurrentType.GetMembers(Binding)
End If
Dim mPattern As String = "*[*?]*"
If Not name Like mPattern Then Return Me.CurrentType.GetMember(name, Binding)
Dim mArray As New List(Of MemberInfo)
For Each m As MemberInfo In Me.CurrentType.GetMembers(Binding)
If m.Name.ToLower Like name.ToLower Then
mArray.Add(m)
End If
Next
Return mArray.ToArray
End Function
Private MemberGetBinding As BindingFlags = _
BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic Or _
BindingFlags.Static Or _
BindingFlags.GetFIEld Or _
BindingFlags.GetProperty Or _
BindingFlags.IgnoreCase
Private MemberSetBinding As BindingFlags = _
BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic Or _
BindingFlags.Static Or _
BindingFlags.SetFIEld Or _
BindingFlags.SetProperty Or _
BindingFlags.IgnoreCase
Private MethodBinding As BindingFlags = _
BindingFlags.Instance Or _
BindingFlags.Public Or _
BindingFlags.NonPublic Or _
BindingFlags.Static Or _
BindingFlags.InvokeMethod Or _
BindingFlags.IgnoreCase
End Class
End Namespace
TypeHelper.Shared.vb
Imports System.Reflection
Namespace LzmTW.uSystem.uReflection
Partial Class TypeHelper
Public Shared Function HGetMemberValue(ByVal obj As Object, ByVal name As String, ByVal ParamArray args() As Object) As Object
Dim mHelper As New TypeHelper(obj)
Return mHelper.GetMemberValue(name, args)
End Function
Public Shared Sub HSetMemberValue(ByVal obj As Object, ByVal name As String, ByVal ParamArray args() As Object)
Dim mHelper As New TypeHelper(obj)
mHelper.SetMemberValue(name, args)
End Sub
Public Shared Function HMethodInvoke(ByVal obj As Object, ByVal name As String, ByVal ParamArray args() As Object) As Object
Dim mHelper As New TypeHelper(obj)
Return mHelper.MethodInvoke(name, args)
End Function
Public Shared Function HNewInstance(ByVal refobj As Object, ByVal ParamArray args() As Object) As Object
Dim mHelper As New TypeHelper(refobj)
Return mHelper.NewInstance(args)
End Function
Public Shared Function HFindMember(ByVal obj As Object, ByVal name As String) As MemberInfo()
Dim mHelper As New TypeHelper(obj)
Return mHelper.FindMember(name)
End Function
End Class
End Namespace
上面說到“歪道”,在下面一個例子可以看到。
注:變量的安全問題我曾經想過“研究”一番,可最後還是沒研下來,因為我覺得那些東西太費腦了,有點吃力。
示例:怎麼保證User的信息安全
Imports System.Security
Imports System.Runtime.InteropServices
Public Class User
Private gName As String
Private gPassWord As SecureString
Sub New(ByVal name As String, ByVal passWord As String)
Me.gName = name
Me.gPassWord = New SecureString
For Each c As Char In passWord.ToCharArray
Me.gPassWord.AppendChar(c)
Next
Me.gPassWord.MakeReadOnly()
;End Sub
Public ReadOnly Property Name() As String
Get
Return gName
End Get
End Property
Public ReadOnly Property PassWord() As String
Get
Return Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(gPassWord))
End Get
End Property
Public Overloads Function ToString()
Return String.Format("my name is {0}, pass is {1} ", Me.Name, Me.PassWord)
End Function
End Class
測試:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As New User("LzmTW", "bybyMycsdn")
Login(t)
''changed
Dim helper As New LzmTW.uSystem.uReflection.TypeHelper(t)
Console.WriteLine("name changed!")
helper.SetMemberValue("gname", "lzm")
Login(t)
Dim tmp As New Security.SecureString
tmp.AppendChar("h")
tmp.AppendChar("e")
tmp.AppendChar("h")
tmp.AppendChar("e")
Console.WriteLine("pass changed!")
helper.SetMemberValue("gPassWord", tmp)
Login(t)
End Sub
Private Sub Login(ByVal user As User)
Console.WriteLine(user.ToString)
Console.WriteLine()
End Sub
End Class
結果:
my name is LzmTW, pass is bybyMycsdn
name changed!
my name is lzm, pass is bybyMycsdn
pass changed!
my name is lzm, pass is hehe
對於構造函數是私有的類,我們也能實例化。
示例:
Imports System.Security
Imports System.Runtime.InteropServices
Public Class User
Private gName As String
Private gPassWord As SecureString
''注意構造函數是私有的
Private Sub New(ByVal name As String, ByVal passWord As String)
Me.gName = name
Me.gPassWord = New SecureString
For Each c As Char In passWord.ToCharArray
Me.gPassWord.AppendChar(c)
Next
Me.gPassWord.MakeReadOnly()
End Sub
Public ReadOnly Property Name() As String
Get
Return gName
End Get
End Property
Public ReadOnly Property PassWord() As String
Get
Return Marshal.PtrToStringAuto(Marshal.SecureStringToBSTR(gPassWord))
End Get
End Property
Public Overloads Function ToString()
Return String.Format("my name is {0}, pass is {1} ", Me.Name, Me.PassWord)
End Function
End Class
測試:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim t As User
Dim helper As New LzmTW.uSystem.uReflection.TypeHelper(GetType(User))
''create instance
t = CType(helper.NewInstance("LzmTW", "Hello"), User)
Login(t)
End Sub
Private Sub Login(ByVal user As User)
Console.WriteLine(user.ToString)
Console.WriteLine()
End Sub
End Class
結果:
my name is LzmTW, pass is Hello