Como retornar o valor de Action ()?

92

Com relação à resposta a esta pergunta Passing DataContext into Action () , como faço para retornar um valor de action (db)?

SimpleUsing.DoUsing(db => { 
// do whatever with db 
}); 

Deve ser mais como:

MyType myType = SimpleUsing.DoUsing<MyType>(db => { 
// do whatever with db.  query buit using db returns MyType.
}); 
4º Espaço
fonte

Respostas:

97

Seu método estático deve ir de:

public static class SimpleUsing
{
    public static void DoUsing(Action<MyDataContext> action)
    {
        using (MyDataContext db = new MyDataContext())
           action(db);
    }
}

Para:

public static class SimpleUsing
{
    public static TResult DoUsing<TResult>(Func<MyDataContext, TResult> action)
    {
        using (MyDataContext db = new MyDataContext())
           return action(db);
    }
}

Essa resposta surgiu de comentários para que eu pudesse fornecer o código. Para uma elaboração completa, consulte a resposta de @sll abaixo.

Kirk Woll
fonte
113

Você pode usar Func<T, TResult>delegado genérico. (Veja MSDN )

Func<MyType, ReturnType> func = (db) => { return new MyType(); }

Além disso, existem delegados genéricos úteis que consideram um valor de retorno:

  • Converter<TInput, TOutput>( MSDN )
  • Predicate<TInput>- sempre retorna bool ( MSDN )

Método:

public MyType SimpleUsing.DoUsing<MyType>(Func<TInput, MyType> myTypeFactory)

Delegado genérico:

Func<InputArgumentType, MyType> createInstance = db => return new MyType();

Executar:

MyType myTypeInstance = SimpleUsing.DoUsing(
                            createInstance(new InputArgumentType()));

OU explicitamente:

MyType myTypeInstance = SimpleUsing.DoUsing(db => return new MyType());
sll
fonte
Certo - você pode fornecer um exemplo de como o método deve ser?
4º Espaço de
5
@LB - pedir às pessoas que pesquisem no Google não é construtivo. O SO existe para fornecer respostas completas.
Kirk Woll
5
@KirkWoll Mas a resposta dá os ingredientes , não precisa ser cozido
LB
9
@LB - é melhor que seja completo. Acho sua analogia espúria.
Kirk Woll
1
@LB, melhor não comentar, já que você não está agregando valor algum.
4º Espaço de
15

Você também pode tirar vantagem do fato de que um método lambda ou anônimo pode fechar as variáveis ​​em seu escopo envolvente.

MyType result;

SimpleUsing.DoUsing(db => 
{
  result = db.SomeQuery(); //whatever returns the MyType result
}); 

//do something with result
Steve Rowbotham
fonte
sim, isso é chamado de Encerramento (coisas linguagem funcitonal que está disponível para nós também)
SLL
4

Use em Func<T>vez de Action<T>.

Action<T>atua como um método void com parâmetro do tipo T, enquanto Func<T>funciona como uma função sem parâmetros e que retorna um objeto do tipo T.

Se você deseja dar parâmetros à sua função, use Func<TParameter1, TParameter2, ..., TReturn>.

Ulysses Alves
fonte