2009-05-19 20 views
19

He pasado dos objetos Uri en un cierto código, uno es un directorio y el otro es un nombre de archivo (o una ruta relativa)¿Cómo combinar los URI

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

cuando intento y combinarlos como esto:

var c = new Uri(a,b); 

me sale

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

donde me harían lo esperan obtener el mismo efecto que con Path.Combine (ya que es el antiguo código tengo que sustituir):

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

no puedo pensar en una solución limpia a esto.

La solución fea siendo añadir un / a la URI si no está ahí

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

así, el uso path.combine i editado mi respuesta, Trabajé intenté –

Respuesta

16

Bueno, vas a tener que decirle al Uri de alguna manera que la última parte es un directorio en lugar de un archivo. Usar una barra inclinada parece ser la forma más obvia para mí.

Tenga en cuenta que para muchos Uris, la respuesta que tiene es exactamente correcta. Por ejemplo, si su navegador web está haciendo

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

y se ve relativamente enlace de "other.html" que luego va a

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

no

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

El uso de un remolque barra inclinada en el "directorio" Uris es una forma bastante familiar de sugerir que Uris relativa solo debe agregarse en lugar de reemplazar.

+0

Estoy tratando de convertir el uso de cadenas y Path. * A usar Uri y la necesidad de duplicar Path.Combine y eso no funciona de esta manera. Va a ser un PITA si no encuentro una buena manera de hacer esto. – BCS

+0

¿Por qué no crear un método estático para hacerlo por usted, similar a Path.Combine, que está documentado para * asumir * que el primer Uri está destinado a ser un directorio, y agregará una barra inclinada si es necesario? –

+0

(Incluso podría ser un método de extensión, si lo desea y si está usando C# 3.) –

2

añadir un extremo tajo de su primera uri, URI ignorará más de una barra inclinada (/)

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

Ese es el código casi exactamente que tengo la tarea de replac ing :) – BCS

+0

todavía no entiendo lo que quieres :) tienes un directorio uri y un archivo uri, e intentas combinarlos, por qué no quieres agregar una barra final directamente al final del directorio uri ... no hay diferencia entre "file: /// c: /some/dir/some.file" y "file: /// c:/some/dir ////////////////// some.file " –

+0

No funciona si el segundo uri comienza con una barra inclinada. –

0

¿Por qué no heredar de Uri y usar eso, es decir. hacer en constructor lo que necesita hacer para arreglarlo? La refabricación es económica, suponiendo que es interna para el ensamblaje o al alcance de la mano.

+0

Eso no tiene ninguna ventaja que veo sobre la opción de Jon. ¿Me estoy perdiendo de algo? – BCS

+0

Probablemente no ... por otra parte, si tiene una parte de esquema en una de ellas, ya puede decir implícitamente que es la que requiere una atención especial. Esto supone que tienes literales por todos lados. Ya sea que los arregles en el sitio en el tipo literal o con el nuevo tipo. Tal vez me falta algo. –

+0

Si obtuve la correlación, la mejor manera sería analizar el código de las declaraciones locales y las expresiones de asignación y el tipo URI con la parte del esquema contenida. Una regla bastante sólida, y si lo contiene, introduce una barra inclinada. Necesitarás un buen analizador, pero un truco rápido podría hacerlo también. –

5

¡Puede probar este método de extensión! Funciona siempre!;-)

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

Creo que esta es la mejor respuesta. La clave es asegurar que la uri base termine con un carácter "/", mientras que el último elemento de camino en la base uri se recortará con un nuevo Uri (base, relativo). "http: // localhost/api/Controller" + "Method" => "http: // localhost/api/Method" mientras "http: // localhost/api/Controller /" + "Method =>" http:// localhost/api/Controller/Method ". – Frode

19

Esto debería hacer el truco para usted:

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

Este constructor siguen las reglas relativas URI estándar por lo que el / son importantes:

  • 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

Solo funcionará si no hay otra ruta después del dominio, por ejemplo: var baseUri = new Uri ("http://www.briankeating.net/api"); var absoluteUri = new Uri (baseUri, "GetDefinitions"); Reemplazará la API de GetDefinitions, lo que dará como resultado http://www.briankeating.net/GetDefinitions –

+3

@ bruno.bologna: Agregue una barra diagonal al parámetro baseUri y debe obtener el efecto deseado: 'new Uri (new Uri (" http://briankeating.net/api/ ")," GetDefinitions ")'. – Kivin

Cuestiones relacionadas