2009-05-19 12 views
19

Mam dwa obiekty Uri przeszedł do jakiegoś kodu, jedno jest katalog i innych jest nazwą pliku (lub ścieżki względnej)Jak połączyć URI

var a = new Uri("file:///C:/Some/Dirs"); 
var b = new Uri("some.file"); 

gdy próbuję i połączyć je tak:

var c = new Uri(a,b); 

uzyskać

file:///C:/Some/some.file

gdzie mogę wold spodziewają się uzyskać taki sam efekt jak z Path.Combine (jak to jest stary kod muszę wymienić):

file:///C:/Some/Dirs/some.file

Nie mogę myśleć o czystym roztworze do tego.

Brzydki rozwiązaniem jest dodanie / do Uri jeśli go tam nie ma

string s = a.OriginalString; 
if(s[s.Length-1] != '/') 
    a = new Uri(s + "/"); 
+0

dobrze, stosowanie path.combine i edytowane moją odpowiedź, to działa próbowałem –

Odpowiedz

16

Cóż, będziesz musiał powiedzieć Uri jakoś, że ostatnia część jest katalogiem, a nie plikiem. Używanie ukośnego ukośnika wydaje mi się najbardziej oczywistym sposobem.

Pamiętaj, że dla wielu Urisów odpowiedź, którą masz, jest dokładnie właściwa. Na przykład, jeśli Twoja przeglądarka renderuje

http://foo.com/bar/index.html 

i widzi stosunkowo ogniwo "other.html" to potem idzie do

http://foo.com/bar/other.html 

nie

http://foo.com/bar/index.html/other.html 

Korzystanie z końcowego znaku ukośnik na "katalogu" Uris to dość znany sposób sugerowania, że ​​względny Uris powinien po prostu dołączyć zamiast zastępować.

+0

Próbuję przekonwertować z używania łańcuchów i ścieżki. * Do używania Uri i konieczności duplikowania Path.Combine, a to nie działa w ten sposób. To będzie PITA, jeśli nie znajdę dobrego sposobu na zrobienie tego. – BCS

+0

Dlaczego nie utworzyć statycznej metody, aby zrobić to za Ciebie, podobnie jak w Path.Combine, która jest udokumentowana, aby * założyć * że pierwszy Uri ma być katalogiem, i jeśli to konieczne, dopiąć do niego ukośnik? –

+0

(Może to być nawet metoda rozszerzenia, jeśli chcesz i jeśli używasz C# 3.) –

2

dodać końcówkę cięciem pierwszej URI, URI zignoruje więcej niż jeden ukośnik (/)

var a = new Uri("file:///C:/Some/Dirs/"); 

EDIT:

var a = new Uri("file:///C:/Some/Dirs"); 
var b = new Uri("some.file", UriKind.Relative); 
var c = new Uri(Path.Combine(a.ToString(), b.ToString())); 
MessageBox.Show(c.AbsoluteUri); 
+1

To prawie dokładnie kod, któremu zlecono mi zastąpienie ing :) – BCS

+0

nadal nie rozumiem, co chcesz :) masz katalog URI i plik URI, i starasz się je połączyć, dlaczego nie chcesz dodać końcowy ukośnik bezpośrednio koniec katalogu uri .. nie ma różnica między "file: /// c: /some/dir/some.file" i "file: /// c:/some/dir ////////////////// some.file " –

+0

Nie działa, jeśli drugi uri zaczyna się od ukośnika. –

0

Dlaczego po prostu nie odziedziczysz po Uri i nie używaj tego, tj. zrobić w konstruktorze to, co musisz zrobić, aby to naprawić? Refaktoryzacja jest tania, zakładając, że jest wewnętrzna do montażu lub w zasięgu ..

+0

Nie ma żadnej przewagi nad Jonem. Czy czegoś brakuje? – BCS

+0

Prawdopodobnie nie .. to znowu, jeśli masz część schematu w jednym z nich, możesz już domyślnie stwierdzić, że to ta, która wymaga szczególnej uwagi. Zakłada to, że masz literały w każdym miejscu. Naprawiasz je na miejscu w wersji dosłownej lub w nowym typie. Być może czegoś brakuje. –

+0

Jeśli mam go corret, najlepszym sposobem byłoby parsować kod dla lokalnych deklaracji i wyrażeń przypisania i typu Uri z zawartą częścią programu. Całkiem silna zasada, a jeśli zawiera, to wprowadzi kreskę. Będziesz potrzebował dobrego parsera, ale szybki hack też może to zrobić. –

5

Możesz wypróbować tę metodę rozszerzenia! Działa zawsze!;-)

public static class StringExtension 
    { 
     public static string UriCombine(this string str, string param) 
     { 
      if (!str.EndsWith("/")) 
      { 
       str = str + "/"; 
      } 
      var uri = new Uri(str); 
      return new Uri(uri, param).AbsoluteUri; 
     } 
    } 

Angelo, Alessandro

+0

Myślę, że to najlepsza odpowiedź. Wskazówką jest upewnienie się, że podstawa uri kończy się znakiem "/", a drugi ostatni element ścieżki w bazie uri zostanie obcięty nowym Uri (podstawowym, względnym). "http: // localhost/api/Controller" + "Method" => "http: // localhost/api/Method" while "http: // localhost/api/Controller /" + "Method =>" http:// localhost/api/Controller/Method ". – Frode

19

To powinno wystarczyć dla Ciebie:

var baseUri = new Uri("http://www.briankeating.net"); 
var absoluteUri = new Uri(baseUri, "/api/GetDefinitions"); 

Ten constructor wykonać standardowe względne zasady URI więc / są ważne:

  • http://example.net + foo = http://example.net/foo
  • http://example.net/foo/bar + baz = http://example.net/foo/baz
  • http://example.net/foo/ + bar = http://example.net/foo/bar
  • http://example.net/foo + bar = http://example.net/bar
  • http://example.net/foo/bar/ + /baz = http://example.net/baz
+1

Będzie działać tylko wtedy, gdy nie ma innej ścieżki po domenie, na przykład: var baseUri = new Uri ("http://www.briankeating.net/api"); var absoluteUri = new Uri (baseUri, "GetDefinitions"); Zastąpi api dla GetDefinitions, w wyniku czego http://www.briankeating.net/GetDefinitions –

+3

@ bruno.bologna: Dodaj końcowy slash do parametru baseUri i powinieneś uzyskać pożądany efekt: 'new Uri (new Uri (" http://briankeating.net/api/ ")," GetDefinitions ")'. – Kivin