Adaptive Code via C#: Agile coding with design patterns and SOLID principles (Developer Reference)

Category: Programming
Author: Gary McLean Hall
4.6
This Year Stack Overflow 3
This Month Stack Overflow 1

Comments

by anonymous   2018-03-19

As you already know, example #2 is Service Locator Pattern. Many of us used it in ASP.Net Web Form in good old days - we didn't know any better back then.

However, better alternatives exists for ASP.Net MVC such as Constructor Injection - a default goal for DI - example #1.

Service Locator has few problems. One of them is it doesn't follow Don't call us, we'll call you principle. Instead, we directly ask for the things we need rather than handed them to us.

With the service locator, we have to examine the code, searching for capricious calls that retrieve a required service. Constructor injection allowed us to view dependencies—all of them—with a glance at the constructor, or at a distance, via IntelliSense.

Source: Dependency Injection in .NET by Mark Seemann and Adaptive Code via C# by Gary McLean Hall

by anonymous   2017-08-20

I think this accomplishes some OOP goal such as Separating Concerns and the Single Responsibility Principle.

The result is opposite. Now, PropertyManager tightly couples to PropertyRepo; previously, they were loosely coupled.

First approach is better than the latter one. However, PropertyManager and UserManager should not create other objects on which they rely to do their work. The responsibility for creating and managing object should be offloaded to IoC container.

Interfaces describe what can be done, whereas classes describe how it is done. Only classes involve the implementation details—interfaces are completely unaware of how something is accomplished. Because only classes have constructors, it follows that constructors are an implementation detail. An interesting corollary to this is that, aside from a few exceptions, you can consider an appearance of the new keyword to be a code smell. - Gary McLean Hall

Answer for Updated Question:

In your updated question, you combine Service/Manager and somewhat Domain into a single class - PropertyManager, UserManager. It becomes personal preference.

I personally like to keep them separate. In addition, I like to use Role based and Claim based authorization. Let me use my GitHub sample project as a reference. Please feel free to clone it.

User Domain

User class is also used by Entity Framework Code First Fluent API.

public partial class User
{
   public int Id { get; set; }
   public string UserName { get; set; }
   public string FirstName { get; set; }
}

User Service

public class UserService : IUserService
{
   private readonly IRepository<User> _repository;

   public UserService(IRepository<User> repository)
   {
      _repository = repository;
   }

   public async Task<IPagedList<User>> GetUsersAsync(UserPagedDataRequest request)
   {
   ...
   }
}

Action Method

Notice that UI related Business Logic stays at UI layer.

public async Task<ActionResult> Login(LoginModel model, string returnUrl)
{
   if (ModelState.IsValid)
   {
      bool result = _activeDirectoryService.ValidateCredentials(
         model.Domain, model.UserName, model.Password);
      if (result)
      {
          ...
      }
   }
   ...
}
by anonymous   2017-08-20

On the last part of the article (The UI), the startup file is accessing the repo. Is this logical? If so why?

I believe you are referring the following code -

services.AddDbContext<ApplicationContext>(options => 
  options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
services.AddTransient<IUserService, UserService>();
services.AddTransient<IUserProfileService, UserProfileService>();

It is normal for UI Project to reference other projects, and register dependencies in IoC container, because Composition Root should be placed as close to the application's entry point as possible.

var userService = new UserService();

If you instantiate UserService using new keyword in UI, they become tightly coupled - a change in one class forces a change in another.

IoC container solves the dependencies issue by resolving dependencies at runtime and pass them as needed.

If you want to know more about DI, you might want to read Dependency Injection in .NET by Mark Seemann and Adaptive Code via C# by Gary McLean Hall