I created this simple WebAPI project containing the following library class
Basically WebAPI project calls(reference) Dtos, and Coordination. Coordination Calls Domain and Domain call Data.
This is what my structure look like.
My issues is implementing Dependency Injection using Autofac. I can call the Coordination layer, when i try to call the domain layer this is where it get confused.
This is how I defined my registertype
public class AutofacWebapiConfig
{
public static IContainer Container;
public static void Initialize(HttpConfiguration config)
{
Initialize(config, RegisterServices(new ContainerBuilder()));
}
public static void Initialize(HttpConfiguration config, IContainer container)
{
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
private static IContainer RegisterServices(ContainerBuilder builder)
{
//Register your Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyTypes(Assembly.Load(nameof(Coordination)))
.Where(t => t.Namespace.Contains("Services"))
.As(t => t.GetInterfaces().FirstOrDefault(i => i.Name == "I" + t.Name));
builder.RegisterAssemblyTypes(Assembly.Load(nameof(Domain)))
.Where(j => j.Namespace.Contains("Domain"))
.As(j => j.GetInterfaces().FirstOrDefault(i => i.Name == "I" + j.Name));
//Set the dependency resolver to be Autofac.
Container = builder.Build();
return Container;
}
}
Nothing that jumps out of me from the service implementation
public class StudentService : IStudentService
{
private readonly IStudentDomain studentDomain;
public StudentService(IStudentDomain _studentDomain)
{
this.studentDomain = _studentDomain;
}
public async Task<StudentDto> GetStudentByID(string id)
{
var test = this.studentDomain.getStudentByID(id);
}
}
And here is my domain implementation
public class StudentDomain : IStudentDomain
{
public StudentDomain()
{
}
/// <summary>
/// Return student
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
StudentEntity IStudentDomain.getStudentByID(string id)
{
StudentEntity student = new StudentEntity("dd", "aa", "ddd");
return student;
}
}
This is the error I keep getting
I am sorry my os is french, but its just mean the value is null. Full stack error
System.ArgumentNullException
HResult=0x80004003
Message=La valeur ne peut pas être null.
Nom du paramètre : serviceType
Source=Autofac
StackTrace:
at Autofac.Core.TypedService..ctor(Type serviceType)
at Autofac.RegistrationExtensions.<>c__DisplayClass14_0`3.<As>b__0(Type t)
at Autofac.RegistrationExtensions.<>c__DisplayClass13_0`3.<As>b__0(Type t)
at Autofac.Features.Scanning.ScanningRegistrationExtensions.<>c__DisplayClass8_0`3.<As>b__0(Type t, IRegistrationBuilder`3 rb)
at Autofac.Features.Scanning.ScanningRegistrationExtensions.ScanTypes(IEnumerable`1 types, IComponentRegistryBuilder cr, IRegistrationBuilder`3 rb)
at Autofac.Features.Scanning.ScanningRegistrationExtensions.ScanAssemblies(IEnumerable`1 assemblies, IComponentRegistryBuilder cr, IRegistrationBuilder`3 rb)
at Autofac.Features.Scanning.ScanningRegistrationExtensions.<>c__DisplayClass0_0.<RegisterAssemblyTypes>b__0(IComponentRegistryBuilder cr)
at Autofac.ContainerBuilder.Build(IComponentRegistryBuilder componentRegistry, Boolean excludeDefaultModules)
at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
at CB.WebAPI.App_Start.AutofacWebapiConfig.RegisterServices(ContainerBuilder builder) in C:\source\repos\CB.WebAPI\CB.WebAPI\App_Start\AutofacWebapiConfig.cs:line 43
at CB.WebAPI.App_Start.AutofacWebapiConfig.Initialize(HttpConfiguration config) in C:\source\repos\CB.WebAPI\CB.WebAPI\App_Start\AutofacWebapiConfig.cs:line 21
at CB.WebAPI.App_Start.Bootstrapper.Run() in C:\source\repos\CB.WebAPI\CB.WebAPI\App_Start\Bootstrapper.cs:line 14
at CB.WebAPI.WebApiApplication.Application_Start() in C:\source\repos\CB.WebAPI\CB.WebAPI\Global.asax.cs:line 18
Here I am adding the global.asax.cs file. Line 18 is my bootstrapper.run();
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
Bootstrapper.Run();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
It seems that there is an issue with registering Domain
because StudentEntity
does not have corresponding interface and .As(j => j.GetInterfaces().FirstOrDefault(i => i.Name == "I" + j.Name))
will fail to find one for it.
If you don't want to manually add all types with interfaces try this:
builder.RegisterAssemblyTypes(typeof(StudentDomain).Assembly)
.Where(j => j.Namespace.Contains("Domain"))
.AsImplementedInterfaces()
Possibly you will want/need to distinguish between types with interfaces and without them, you can try next approach:
builder.RegisterAssemblyTypes(typeof(StudentDomain).Assembly)
.Where(j => j.Namespace.Contains("Domain") && j.GetInterfaces().Any())
.AsImplementedInterfaces()
builder.RegisterAssemblyTypes(typeof(StudentDomain).Assembly)
.Where(j => j.Namespace.Contains("Domain") && !j.GetInterfaces().Any())
.AsSelf();
P.S.
Also I would recommend to change all Assembly.Load(nameof(SOME_NAME))
to typeof(TYPE_NAME).Assembly
, I think it is more readable and obvious.
User contributions licensed under CC BY-SA 3.0