0

Я меня были пойти на это некоторое время не повезло :(Использование Autofac Реализовано с IDependencyResolver в MVC5

Где я застревания:

У меня есть веб-приложение MVC5 и Я использую Autofac для контейнера IoC под капотом. В основном у меня есть зависимость, которая требует от меня передать параметр через конструктор , но поскольку я разрешаю Autofac через интерфейс IDependencyResolver, мне не разрешено для вставки параметры непосредственно.

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

//////////////// 
//My Interface// 
//////////////// 

public interface IConfiguration 
{ 
    string OwnerId { get; set; } 
    IDictionary<string, string> GetAllSettings(); 
    string GetSettingByKey(string SettingsKey); 
} 

/////////////////// 
//My Concrete Obj// 
/////////////////// 

public class Configuration : IConfiguration 
{ 
    public delegate Configuration Factory(string ownerId); //Added this based on what's on the Autofac Wiki - Delegate Factories 

    public string OwnerId { get; set; } 
    public Dictionary<string, string> AllSettings {get; set;} 

    public Configuration(string ownerId) { 
     //Some logic that requires ownerId 
    } 

    public IDictionary<string, string> GetAllSettings() 
    { 
     //Some other logic irrelevant for now 
    } 

    public string GetSettingByKey(string settingsKey) 
    { 
     //Some other logic irrelevant for now 
    } 
} 

/////////////////////////////////// 
//Registering Dependencies in MVC// 
/////////////////////////////////// 

var builder = new ContainerBuilder(); 
builder.RegisterType<Configuration>().As<IConfiguration>(); 

//Some other configuration 

var container = builder.Build(); 

//Set Dependency Resolver for MVC5 
DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 

////////////////////////////////////////////////////////// 
//Somewhere in my MVC App where I require IConfiguration// 
////////////////////////////////////////////////////////// 

var ownerId = GetOwnerId(); 

//Where I require Help 

var config = DependencyResolver.Current.GetService<IConfiguration>(); //How do I pass in a parameter (ownerId) to my underlying autofac container? 

//I Tried this but it didn't work 
var configFactory = DependencyResolver.Current.GetService<Func<string,IConfiguration>>(); 
var config = configFactory.Invoke(ownerId); 

YSOD Я получаю идет о так

ни один из конструкторов, найденных с «Autofac.Core.Activators.Reflection.DefaultConstructorFinder» на «» Common.Configuration типа не могут использоваться с имеющимися услугами и параметрами: не удается разрешить параметр «System.String OwnerId» конструктора 'Void .ctor (System.String)'.

Заранее спасибо ребята :)

+0

Мне нужно поместить Баунти на этот Do парни :)? –

+0

Что такое 'ownerId'? Это что-то, что изменяется в зависимости от условий выполнения (например, входящего запроса или сеанса пользователя) или это то, что исправлено в течение всего срока службы вашего приложения (например, потому что оно настроено в файле конфигурации)? – Steven

+0

Привет, Стивен, спасибо за вопрос да, что-то, что определено во время выполнения :) Я не могу разместить его в конфиге, пока он еще не известен ... –

ответ

1

Я думаю, что вы, наверное, видели эту ссылку: DependencyResolver: Pass parameters

Одно из предложений, которые могут решить проблему в данном конкретном случае, это сделать бросок обратно AutofacDependencyResolver и позвонить родным метод из ApplicationContainer, что-то вроде этого (я не знаю, если синтаксис правильно):

var rawContainer = (AutofacDependencyResolver)DependencyResolver.Current; 
     rawContainer.ApplicationContainer.Resolve<IConfiguration>(new[] { ownerId }); 

Я не Асесс к коду прямо сейчас, но я видел в компании, что я работаю для Extensi о методе, чтобы IDependencyResolver обернуть этот код выше, что-то вроде этого:

public static class AutofacHelper 
{ 
    public static T Resolve<T>(this IDependencyResolver container, Parameter[] paramsCtor = null) 
    { 
     var rawContainer = (AutofacDependencyResolver) DependencyResolver.Current; 
     return rawContainer.ApplicationContainer.Resolve<T>((IEnumerable<Parameter>) paramsCtor); 
    } 
} 

, а затем вы можете назвать это обычно через DependencyResolver.Current

+0

Вы можете использовать 'AutofacDependencyResolver.Current', чтобы избежать кастинга. –

+0

Спасибо, ребята, дайте ему взломать, правда, что я никогда не думал о том, чтобы отбросить его/или не сказать, что Трэвис заподозрил ... Я дал ему шанс, и пусть у ребят понимают ура ... –

+0

Да, это действительно сообщение, которое я видел, когда я пытался придумать решение ... @Peter Lillevold может все еще помочь мне? –

1

Волнения вызваны, потому что вы смешиваете данные во время выполнения с поведением. Вы не должны вводить данные времени выполнения (ваши ownerId - данные времени исполнения) в компоненты вашего приложения. Ваши компоненты приложения должны зависеть только от других компонентов. Смешивая всевозможные неприятности. Например, это значительно упрощает проверку объектного графика.

Таким образом, вместо того, чтобы вводить данные времени выполнения в конструктор, введите службу, которая позволяет получить это значение времени выполнения после построения графика объекта. В вашем случае я мог бы представить себе существование IOwnerContext абстракции:

public interface IOwnerContext 
{ 
    string CurrentOwnerId { get; } 
} 

Как это владелец идентификатор извлекается будет зависеть от приложения, которое вы используете. Например, можно предположить, что у вас есть фоновая служба, которая работает поверх бизнес-логики, которая имеет реализацию IOwnerContext, которая возвращает значение на основе какого-либо обрабатываемого сообщения или на основе некоторого значения конфигурации.

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

public class AspNetOwnerContext : IOwnerContext 
{ 
    public string CurrentOwnerId 
    { 
     get 
     { 
      string host = HttpContext.Current.Request.Url.Host; 
      int index = host.IndexOf("."); 
      string subdomain = host.Substring(0, index); 
      return subdomain; 
     } 
    } 
} 
+0

Хе-хе У меня на самом деле есть интерфейс, который я просто решил не вставлять (я вырезал код, поместив этот var ownerId = GetOwerId();), потому что я думал, что буду раздувать пример (для реальной проблемы, которую я пытался решить), что это хорошо, что вы упомянули об этом, но заставляете меня чувствовать правильный путь мой интерфейс называется IConfigOwner, и у него есть только одна цель для GetOwnerId() :) Мне нравится, как вы упомянули, не смешивая данные времени выполнения с поведением. Я делаю именно то, что вы упомянули; конкретный класс, реализующий этот интерфейс ... любые идеи по моей конкретной проблеме? –

+0

@EgliBecerra: вы должны ввести «IConfigOwner» в класс «Конфигурация», и это должно решить ваши проблемы. – Steven

Смежные вопросы