2011-10-04 5 views
6

que tiene la siguiente función en C#:azúcar Sintaxis para la función de doble genérica

bool Handle<TCommandHandler, TModel>(TModel model) where TCommandHandler : ICommandHandler<TModel> { 
    // ... 
    _container.Resolve<TCommandHandler>(); 
    // ... 
} 

Desde TModel se desprende de un parámetro de función Quiero un poco de manera de no especificar su tipo cuando se llama a una función. Lo ideal es que quiero llamar así:

Handle<MyCommandHandler>(model); 

Dado que este es probablemente imposible, me ocurrió lo siguiente:

HandleTemp<TModel> Handle<TModel>(TModel model) { 
    return new HandleTemp<TModel>(model); 
} 

public class HandleTemp<TModel> { 
    private TModel _model; 
    public HandleTemp(TModel model) { _model = model;} 

    public bool With<TCommandHandler>() where TCommandHandler : ICommandHandler<TModel> { 
    } 
} 

Así que ahora estoy llamándolo como:

Handle(model).With<MyCommandHandler>(); 

¿Hay otras posibilidades? ¿Hice algo completamente incorrecto con mi solución?

+0

Si el método fuera estática, entonces esto se podría haber hecho mejor en un '' clase estática. – nawfal

Respuesta

4

No, su análisis y solución parecen correctos. De hecho, la inferencia de tipo genérico solo puede funcionar sobre la base de todo o nada. Si hay algunos parámetros genéricos que no se pueden inferir, todos deben estar explícitamente establecidos. Personalmente, me gustaría una manera de decir "te preocupas por estos parámetros, te lo digo", pero ... eso no existe.

La única otra opción es añadir un artificial adicional parámetro regular para permitir que se inferir el parámetro genérico - un poco asqueroso.

Otra opción: cuestionar la suposición de que aquí se necesitan genéricos. Por ejemplo, ¿podría ser una instancia de Type? Podría:

bool Handle<TModel>(TModel model, Type type)... 
... 
Handle(model, typeof(MyCommandHandler)); 

¿trabajo, por ejemplo? No puedo responder esto directamente, ya que no conozco los detalles de su método _container.Resolve<TCommandHandler>();, en cuanto a si que podría ajustarse para tomar Type en lugar de <T>.

+1

Sí, eso podría convertirse fácilmente en argumento de 'Tipo', pero me gustaría tener una comprobación en tiempo de compilación (esa oferta de tipos genéricos) para que sea imposible pasar en un 'Tipo' que no implementa mi ICommandHandler . Gracias por revisar mi implementación :) – Shaddix

+0

Consulte también la respuesta de Eric Lippert a una pregunta sobre [Mumble Typing] (http://stackoverflow.com/questions/5693503/what-is-mumble-typing/5693505#5693505). – Brian

1

Todas las necesidades del compilador C# son una demostración del tipo en los argumentos, así que en lugar de intentar ubicarlo en los argumentos genéricos (en el sitio de uso) haga algo que le permita proporcionar un argumento que ayude al compilador a identificar tipo. Para que sea menos confusa, he aquí un ejemplo:

// Your classes/interfaces. 
class Container 
{ 
    public static T Resolve<T>() 
    { 
     Console.WriteLine("Resolving {0}", typeof(T).FullName); 
     return default(T); 
    } 
} 
interface ICommandHandler<TModel> 
{ 
    void DoSomething(); 
} 

// An implemented ICommandHandler. 
public class WackyCommandHandler : ICommandHandler<string> 
{ 
    public void DoSomething() { } 
} 

// Used to help the C# compiler identify types. 
public static class Identify 
{ 
    public static TypeIdentity<TType> TheType<TType>() 
    { 
     return null; // You don't actually need an instance. 
    } 
} 
public sealed class TypeIdentity<TType> 
{ 
    private TypeIdentity() { } 
} 

// Your method 
static bool Handle<TCommandHandler, TModel>(TModel model, TypeIdentity<TCommandHandler> handler) 
    where TCommandHandler : ICommandHandler<TModel> 
{ 
    var item = Container.Resolve<TCommandHandler>(); 
    return true; 
} 

// And the usage site: 
var a = "hello"; 
Handle(a, Identify.TheType<WackyCommandHandler>()); 
Console.ReadLine(); 
+1

gracias, entiendo su punto, pero me parece que mi implementación será más clara para mí cuando la use :) – Shaddix

Cuestiones relacionadas