I думаю это подпадает под концепцию контекстной привязки , но документация Ninject, хотя и очень тщательная, не имеет примеров, достаточно близких к моей текущей ситуации, чтобы я мог по-настоящемубыть уверенным.Я все еще в замешательстве.
У меня в основном есть классы, которые представляют структуры параметров для запросов.Например ..
class CurrentUser {
string Email { get; set; }
}
И затем интерфейс, который представляет его поиск в базе данных (на уровне данных)
class CurrentUserQuery : IQueryFor<CurrentUser> {
public CurrentUserQuery(ISession session) {
this.session = session;
}
public Member ExecuteQuery(CurrentUser parameters) {
var member = session.Query<Member>().Where(n => n.Email == CurrentUser.Email);
// validation logic
return member;
}
}
Теперь, что я хочу сделать, это установить простоекласс, который может взять данный объект и получить из него класс IQueryFor<T>
, создать его из моего Ninject.IKernel
(параметр конструктора) и выполнить с ним метод ExecuteQuery
, проходя через данный объект.
Единственный способ, которым я смог это сделать, - это сделать следующее ...
Bind<IQueryFor<CurrentUser>>().To<CurrentUserQuery>();
Это решает проблему для этого одного запроса.Но я ожидаю, что будет большое количество запросов ... поэтому этот метод станет не только утомительным, но и очень склонным к избыточности.
Мне было интересно, есть ли способ наследования в Ninjectвключить этот вид поведения.: -
В конце концов, мой (идеальный) способ использования этого был бы ...
class HomeController : Controller {
public HomeController(ITransit transit) {
// injection of the transit service
}
public ActionResult CurrentMember() {
var member = transit.Send(new CurrentUser{ Email = User.Identity.Name });
}
}
Очевидно, что это не будет работать правильно, так как метод Send
не имеетспособ узнать тип возвращаемого значения.
Я интенсивно анализировал Rhino Service Bus
и проект Alexandria
, чтобы попытаться сделать мою легкую, легкую и легкую реализацию.
Обновление
Мне удалось получить довольно желаемый результат, используя объекты .NET 4.0 dynamic
, такие как следующие ...
dynamic Send<T>(object message);
И затемобъявляя мой интерфейс ...
public interface IQueryFor<T,K>
{
K Execute(T message);
}
И затем его использование ...
public class TestCurrentMember
{
public string Email { get; set; }
}
public class TestCurrentMemberQuery : IConsumerFor<TestCurrentMember, Member>
{
private readonly ISession session;
public TestCurrentMemberQuery(ISession session) {
this.session = session;
}
public Member Execute(TestCurrentMember user)
{
// query the session for the current member
var member = session.Query<Member>()
.Where(n => n.Email == user.Email).SingleOrDefault();
return member;
}
}
А затем в моем контроллере ...
var member = Transit.Send<TestCurrentMemberQuery>(
new TestCurrentMember {
Email = User.Identity.Name
}
);
эффективно используя<T>
как «Эй, это то, что реализует параметры запроса!».Это работает , но я чувствую себя довольно неловко с этим.Является ли это неправильным использованием функции dynamic
.NET 4.0?Или это еще одна причина, по которой он вообще существует?
Обновление (2)
Ради последовательности и сохранения этого поста относительно первоначального вопроса, который я открываюдругой вопрос для динамического вопроса.