Фактично можливо повернути анонімний тип із методу в конкретному випадку використання. Давай подивимось!
За допомогою C # 7 можна повернути анонімні типи з методу, хоча це має незначне обмеження. Ми будемо використовувати нову мовну функцію під назвою локальна функція разом з непрямим фокусом (інший шар непрямості може вирішити будь-яку проблему програмування, правда?).
Ось випадок використання, який я нещодавно визначив. Я хочу записати всі значення конфігурації після того, як я їх завантажив AppSettings
. Чому? Оскільки існує якась логіка навколо відсутніх значень, які повертаються до значень за замовчуванням, деякі розбору тощо. Найпростіший спосіб реєстрації значень після застосування логіки - це розмістити їх у класі та серіалізувати їх у лог-файл (за допомогою log4net). Я також хочу прокласти складну логіку роботи з налаштуваннями і відокремити цю програму від того, що мені потрібно робити. Все без створення названого класу, який існує лише для одного використання!
Подивимося, як вирішити це за допомогою локальної функції, яка створює анонімний тип.
public static HttpClient CreateHttpClient()
{
// I deal with configuration values in this slightly convoluted way.
// The benefit is encapsulation of logic and we do not need to
// create a class, as we can use an anonymous class.
// The result resembles an expression statement that
// returns a value (similar to expressions in F#)
var config = Invoke(() =>
{
// slightly complex logic with default value
// in case of missing configuration value
// (this is what I want to encapsulate)
int? acquireTokenTimeoutSeconds = null;
if (int.TryParse(ConfigurationManager.AppSettings["AcquireTokenTimeoutSeconds"], out int i))
{
acquireTokenTimeoutSeconds = i;
}
// more complex logic surrounding configuration values ...
// construct the aggregate configuration class as an anonymous type!
var c = new
{
AcquireTokenTimeoutSeconds =
acquireTokenTimeoutSeconds ?? DefaultAcquireTokenTimeoutSeconds,
// ... more properties
};
// log the whole object for monitoring purposes
// (this is also a reason I want encapsulation)
Log.InfoFormat("Config={0}", c);
return c;
});
// use this configuration in any way necessary...
// the rest of the method concerns only the factory,
// i.e. creating the HttpClient with whatever configuration
// in my case this:
return new HttpClient(...);
// local function that enables the above expression
T Invoke<T>(Func<T> func) => func.Invoke();
}
Мені вдалося створити анонімний клас, а також уклав логіку роботи зі складним управлінням налаштуваннями, всередині CreateHttpClient
і всередині власного "вираження". Це може бути не саме те, чого хотіла ОП, але це легкий підхід з анонімними типами, який наразі можливий у сучасному C #.