Я на самом деле решил именно эту проблему и построил структуру вокруг нее. Я использовал параметры Autofac для передачи существующих представлений в вызов разрешения докладчика.
Сначала я определил пользовательский интерфейс разрешения, полученный из Autofac:
public interface IMvpContext : IContext
{
T View<T>();
}
, что позволило мне зарегистрировать докладчика, который разрешает представление:
builder.RegisterPresenter(c => new FooPresenter(
c.View<IFooView>(),
c.Resolve<IFooService>()));
с использованием метода расширения, который оборачивает IContext
Autofac в реализацию IMvpContext
:
public static IConcreteRegistrar RegisterPresenter<T>(
this ContainerBuilder builder,
Func<IMvpContext, T> creator)
{
return builder
.Register((context, parameters) => creator(new MvpContext(context, parameters)))
.FactoryScoped();
}
Я определил тип параметра, представляющий параметр представления:
public class MvpViewParameter : NamedParameter
{
public static readonly string ParameterName = typeof(MvpViewParameter).AssemblyQualifiedName;
public MvpViewParameter(object view) : base(ParameterName, view)
{}
}
В качестве имени параметра используется собственное имя типа, уточненное сборкой. Это имеет очень низкую вероятность конфликта с законными параметрами.
MvpContext
передает все вызовы стандартного разрешения в базовый контекст. Для представления он разрешает параметр с известным именем:
public sealed class MvpContext : IMvpContext
{
private IContext _context;
private IEnumerable<Parameter> _resolutionParameters;
public MvpContext(IContext context, IEnumerable<Parameter> resolutionParameters)
{
_context = context;
_resolutionParameters = resolutionParameters;
}
#region IContext
// Pass through all calls to _context
#endregion
#region IMvpContext
public T View<T>()
{
return _resolutionParameters.Named<T>(MvpViewParameter.ParameterName);
}
#endregion
}
Вызов для разрешения докладчика предоставляет параметр просмотра:
public partial class Foo : Page, IFooView
{
private readonly FooPresenter presenter;
public Foo()
{
this.presenter = IoCResolve<IFooPresenter>(new MvpViewParameter(this));
}
}