HOW TO:程序集内读取内嵌默认资源

来源:岁月联盟 编辑:zhu 时间:2006-05-24
Author:水如烟

当用Reflector查看程序集资源时,我们通常都会看到三个类SR,SRCategoryAttribute和SRDescriptionAttribute,来读取当前程序集的资源信息。
在这里,所谓的默认我指的是在Framework2.0里。默认的资源名称一般是[RootNameSpace].Resources.resources。
三个类的代码在各程序集中基本是一样的,但因为各自的资源有异,它的Resourcemanager定义为Private,而其它的变量和方法,基本上是Shared。再一点,它只服务于本程序集,所以多用Friend限制作用范围。代码有些技巧,稍增改,如下:

SR.VB
Imports System.Resources, System.Globalization

Friend NotInheritable Class SR

    '如是特殊名称,在这修改。默认的为[RootNameSpace].Resources.resources
    Friend Sub New()
        Dim localAssembly As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly
        Dim baseName As String = Nothing
        For Each resourceName As String In localAssembly.GetManifestResourceNames
            If System.Text.RegularExpressions.Regex.IsMatch(resourceName, ".Resources.resources$")  Then
                baseName = resourceName
                Exit For
            End If
        Next
        Me.m_resources = New ResourceManager(baseName, localAssembly)
    End Sub

    Private Shared Function GetLoader() As SR
        If SR.loader Is Nothing Then
            SyncLock SR.InternalSyncObject
                If SR.loader Is Nothing Then
                    SR.loader = New SR
                End If
            End SyncLock
        End If
        Return loader
    End Function

    Public Shared Function GetObject(ByVal name As String) As Object
        SR.GetLoader()
        If SR.loader Is Nothing Then
            Return Nothing
        End If

        Return SR.Resources.GetObject(name, SR.Culture)
    End Function

    Public Shared Function GetString(ByVal name As String) As String
        SR.GetLoader()
        If SR.loader Is Nothing Then
            Return Nothing
        End If

        Return SR.Resources.GetString(name, SR.Culture)
    End Function

    Public Shared Function GetString(ByVal name As String, ByVal ParamArray args As Object()) As String
        SR.GetLoader()
        If SR.loader Is Nothing Then
            Return Nothing
        End If

        Dim Result As String
        Result = SR.Resources.GetString(name, SR.Culture)
        If ((args Is Nothing) OrElse (args.Length <= 0)) Then
            Return Result
        End If

        Dim argsCount As Integer = 0
        Do While argsCount < args.Length
            Dim argString As String = TryCast(args(argsCount), String)
            If (Not argString Is Nothing) AndAlso (argString.Length > 1024) Then
                args(argsCount) = (argString.Substring(0, 1021) & "")
            End If
            argsCount += 1
        Loop

        Return String.Format(CultureInfo.CurrentCulture, Result, args)
    End Function


    Private Shared ReadOnly Property Culture() As CultureInfo
        Get
            Return Nothing '取本地CultureInfo
        End Get
    End Property

    Private Shared ReadOnly Property InternalSyncObject() As Object
        Get
            If (SR.s_InternalSyncObject Is Nothing) Then
                Dim tmpObj As New Object
                System.Threading.Interlocked.CompareExchange(SR.s_InternalSyncObject, tmpObj, Nothing)
            End If
            Return SR.s_InternalSyncObject
        End Get
    End Property

    Public Shared ReadOnly Property Resources() As ResourceManager
        Get
            Return SR.loader.m_resources
        End Get

    End Property


    Private Shared loader As SR
    Private Shared s_InternalSyncObject As Object

    Private m_resources As ResourceManager

    'Friend Const Text1 As String = "Text1"
End Class
SRCategoryAttribute.VB
Imports System.ComponentModel

<AttributeUsage(AttributeTargets.All)> _
Friend NotInheritable Class SRCategoryAttribute
    Inherits CategoryAttribute

    Public Sub New(ByVal category As String)
        MyBase.New(category)
    End Sub

    Protected Overrides Function GetLocalizedString(ByVal value As String) As String
        Return SR.GetString(value)
    End Function
End Class
SRDescriptionAttribute.VB
Imports System.ComponentModel

<AttributeUsage(AttributeTargets.All)> _
Friend NotInheritable Class SRDescriptionAttribute
    Inherits DescriptionAttribute

    Private replaced As Boolean

    Public Sub New(ByVal description As String)
        MyBase.New(description)
    End Sub

    Public Overrides ReadOnly Property Description() As String
        Get
            If Not Me.replaced Then
                Me.replaced = True
                MyBase.DescriptionValue = SR.GetString(MyBase.Description)
            End If
            Return MyBase.Description
        End Get
    End Property

End Class