2010-09-15 27 views
5

No creo que esto sea posible, pero aquí va ...genéricos C# - posible crear un método con n tipos genéricos ..?

Quiero agregar el método que puede manejar n cantidad de genéricos. por ejemplo:

bool<T> MyMethod() where T: Isomething 
{ 
} 

funcionará para un tipo

bool<T,K> MyMethod() where T: Isomething 
{ 
} 

va a trabajar para dos tipos

¿Hay una manera de trabajar con n tipos - por ejemplo,

bool<T[]> MyMethod() where T: Isomething 
{ 
} 

la razón por la que quiero hacer esto es poner en práctica un método de ayuda nhibernate estática que puede cargar desde múltiples montajes - ahora funciona muy bien para un montaje. Mi método actual es como se muestra a continuación:

 public static ISessionFactory GetMySqlSessionFactory<T>(string connectionString, bool BuildSchema) 
    { 
     //configuring is meant to be costly so just do it once for each db and store statically 
     if (!AllFactories.ContainsKey(connectionString)) 
     { 
      var configuration = 
      Fluently.Configure() 
      .Database(MySQLConfiguration.Standard 
         .ConnectionString(connectionString) 
         .ShowSql() //for development/debug only.. 
         .UseOuterJoin() 
         .QuerySubstitutions("true 1, false 0, yes 'Y', no 'N'")) 
      .Mappings(m => 
         { 
          m.FluentMappings.AddFromAssemblyOf<T>(); 
          m.AutoMappings.Add(AutoMap.AssemblyOf<T>().Conventions.Add<CascadeAll>); 
         }) 
      .ExposeConfiguration(cfg => 
           { 
            new SchemaExport(cfg) 
            .Create(BuildSchema, BuildSchema); 
           }); 
      AllFactories[connectionString] = configuration.BuildSessionFactory(); 
     } 

     return AllFactories[connectionString]; 
    } 

Donde la línea: m.FluentMappings.AddFromAssemblyOf(), quisiera añadir varios tipos, por ejemplo,

foreach(T in T[]){ 
    m.FluentMappings.AddFromAssemblyOf<T>() 

}

Obviamente, esto no podría funcionar no estoy completamente mudo, pero no estoy tan caliente en los genéricos - alguien puede confirmar que esto no es posible :-) ..? ¿Cuál sería la forma más elegante de lograr este efecto en tu opinión ...?

+1

Como señala Jon, esta no es una característica de C# o del sistema de tipo CLR. Si este tipo de sistema de tipo te interesa, considera leer en tipos de rango superior en Haskell. –

+0

@Eric - gracias - Acabo de empezar a mirar a Haskell y parece un lenguaje muy interesante. –

Respuesta

6

No - la cantidad de métodos y tipos genéricos se fija por tipo/método.

Es por eso que hay todos los diferentes tipos de Action<...>, Func<...> y Tuple<...> en el marco.

Ocasionalmente es una pena, pero se pone en el camino relativamente rara vez, y sospecho que todo tipo de cosas sería mucho más complicado con la variable arity.

+0

Gracias, esa es una respuesta, es decir, que no es posible, pero ¿tiene alguna sugerencia sobre cómo se podría hacer? ¿Hay algo con reflejo, etc. que pueda usarse para recorrer una lista de tipos y crear un genérico basado en ¿ellos? p.ej. pasando los tipos como una matriz? Casi tuve ganas de darte una marca correcta para enseñarme una nueva palabra. Ahora intentaré agregar arity en tantas oraciones como sea posible. –

+0

@Mark: sospecho que su mejor opción en este momento es simplemente sobrecargar el método. (Puede sobrecargar por arity.) Alternativamente, haga que el método devuelva algo que no sea 'bool', de modo que pueda llamarlo varias veces de manera encadenada/fluida. –

+0

gracias - configurarlo como una fluidez ni siquiera se me ocurrió - ¡esto es exactamente lo que haré! algo así como NHelper (ConnectionString) .Desde () .Desde () .Build() - ¡excelente! –

1

parece que repite el mismo error que alguna vez hizo Newton. Él tiene dos gatos, uno era más grande y el otro era más pequeño. Hizo dos agujeros en la puerta, un agujero más grande para el más grande y uno más pequeño para un gato más pequeño. Donde en realidad necesitaba un gran hoyo para ayudar al gato.

¿Por qué no crear un único método que puede hacer frente a tantos como tipos que quiera ..

bool<T[]> MyMethod() where T: Isomething 
{ 
} 
+0

Gracias, pero no estoy seguro de haber leído la pregunta correctamente. No estaba creando 3 métodos diferentes, simplemente tratando de ilustrar un punto. es decir, el tercero no es válido, pero es el tipo de cosas que necesito hacer. –

0

En realidad me he dado cuenta de este enlace - Tengo que ir a casa ahora, pero puede ser que intente algo como esto más adelante, si funciona:

http://geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx

Creo que si pasaba en una variedad de tipos y se transmitirán a través de los tipos con la reflexión que esto funcionaría.

0

Como otros han indicado que no se puede hacer:

bool MyMethod<T[]>() where T: ISomething 

pero se puede hacer:

bool MyMethod<T>(params T[] somethings) where T : ISomething 

Por ejemplo:

public interface ISomething { string Name { get; set; } } 

public class SomethingA : ISomething { public string Name { get; set; } = nameof(SomethingA); } 
public class SomethingB : ISomething { public string Name { get; set; } = nameof(SomethingB); } 

void MyMethod<T>(params T[] somethings) where T : ISomething 
{ 
    foreach (var something in somethings) 
    { 
     if (something != null) 
      Console.WriteLine(something); 
    } 
} 

// Use it! 
ISomething a = new SomethingA(); 
ISomething b = new SomethingB(); 

// You don't need to specify the type in this call since it can determine it itself. 
MyMethod(a, b); 

// If calling it like this though you do: 
MyMethod<ISomething>(new SomethingA(), new SomethingB()); 
Ventana

C# interactivo de salida:

> MyMethod(a, b); 
Submission#0+SomethingA 
Submission#0+SomethingB 
> 
> MyMethod<ISomething>(new SomethingA(), new SomethingB()); 
Submission#0+SomethingA 
Submission#0+SomethingB 

Por lo tanto, podría tomar sus tipos que desee (que se ajusten a los genéricos) y recorrerlos y llamar a su código como usted especificó. Tampoco puedes usar genéricos y solo tomar params object [] algunas cosas; pero recomiendo escribir fuertemente si puedes.

Si alguien ve esto, por favor avíseme si estoy fuera de contexto o si no entiendo bien la pregunta ... ¡Gracias!