Author:水如烟
也见论坛贴子,你知道吗
这个类是用来处理隐蔽的类或类的隐蔽属性。说实话,我并不想将它贴出来。但后面的很多处理,都需要它。所以贴了出来。
不想贴出来,并非是它有什么高深的技术,相反,它非常简单。不想贴的原因是,它反映的“歪道”思路可能影响你对.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
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
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
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
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
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
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
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