Compact Framework Func <T>выпуски - PullRequest
0 голосов
/ 16 июня 2011

Я пытаюсь сделать какую-то работу над процессом backgroundworker, и пока работа сделана, я хочу отобразить модальное диалоговое окно. У меня есть код, хорошо работающий для простого делегата Action, но я хочу иметь возможность передать делегат Func и получить возвращаемый тип. То, что у меня есть, это форма с методом

    public void ShowDialogWhile(Action work)
    {
        _work = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();
    }

То, что я хотел бы получить дальше, это что-то вроде

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }

Пока что мне не повезло, потому что я продолжаю падать, когда объявляю тип моего _workWithReturn

        Func<TResult> _workWithReturn;

У кого-нибудь есть мысли?

Вот полный код.

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    BackgroundWorker _worker = new BackgroundWorker();
    Action _work;
    Func<TResult> _workWithReturn;
    public object Result { get; private set; }


    public AsyncWaitDialog()
    {
        InitializeComponent();
        _worker.DoWork += HandleDoWorkEvent;
        _worker.RunWorkerCompleted += HandleWorkerCompleted;
    }


    public void ShowDialogWhile(Action work)
    {
        _work = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();
    }

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }


    private void HandleDoWorkEvent(object sender, EventArgs e)
    {
        try
        {
            if (_work != null)
            {
                _work();
            }
            if (_workWithReturn != null)
            {
                Result = _workWithReturn();
            }

        }
        catch (Exception)
        {
            this.Close();
            throw;
        }
    }

    private void HandleWorkerCompleted(object sender, EventArgs e)
    {
        this.Close();
    }

}

Ответы [ 3 ]

2 голосов
/ 17 июня 2011

Ошибки, которые вы получаете при компиляции, связаны не с Compact Framework, а скорее с неправильным использованием Generics. Как уже говорили другие, тип TResult находится вне области вашего класса, если вы не объявите его в самом классе.

Если бы я посмотрел на то, что вы пытаетесь достичь, я бы сказал, что вы можете получить то, что вы хотите, сохранив все типы, специфичные для метода. Внесите изменения следующим образом:

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    ...
    //Func<TResult> _workWithReturn; REMOVE THIS LINE
    ...

    //Change your function to be this:
    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        var result = default(TResult);
        _work = () =>
        {
            result = work();
        };
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return result;
    }
}

Ваша «работа» теперь выполняется анонимным делегатом, который вызывает вашу функцию, и возврат функции удерживается в рамках функции ShowDialogWhile. Хороший и легкий трюк.

Чтобы добавить рефакторинг, вы можете использовать существующий метод для обработки логики работника и диалога:

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        var result = default(TResult);
        ShowDialogWhile(() =>
        {
            result = work();
        });
        return result;
    }
1 голос
/ 16 июня 2011

Ваша проблема в том, что TResult является универсальным, определенным в методе ShowDialogWhile, но вы объявили свой _workWithReturn вне этой области.Одним из исправлений было бы иметь TResult как часть объявления класса.

1 голос
/ 16 июня 2011

У вас есть универсальный метод с TResult, но у вас также есть поле, использующее тип.Переместите универсальное определение из метода в класс, если вам нужно поле этого типа во время выполнения.

public partial class AsyncWaitDialog : Form, IAsyncDialog
{
    ...
    Func<TResult> _workWithReturn; //TRESULT IS NOT IN SCOPE
    ...

    public TResult ShowDialogWhile<TResult>(Func<TResult> work)
    {
        //TResult **IS** in scope here
        _workWithReturn = work;
        _worker.RunWorkerAsync();
        this.CenterForm();
        this.ShowDialog();

        return (TResult)Result;
    }


// possible solution, move the generic definition of TResult to the class definition

public partial class AsyncWaitDialog<TResult> : Form, IAsyncDialog { ... }
...