К тому же как вы работаете с EF? создавали контекст для каждого репозитория свой?
Конечно же нет, согласно лучшим рекомендациям от Microsoft: one dbContext per web request. Однако получается, что только Singleton позволяет не создавать экземпляр во время веб-запроса. Singleton удается применить далеко не всегда и не везде,
Property Injection не пробовали? Конструктор не такой страшный и не знаю как в Ninject, но в AutoFac и Unity циклические зависимости тоже отлавливаются. Но мне больше нравиться когда все зависимости прописаны в конструкторе, напрягает только если есть наследование.
Ninject при циклической зависимости кинет исключение. Property Injection не нравится тем, что, во-первых, еще больше скрывает зависимости типа, во-вторых, создает иллюзию необязательности внедрения зависимости. Но все-таки иногда используем, например, на уровне родительского класса.
Не будет правильнее в этом случае воспользоваться фасадом и предоставить клиенту ограниченный набор методов а не сами объекты репозиториев?
У такого класса-фасада возникнет такая же проблема: несколько интерфейсов репозиториев в конструкторе класса. Однако сама по себе мысль спрятать за фасадом только нужные определенному участку бизнес-логики методы доступа к данным кажется мне очень правильной.
Знаю что можно определить свой атрибут который будет работать подобно [Inject], есть ли что то подобное для [Intercept]
Можно, но придется приложить немного усилий:
Тут код
Пишем свою PlanningStrategy:
public class CustomPlanningStrategy<TAttribute, TInterceptor> :
NinjectComponent, IPlanningStrategy
where TAttribute : Attribute
where TInterceptor : IInterceptor
{
private readonly IAdviceFactory _adviceFactory;
private readonly IAdviceRegistry _adviceRegistry;
public CustomPlanningStrategy(
IAdviceFactory adviceFactory, IAdviceRegistry adviceRegistry)
{
_adviceFactory = adviceFactory;
_adviceRegistry = adviceRegistry;
}
public void Execute(IPlan plan)
{
var methods = GetCandidateMethods(plan.Type);
foreach (var method in methods)
{
var attributes = method.GetCustomAttributes(typeof (TAttribute), true) as TAttribute[];
if (attributes != null && attributes.Length == 0)
continue;
var advice = _adviceFactory.Create(method);
advice.Callback = request => request.Kernel.Get<TInterceptor>();
_adviceRegistry.Register(advice);
if (!plan.Has<ProxyDirective>())
plan.Add(new ProxyDirective());
}
}
private static IEnumerable<MethodInfo> GetCandidateMethods(Type type)
{
var methods = type.GetMethods(
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance
);
return methods.Where(ShouldIntercept);
}
private static bool ShouldIntercept(MethodInfo methodInfo)
{
return methodInfo.DeclaringType != typeof (object) &&
!methodInfo.IsPrivate &&
!methodInfo.IsFinal;
}
}
Добавляем в kernel, указывая тип целевого атрибута и тип Interceptor:
Конечно же нет, согласно лучшим рекомендациям от Microsoft: one dbContext per web request. Однако получается, что только Singleton позволяет не создавать экземпляр во время веб-запроса. Singleton удается применить далеко не всегда и не везде,
Ninject при циклической зависимости кинет исключение. Property Injection не нравится тем, что, во-первых, еще больше скрывает зависимости типа, во-вторых, создает иллюзию необязательности внедрения зависимости. Но все-таки иногда используем, например, на уровне родительского класса.
У такого класса-фасада возникнет такая же проблема: несколько интерфейсов репозиториев в конструкторе класса. Однако сама по себе мысль спрятать за фасадом только нужные определенному участку бизнес-логики методы доступа к данным кажется мне очень правильной.
Можно, но придется приложить немного усилий:
Добавляем в kernel, указывая тип целевого атрибута и тип Interceptor:
Теперь наш атрибут не зависит от Ninject: