Мне удалось решить это с помощью дерева выражений, которое вызывает обобщенный c метод для создания фабричной функции:
public class ModularWebApiController : WebApiController
{
public Func<T> CreateFactoryMethod<T>() where T : WebApiController => () => (T)this;
}
public static class Extensions
{
public static WebApiModule WithController(this WebApiModule webApiModule, ModularWebApiController api)
{
Delegate factoryFunc = Expression
.Lambda(Expression.Call(
Expression.Constant(api),
typeof(ModularWebApiController).GetMethod("CreateFactoryMethod").MakeGenericMethod(api.GetType())
))
.Compile();
return (WebApiModule)typeof(WebApiModuleExtensions)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Single(mi => mi.IsGenericMethod & mi.Name == "WithController" && mi.GetParameters().Length == 2)
.MakeGenericMethod(api.GetType())
.Invoke(null, new object[] { webApiModule, factoryFunc.DynamicInvoke(Array.Empty<object>()) });
}
}
Мне нужно было только убедиться, что все типы контроллеров веб-API расширяют * Типа 1004 *, и мне пришлось изменить настройку модульного веб-API для EmbedIO:
Dictionary<string, ModularWebApiController> apis = ...;
foreach(KeyValuePair<string, ModularWebApiController> kvp in apis)
{
Server.WithWebApi(kvp.Key, m => m.WithController(kvp.Value));
}
После просмотра источника EmbedIO я думаю, что это единственный способ настроить модульный веб-API, где Код не знает, какие типы контроллеров веб-API будут использоваться.
Теперь я могу загрузить и скопировать любой тип контроллера веб-API, настроенный в файле конфигурации JSON, например:
[
{
"Type": "name.space.WebApiControllerTypeName",
"Path": "/webapipath/"
},
{
"Type": "name.space.AnotherWebApiControllerTypeName",
"Path": "/anotherwebapipath/"
}
]
Просто для примера. Интересно, почему кажется, что никто больше не хочет этого делать;)