2010-09-15 15 views
5

Nie sądzę, że jest to możliwe, ale tutaj jest ...C# generics - możliwe do stworzenia metody z n Rodzajami rodzajowymi ...?

Chcę dodać metodę, która może obsłużyć n liczbę generycznych. Np

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

działa dla jednego typu

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

działa na dwóch rodzajach

istnieje sposób do pracy z n typów - np

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

powodem chcę, aby to zrobić jest wdrożenie statycznego NHibernate metody pomocnika, który można załadować z wieloma zespołami - teraz działa świetnie dla jednego zespołu. Mój obecny sposób jest przedstawiony poniżej:

 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]; 
    } 

Jeżeli linia: m.FluentMappings.AddFromAssemblyOf(), to dodam wiele typów np

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

}

Oczywiście to nie może pracować nie jestem całkowicie niemy, ale nie jestem tak gorąco na generycznych - może ktoś potwierdzić, że nie jest to możliwe :-) ..? Jaki byłby najbardziej elegancki sposób osiągnięcia tego efektu w twojej opinii ..?

+1

Jak zauważa Jon, nie jest to cecha języka C# ani systemu typu CLR. Jeśli ten rodzaj systemu interesuje cię, rozważ czytanie lepszych typów w Haskell. –

+0

@Eric - dziękuję - właśnie zacząłem patrzeć na Haskella i wygląda na bardzo interesujący język. –

Odpowiedz

6

Nie - ilość ogólnych rodzajów i metod ustalana jest dla każdego rodzaju/metody.

Dlatego w strukturze występują różne typy: Action<...>, Func<...> i Tuple<...>.

Czasami jest to wstyd, ale rzadko staje się to względnie niezauważalne, i podejrzewam, że wszystkie rzeczy byłyby o wiele bardziej skomplikowane w przypadku zmiennej arii.

+0

Dzięki - to odpowiedź - tzn. Że nie jest to możliwe, ale czy masz jakieś sugestie, jak to zrobić - czy jest coś z refleksją, itp., Które można wykorzystać do przejrzenia listy typów i stworzenia generycznego na podstawie im? na przykład przekazując typy jako tablicę? Prawie poczułem, że podałem ci prawidłową ocenę, żeby nauczyć mnie nowego słowa. Teraz spróbuję zrzucić arytję na jak najwięcej zdań. –

+0

@ Mark: Podejrzewam, że w tej chwili najlepszym wyjściem jest po prostu przeciążenie metody. (Możesz przeciążyć przez arytę.) Alternatywnie, spraw, aby metoda zwróciła coś innego niż 'bool', abyś mógł wywołać ją wiele razy w łańcuchu/płynnie. –

+0

dzięki - ustawienie tego jako płynnego nawet mi nie przyszło - dokładnie to zrobię! coś jak NHelper (ConnectionString). Od () .Od () .Build() - wspaniałe! –

1

wydaje się, że powtarzasz ten sam błąd, co kiedyś zrobił Newton. Ma dwa koty, jeden był większy, a drugi był mniejszy. Wykonał dwie dziury w drzwiach, większą dziurę na większą i mniejszą dla mniejszego kota. Gdzie tak naprawdę potrzebował jednej dużej dziury, aby pomóc obu kotom.

Dlaczego nie stworzyć pojedynczą metodę, która może zajmować się tyle, ile rodzajów chcesz ..

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

Dzięki, ale nie jestem pewien, czy poprawnie przeczytałeś pytanie. Nie tworzyłem 3 różnych metod - tylko próbowałem zilustrować punkt. tj. trzeci nie jest ważny, ale jest to coś, co muszę zrobić. –

0

Jak inni określony nie można zrobić:

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

ale można zrobić:

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

Na przykład:

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()); 

C# Interactive Okno wyjściowe:

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

Możesz więc wybrać odpowiednie typy (zgodne z typem) i przechodzić między nimi, a następnie wywoływać kod, tak jak to określiłeś. Nie można również używać generycznych i po prostu wziąć obiekty params [] cos; ale zdecydowanie zalecam wpisanie go, jeśli możesz.

Jeśli ktoś to widzi, proszę dać mi znać, jeśli jestem daleko od podstawy lub źle zrozumiałem pytanie ... Dzięki!