Die Methode ResolveClientUrl aus der control-Klasse, ist vor allem in Webs mit sehr tiefen Strukturen, sehr praktisch, um zum Beispiel den Pfad zu einer Bilddatei für den Client in einen relativen Pfad aufzulösen, denn nicht immer möchte oder kann man auf ASP.NET-Server-Controls zurückgreifen, die ja Tilde-Url's automatisch darüber auflösen.
Das für ASP.NET spezifische Tilde-Zeichen am Anfang einer Url ist ein Platzhalter für die Wurzel der ASP.NET-Anwendung, die nicht immer mit dem Root der WebSite übereinstimmen muss. Mit Hilfe dieses Platzhalters und der möglichen Auflösung eines solchen Pfades durch ASP.NET, egal in welche Ebene der Site, funktionieren erst Dinge wie die Kapselung bestimmer Funktionalitäten in UserControls.
Nun kommt es vor, dass der ordentliche Entwickler bestimmte, immer wiederkehrende Methoden, in eine eigene Klasse auslagern möchte, auf deren Methoden über das Shared-Attribut von überall aus zugegriffen werden soll. In solchen Methoden ist die Auflösung eines Pfades über ResolveClientUrl auf den ersten Blick nicht möglich, wenn die Klasse nicht gerade von System.Web.UI.Control erbt.
Anstatt sich nun mit allerlei Hilfskonstruktionen zu behelfen oder den Code doch lieber redundant zu halten, sollte man sich einmal ansehen wie ResolveClientUrl überhaupt implementiert ist. Lutz Roeders .NET Reflector ist da die erste Anlaufstation.
Da die Methode auf dem Interface IUrlResolutionService basiert, spricht nichts dagegen, das Interface dazu zu verwenden, um einer Funktion, in der ResolveClientUrl benötigt wird, als Parameter einen "Handler" mitzugeben, der das Interface implementiert: ein Objekt das von Control erbt.
Eine sehr simple Funktion als Beispiel:
Public Shared Function GetMyImageUrl( _
ByVal objUrlResolver As IUrlResolutionService) As String
Dim strImagePath As String = "~/images/me.jpg"
Return objUrlResolver.ResolveClientUrl(strImagePath)
End Function
Aufgerufen wird die Methode zum Beispiel aus einer ASPX-Seite heraus dann wie folgt:
Dim strMyImageUrl As String = Tools.GetMyImageUrl(Me.Page)
Das Page-Objekt, das bekanntlich ja auch von Control erbt, fungiert hier als der "Resolver", über den die Methode ResolveClientUrl aufgerufen werden kann.
Update
Peter hat mit seinem Kommentar natürlich völlig recht. Es gibt allerdings eine weitere Methode, die sehr simpel ist:
Public Shared Function ResolveClientURL(ByVal strPath As String) As String
Dim gc As HtmlGenericControl = New HtmlGenericControl
Return gc.ResolveClientUrl(strPath)
End Function
Man leiht sich die Funktionalität schlicht von einem Generic-Control aus...