Разрешение обобщений с интерфейсом в качестве параметра типа в Autofac - PullRequest
2 голосов
/ 27 декабря 2011

После прочтения тонны документации и вопросов отсюда я все еще застрял в следующем.Это интерфейсы / реализации, зарегистрированные в Autofac:

public interface ITestService<T>
{
}

public class TestService<T> : ITestService<T>
{
}

public interface ITest<TService, T>
    where TService : ITestService<T>
{
}

public class Test<TService, T> : ITest<TService, T>
    where TService : ITestService<T>
{
}

Регистрация выглядит следующим образом, где builder является экземпляром ContainerBuilder и обновляет центральный IComponentRegistry:

builder.RegisterGeneric(typeof(TestService<>)).As(typeof(ITestService<>)).InstancePerLifetimeScope();

builder.RegisterGeneric(typeof(Test<,>)).As(typeof(ITest<,>)).InstancePerLifetimeScope();

Теперь это работает (где _componentContext - это экземпляр IComponentContext):

_componentContext.Resolve<ITest<TestService<MyType>, MyType>>();

Это не (исключение ComponentNotRegisteredException):

_componentContext.Resolve<ITest<ITestService<TNodeToNodeConnectorRecord>, TNodeToNodeConnectorRecord>>();

Любые советыо том, как разрешение может работать, не зная реализацию ITestService?Поскольку

_componentContext.Resolve<ITestService<MyType>>();

работает должным образом, использование его типа может использоваться каким-либо образом, но мне это не удалось.

Обновление, подробности об исключении: Выдается исключение какследующее:

"The requested service 'MyProject.ITest`2[[MyProject.ITestService`1[[MyProject.MyType, MyProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]], MyProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[MyProject.MyType, MyProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered."

Трассировка стека:

   at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Service service, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.Resolve(IComponentContext context, Type serviceType, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.Resolve[TService](IComponentContext context)
   at MyProject.SomeController`4.Execute(RequestContext requestContext) in d:\SomeController.cs:line 55
   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
   at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
   at Orchard.Mvc.Routes.ShellRoute.HttpAsyncHandler.EndProcessRequest(IAsyncResult result) in D:\MyProject.SomeRoutes.cs:line 148
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Код, выполняющий вызовы разрешения, фактически находится в методе Execute () контроллера ASP.NET MVC.

Любая помощь будет принята с благодарностью!

1 Ответ

2 голосов
/ 27 декабря 2011

К сожалению, в вашей версии Autofac есть ошибка: Общие параметры ограничены, поскольку общие интерфейсы не могут быть разрешены. .

Исправлено, предположительно в 2.5.1. Вам придется обновить, чтобы использовать эту функцию.

Или вы можете попробовать обходной путь:

public interface ITestService<T>
{
}

public class TestService<T> : ITestService<T>
{
}

public interface ITest<T>
{
  ITestService<T> TestService { get; }
}

public class Test<T> : ITest<T>
{
  readonly ITestService<T> _TestService;

  public Test(ITestService<T> testService)
  {
    _TestService = testService;
  }

  public ITestService<T>
  {
    get
    {
      return this._TestService;
    }
  }
}

builder.RegisterGeneric(typeof(TestService<>)).As(typeof(ITestService<>)).InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(Test<>)).As(typeof(ITest<>)).InstancePerLifetimeScope();
...

_componentContext.Resolve<ITest<TNodeToNodeConnectorRecord>>();

// if you need to specify the ITestService type to use:
var testService = _componentContext.Resolve<TestService<TNodeToNodeConnectorRecord>>();
var test = _componentContext.Resolve<Func<ITestService<TNodeToNodeConnectorRecord>, ITest<TNodeToNodeConnectorRecord>>>()(testService);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...