Доступ к методу, который был назначен переданному параметру Func <> - PullRequest
1 голос
/ 17 января 2012

Похоже, я упустил что-то очевидное, но на самом деле не могу понять, почему я не могу использовать / получить доступ к методу, который был назначен переданному параметру Func<>, я хочу получить доступ / вызвать его во внешнемвызывающий контекст.

Ниже приведен простой пример: (реальный results тип данных не string, а некоторый сложный тип)

class Caller
{
    private Func<string> factory;

    public Caller()
    {
        this.factory = null;
        var adapter = new Adapter(this.factory);
        adapter.Adapt(...);

        // then I would share this factory via IoC
        dependencyContainer.RegisterUsingFactoryMethod<string>(this.factory);

        // !!! but here is factory still not assigned
        string results = this.factory();
    }
}

class Adapter
{
    private string results;

    public Adapter(Func<string> factory)
    {
        factory = () => this.results;
    }

    public IOut Adapt(IIn input)
    {
       this.results = someCalculatedData;
    }
}

Ответы [ 4 ]

4 голосов
/ 17 января 2012

Это не имеет ничего общего с делегатами, и все, что связано с тем, что по умолчанию все аргументы передаются по значению. Вы бы видели такое же поведение, если бы factory было int, или string, или StringBuilder.

Если вы хотите, чтобы ваш конструктор Service изменил значение аргумента, вам нужен параметр ref или out. Однако я бы лично предложил вам изменить его на метод, который возвращает a Func<string>:

public class Caller
{
    private readonly Func<string> factory;

    public Caller()
    {
        this.factory = Service.GetFunc();
    }
}

public class Service
{
    public static Func<string> GetFunc()
    {
        return () => Guid.NewGuid().ToString();
    }
}

(Здесь есть и другие варианты, такие как преобразование группы методов или свойство. Трудно понять, что порекомендовать, когда у нас мало контекста.)

Очевидно, вы захотите переименовать метод. Но вызов конструктора исключительно для изменения параметра out был бы очень странным кусочком кода.

Подробнее о передаче параметров см. Мою статью на тему .

3 голосов
/ 17 января 2012

Можете ли вы попробовать вставить функцию с параметром out в конструктор Service?

например,

class Caller
{
    private Func<string> factory;

    public Caller()
    {
        this.factory = null;
        var service = new Service(out this.factory);

        // !!! but here is factory still not assigned
        string results = this.factory();
    }
}

class Service
{
    public Service(out Func<string> factory)
    {
        factory = () => Guid.NewGuid().ToString();
    }
}

Это позволит компилятору знать, как инициализировать ссылку на фабричный параметр в конструкторе Service.В противном случае вы просто передаете ссылку на нулевой Func конструктору по значению, а затем локально присваиваете функцию этой переменной в стеке внутри ctor.

См. этот связанный вопрос для ясности параметров ref и out.

С уважением,

2 голосов
/ 17 января 2012

Вы никогда не назначаете на заводе в Callee,

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

Я не уверен, можете ли вы передать параметры в конструктор по ссылке или нет ...

0 голосов
/ 17 января 2012

Чтобы вызвать ссылку Func<T...>, вам нужно просто вызвать, как если бы это был обычный метод.т.е.:

class Service
{
    public Service(Func<string> factory)
    {
        string result = factory();
    }
}

Обратите внимание, что Func<string> вернет тип string.

РЕДАКТИРОВАТЬ

Из вашего комментария я понял, чтовы на самом деле спрашивали в ОП.Чтобы иметь возможность присвоить значение любому параметру, вам необходимо пометить его как out или ref.Таким образом, ваша декларация будет выглядеть так:

public Service(out Func<string> factory)

или

public Service(ref Func<string> factory)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...