0

i'm using in a MVC project autofac. I've another project with the core business(dll library). In this core, i want use autofac for retrieve some interface.

Now, if i'm in the MVC application i can use

DependencyResolver.Current.GetService<IMyService>();

for retrieve the service. But in the library how can I retrieve the service without pass it as property in some class declaration?

DependencyResolver is defined only in MVC project.

Is it a best practice?

user3401335
  • 2,335
  • 2
  • 19
  • 32
  • 2
    Some useful reading material: http://blog.ploeh.dk/2014/05/19/di-friendly-library/ and http://blog.ploeh.dk/2014/05/19/di-friendly-framework/ – trailmax Feb 15 '17 at 11:09
  • 1
    @trailmax: those posts are actually over reusable libraries, such as NuGet packages. This question is about libraries (or projects) within the same solution. I think more related to this question is http://blog.ploeh.dk/2011/07/28/CompositionRoot/ and this https://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-entry-application. – Steven Feb 15 '17 at 12:58

1 Answers1

2

I see following issues with your approach:

  1. DepdencyResolver is defined in System.Web.Mvc, and your BL-project should not reference that assembly.
  2. You are using the Service Locator Pattern, which is declared an Anti-Pattern.

Avoid the System.Web.Mvc-dependency in your BL-project

I found a specific Locator<T> is a practicable approach, which circumnavigates the "open to everything"- and static-issue of the Service Locator Pattern:

public interface ILocator<T> // defined in some *CORE* project
{
  T Locate();
}

public class AutofacLocator<T> : ILocator<T> // defined and injected in your *FRONTEND* project
{
  public AutofacLocator(ILifetimeScope lifetimeScope)
  {
    this.LifetimeScope = lifetimeScope;
  }

  public virtual T Locate()
  {
    var service = this.LifetimeScope.Resolve<T>();

    return service;
  }
}

This can simply be registered as an open generic:

builder.RegisterGeneric(typeof(AutofacLocator<>))
       .As(typeof(ILocator<>))
       .InstancePerDependency();

So, instead of depending on the static DependencyResolver.Current, you create your own resolver, and inject it in the BL-class' ctor:

public class SomeBusinessLogic
{
  public SomeBusinessLogic(ILocator<SomeDependency> someDependencyLocator)
  {
  }
}

Use Ctor-Injection instead of the Service Locator Pattern

Another approach would be, to simply define the dependency on a T-instance as a ctor-parameter, and let Autofac build the instance of your BL-class:

public class SomeBusinessLogic // defined in your *BL* project
{
  public SomeBusinessLogic(SomeDependency someDependency)
  {
  }
}

var someBusinessLogic = DependencyResolver.Current.GetService<SomeBusinessLogic>(); // in your *FRONTEND* project