¿Cómo cambiar entre el tipo “posible” de un objeto?

Posible duplicado:
C # – ¿Hay una mejor alternativa que esta para ‘encender el tipo’?

El código heredado de mi compañía tiene algo como lo siguiente

public override Uri GetUri(object obj) { if ((obj is Entry) || (obj is EntryComment)) { // } if (obj is Blog) { // } // if obj is blah blah blah } 

Este método es feo. Quiero refactorizarlo, pero no conozco una técnica para iterar sobre los tipos “posibles” que pueden ser obj.

¿Cómo puedo refactorizar esto?

Gracias.

También puede refactorizar esto con interfaces

 public interface IHasUri { public Uri GetUri(); } 

e implementa esta interfaz en toda tu jerarquía. De lo que puedes usar

 public Uri GetUri(object obj) { IHasUri hasUri = obj as IHasUri; if(hasUri != null) Uri uri = hasUri.GetUri(); // bla bla bla } 

Un par de opciones:

  • Si está utilizando C # 4, puede usar el tipado dynamic y dividir el método en varias sobrecargas:

     public Uri GetUri(dynamic obj) { return GetUriImpl(obj); } private Uri GetUriImpl(Entry entry) { ... } private Uri GetUriImpl(EntryComment comment) { ... } 

    En este caso, es probable que desee algún tipo de método de “protección” en caso de que no sea un tipo conocido.

  • Puede crear un Dictionary> :

     private static Dictionary> UriProviders = new Dictionary> { { typeof(Entry), value => ... }, { typeof(EntryComment), value => ... }, { typeof(Blog), value => ... }, }; 

    y entonces:

     public Uri GetUri(object obj) { Func provider; if (!UriProviders.TryGetValue(obj.GetType(), out provider)) { // Handle unknown type case } return provider(obj); } 

    Tenga en cuenta que esto no cubrirá el caso en el que reciba un subtipo de Entry etc.

Ninguno de estos es particularmente agradable, fíjate … Sospecho que un rediseño de nivel superior puede ser preferible.

Creo que Lasse V. Karlsen tiene el derecho en sus comentarios, un rediseño es más apropiado quizás

Podrías crear una interfaz como sugiere Stecya

 public interface IUriAccessible { //or some sort of a more descriptive name Uri Url {get;} } 

y luego, para cada objeto que le interese, por ejemplo, Entry , podría

 public class Entry:IUriAccessible { //... other code here public Uri Url { get { //return uri here } } } 

y ahora puedes simplemente llamarlo al objeto

 var entry = new Entry(); var uri = entry.Url; 

Puede tener una List() con todos los tipos que desee verificar e iterar esa lista. pero no creo que eso haga que el código sea más rápido.

No se pueden switch-case tipos de switch-case .

Una expresión de interruptor o etiqueta de caso debe ser un bool, char, string, integral, enum o tipo anulable correspondiente