2011-07-25 12 views
5

Obecnie refactoruję istniejący DAL, który ma fasadę wywoływaną przez użytkownika i wewnętrzną klasę, która wykonuje rzeczywistą pracę zależną od dostawcy ADO.Net, aby użyć np. SqlProvider, a ja staram się zapewnić, że kod jest sucha, zrobiłem ok stosując Func więc mogę zrobić:C# delegat ogólny z parametrem out - zdefiniuj i wywołaj

return RunCommand(c => c.ExecuteNonQuery(commandText, parameters)); 

A metoda RunCommand wygląda następująco:

private T RunCommand<T>(Func<Commands, T> toRun) 
    { 
     return toRun(CreateCommand()); 
    } 

The CreateCommand() Metoda po prostu buduje obiekt polecenia do użycia, to pozwala mi mieć jedną metodę, która obsługuje wszystkie wywołania, które właśnie zwracają oczekiwany typ, np. DataSet, DataReader itp

Problemem jest to, że mam kilka wzywa elewacji dostarczyć parametr out wiem, powinien być w stanie usunąć powtarzające się kod, jeśli mogę użyć delegata ale po wielu googlowania & eksperymentowania mam nie udało się wypracować sposobu. Kod jest:

Commands commands = CreateCommand(); 
return commands.ExecuteNonQuery(out cmd, commandText, parameters); 

Co naprawdę chciałbym zrobić, to móc zadzwonić:

return RunCommand(c => c.ExecuteNonQuery(out cmd, commandText, parameters)); 

Widziałem this istniejące pytanie, ale dla życia mnie nie mogę dowiedzieć się, jak aby zmienić to w to, czego potrzebuję.

Ten delegat wydaje się być to, czego potrzebuję private delegate V TestOutParameter<T, U, V>(T a, out U b, V c); ale kod mam dla nazywając go po prostu nie ma rację:

private V RunCommand<T, U, V>(TestOutParameter<Commands, DbCommand, V> commandToExecute) 
    { 
     DbCommand cmd; 
     return (V)commandToExecute(CreateCommand(), out cmd); 
    } 

Czy ktoś może mi pomóc jak zostało to doprowadza mnie do szaleństwa dla tydzień!

Odpowiedz

11

Twój delegat ma trzy parametry zamiast dwóch. Zakładając, że chcesz to lustro Func zamiast:

private delegate V TestOutParameter<T, U, V>(T a, out U b, V c); 

powinny mieć:

private delegate V TestOutParameter<T, U, V>(T a, out U b); 

ja osobiście polecam ją zmienić na coś w stylu:

private delegate TResult FuncOut<T1, T2, TResult>(T1 arg1, out T2 arg2) 
+0

To delegat czyni mistrza zmysł, który jest świetny. Ciągle jednak drapię się w głowę, jak to nazwać. T1 jest klasą, której potrzebuję wywołać aktualną metodę i która ma parametr out. TBH Nie wiem, jak to nazwać. – Nathan

+0

@Nathan: Zmiana typu delegata powinna sprawić, że twój kod 'RunCommand' po prostu się skompiluje bez problemu, o ile metoda' CreateCommand' zwróci 'Polecenia'. –

+0

Zobacz, na czym polegam dalej :) Kod 'RunCommand' jest szczęśliwy, ale kiedy próbuję użyć' return RunCommand (c => c.ExecuteNonQuery (out cmd, commandText, parametry)); 'Powiedziano mi przez VS, który "nie może używać parametrów ref lub out". Chyba nie używam poprawnej składni do wywoływania metody? – Nathan