水如烟

秋里生活,恬淡宁静。那如洗碧空,那伏黄草地,风凉夜寂,心儿涌动,情绪萦绕。可以凭窗,可以临江,可以坐,可以仰卧,可以独处,可以相依。倚明月,抚清辉,人生多少情怀,尽在秋里?

原创 处理隐蔽的类或类的隐蔽属性TypeHelper 收藏

新一篇: HOW TO:判断主程序是Windows应用程序还是控制台应用程序 | 旧一篇: 复数类的设计及其应用:复数类的设计

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 AssemblyByVal fullTypeName As String)
            
Me.InternalCreate(assembly, fullTypeName)

            
Me.InternalCheckIsValid(fullTypeName, True)
        
End Sub

        
Sub New(ByVal referrenceType As Type, ByVal typeName As StringOptional ByVal isNestedType As Boolean = False)

            
Dim mAssembly As Assembly = referrenceType.Assembly

            
Me.InternalCreate(mAssembly, typeName)

            
If Me.InternalCheckIsValid(typeNameFalseThen 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 AssemblyByVal fulltypename As String)
            gType 
= ass.GetType(fulltypename, FalseTrue)
        
End Sub

        
Private Function InternalCheckIsValid(ByVal typename As StringByVal throwOnError As BooleanAs 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 StringByVal isNestedType As BooleanAs 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 ObjectAs 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 StringByVal ParamArray args() As ObjectAs Object
            
Return Me.CurrentType.InvokeMember( _
                name, _
                MemberGetBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Function


        
Public Sub SetMemberValue(ByVal name As StringByVal ParamArray args() As Object)
            
Me.CurrentType.InvokeMember( _
                name, _
                MemberSetBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Sub

        
Public Function MethodInvoke(ByVal name As StringByVal ParamArray args() As ObjectAs Object
            
Return Me.CurrentType.InvokeMember( _
                name, _
                MethodBinding, _
                
Nothing, _
                
Me.CurrentObject, _
                args)
        
End Function

        
Public Function NewInstance(ByVal ParamArray args() As ObjectAs 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 StringAs 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 ObjectByVal name As StringByVal ParamArray args() As ObjectAs Object
            
Dim mHelper As New TypeHelper(obj)
            
Return mHelper.GetMemberValue(name, args)
        
End Function

        
Public Shared Sub HSetMemberValue(ByVal obj As ObjectByVal name As StringByVal ParamArray args() As Object)
            
Dim mHelper As New TypeHelper(obj)
            mHelper.SetMemberValue(name, args)
        
End Sub

        
Public Shared Function HMethodInvoke(ByVal obj As ObjectByVal name As StringByVal ParamArray args() As ObjectAs Object
            
Dim mHelper As New TypeHelper(obj)
            
Return mHelper.MethodInvoke(name, args)
        
End Function

        
Public Shared Function HNewInstance(ByVal refobj As ObjectByVal ParamArray args() As ObjectAs Object
            
Dim mHelper As New TypeHelper(refobj)
            
Return mHelper.NewInstance(args)
        
End Function

        
Public Shared Function HFindMember(ByVal obj As ObjectByVal name As StringAs 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 StringByVal 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 StringByVal 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

发表于 @ 2007年11月17日 23:16:00|评论(loading...)|收藏

新一篇: HOW TO:判断主程序是Windows应用程序还是控制台应用程序 | 旧一篇: 复数类的设计及其应用:复数类的设计

评论

#qinboody 发表于2008-04-15 16:21:02  IP: 219.134.253.*
幫幫忙阿.小弟新手. 看了半天還是看不懂怎么改妳的代碼才能實現.根據變量的名稱(string)得到該變量的值.
能不能為我寫個函數呢?
小弟拜謝!
发表评论  


登录
Csdn Blog version 3.1a
Copyright © 水如烟