Results 1 to 3 of 3

Thread: [.NET 8] Dependency Injection on an N-Tier solution

Hybrid View

  1. #1

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,989

    [.NET 8] Dependency Injection on an N-Tier solution

    I am creating a solution that has an API (Microsoft.NET.Sdk.Web), domain (Microsoft.NET.Sdk), and MVC projects (Microsoft.NET.Sdk.Web).

    In my domain I have two classes that look like this:
    Code:
    public class ApplicationUserQuery
    {
    
        private readonly string _connectionString;
    
        public ApplicationUserQuery(string connectionString)
        {
            _connectionString = connectionString;
        }
    
        // ...
    }
    
    public class ApplicationUserService
    {
    
        private readonly ApplicationUserQuery _applicationUserQuery;
    
        public ApplicationUserService(ApplicationUserQuery applicationUserQuery)
        {
            _applicationUserQuery = applicationUserQuery;
        }
    
        // ...
    }
    To use the classes in my API project I am doing the following:
    Code:
    var applicationDatabaseConnectionString = builder.Configuration.GetConnectionString("ApplicationDatabase");
    if (applicationDatabaseConnectionString == null)
    {
        throw new ArgumentNullException(nameof(applicationDatabaseConnectionString));
    }
    builder.Services.AddScoped(_ => new ApplicationUserQuery(applicationDatabaseConnectionString));
    builder.Services.AddScoped<ApplicationUserService>();
    This works, but it seems like a lot of boilerplate just for two classes. Is there anyway to simplify this using the built-in .NET core stuff? I'm wanting to avoid using a 3rd party library like Ninject because of issues we recently started running into at work. This solution I'm building is a personal project.
    Last edited by dday9; Jan 22nd, 2024 at 05:28 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  2. #2

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,989

    Re: [RESOLVED] [.NET 8] Dependency Injection on an N-Tier solution

    Question resolved here: https://stackoverflow.com/questions/...ve-boilerplate

    First, I created two attributes called QueryAttribute and ServiceAttribute then added them to my respective query/service classes.

    Next, I created a new class in my API project called RegisterDependencies that looks like this:
    Code:
    public class RegisterDependencies
    {
    
        private static Assembly AssertDomainAssembly()
        {
            var domainAssembly = Assembly.GetAssembly(typeof(BaseModel));
            if (domainAssembly == null)
            {
                throw new Exception("Cannot find the domain assembly.");
            }
            return domainAssembly;
        }
    
        public static void RegisterQueries(IServiceCollection services, string connectionString)
        {
            var domainAssembly = AssertDomainAssembly();
            var queryTypes = domainAssembly
                .GetTypes()
                .Where(t => t.GetCustomAttributes(typeof(QueryAttribute), false).Length > 0);
    
            foreach (var queryType in queryTypes)
            {
                services.AddScoped(queryType, serviceProvider =>
                {
                    var newInstance = Activator.CreateInstance(queryType, new object[] { connectionString })
                        ?? throw new Exception($"Unable to create a new instance of query: {queryType.Name}");
                    return newInstance;
                });
            }
        }
    
        public static void RegisterServices(IServiceCollection services)
        {
            var domainAssembly = AssertDomainAssembly();
            var serviceTypes = domainAssembly
                .GetTypes()
                .Where(t => t.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0);
    
            foreach (var serviceType in serviceTypes)
            {
                services.AddScoped(serviceType);
            }
        }
    }
    Finally, I am calling the methods in my Program.cs:
    Code:
    var applicationDatabaseConnectionString = builder.Configuration.GetConnectionString("ApplicationDatabase");
    if (applicationDatabaseConnectionString == null)
    {
        throw new ArgumentNullException(nameof(applicationDatabaseConnectionString));
    }
    RegisterDependencies.RegisterQueries(builder.Services, applicationDatabaseConnectionString);
    RegisterDependencies.RegisterServices(builder.Services);
    Now, so long as I have the Query/Service attribute on my class it will automatically get wired up for me without having to do all the boilerplate stuff.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  3. #3

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,989

    Re: [.NET 8] Dependency Injection on an N-Tier solution

    I'm going to take off the resolved tag (for now).

    There has to be a better way to set this up. If I create a BaseQuery class that looks like this:
    Code:
    public class BaseQuery
    {
    
        protected readonly string _connectionString;
    
        public BaseQuery(string connectionString)
        {
            _connectionString = connectionString;
        }
    
    }
    Then have my ApplicationUserQuery class inherit from it, why does this fail to wire everything up:
    Code:
    builder.Services.AddScoped(services.AddScoped(typeof(BaseQuery), () => new BaseQuery(connectionString)));
    I don't understand why I would need to explicitly call AddScoped on ApplicationUserService and ApplicationUserQuery since the dependency tree would look like this:
    Code:
    └── ApplicationUserService
        └── ApplicationUserQuery
            └── BaseQuery
    Since the application knows how to build a BaseQuery it should be able to create an ApplicationUserQuery and because it know how to create an ApplicationUserQuery it should know how to create an ApplicationUserService.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width