← Back to Articles         
Real-Time OOP Scenarios in ASP.NET Core

Real-Time OOP Scenarios in ASP.NET Core

Published on 12 Oct 2026     14 min read OOPs
Real-Time OOP Scenarios in ASP.NET Core

Focus: Practical implementation, Clean Architecture, SOLID principles, Dependency Injection, and real-world scenarios.

1. 🔴 How do you apply the four OOP pillars in an ASP.NET Core Web API application?

The four OOP pillars are Encapsulation, Abstraction, Inheritance, and Polymorphism.

OOP Pillar

ASP.NET Core Example

Encapsulation

Protect business data using private fields and public methods

Abstraction

Define service contracts using interfaces

Inheritance

Create common functionality in base classes

Polymorphism

Implement different behaviors using the same interface

Real-world example: Banking Application

  • Encapsulation: BankAccount controls deposits and withdrawals.

  • Abstraction: IAccountService defines account operations.

  • Inheritance: SavingsAccount inherits from BankAccount.

  • Polymorphism: Savings and Current accounts calculate interest differently.

Interview Key Point: OOP helps build maintainable, reusable, loosely coupled, and testable Web API applications.

 

2. 🔴 How do interfaces and Dependency Injection work together in ASP.NET Core?

An interface defines a contract, while Dependency Injection (DI) supplies the implementation at runtime.

Example:

public interface IUserService
{
    string GetUser();
}

public class UserService : IUserService
{
    public string GetUser() => "John";
}

Register in Program.cs:

builder.Services.AddScoped<IUserService, UserService>();

Inject into Controller:

public class UserController : ControllerBase
{
    private readonly IUserService _service;

    public UserController(IUserService service)
    {
        _service = service;
    }

    [HttpGet]
    public string Get() => _service.GetUser();
}

How it works:

Controller
    |
    v
IUserService (Interface)
    |
    v
Dependency Injection Container
    |
    v
UserService (Implementation)

Interview Key Point: Interfaces provide abstraction; DI provides implementations without the controller creating concrete service objects.

 

3. 🔴 Why do we create separate Controller, Service, and Repository classes?

We separate these classes to follow the Single Responsibility Principle (SRP) and maintain Separation of Concerns.

Layer

Responsibility

Controller

Handles HTTP requests and responses

Service

Contains business logic and validations

Repository

Handles database operations

Example:

HTTP Request
     |
     v
UserController
     |
     v
IUserService
     |
     v
UserService
     |
     v
IUserRepository
     |
     v
UserRepository
     |
     v
SQL Server

Advantages:

  • Easy unit testing.

  • Better maintainability.

  • Reusable business logic.

  • Reduced coupling.

  • Changes in one layer have less impact on others.

Interview Key Point: Controllers handle HTTP, Services handle business rules, and Repositories handle data access. A repository layer is optional when EF Core already provides sufficient abstraction.

 

4. 🔴 How do you implement polymorphism in a real-world application?

Polymorphism allows different classes to provide different implementations through a common interface or base class.

Example: Notification System

public interface INotification
{
    void Send();
}

public class EmailNotification : INotification
{
    public void Send()
    {
        Console.WriteLine("Email sent");
    }
}

public class SmsNotification : INotification
{
    public void Send()
    {
        Console.WriteLine("SMS sent");
    }
}

Usage:

INotification notification = new EmailNotification();
notification.Send();

notification = new SmsNotification();
notification.Send();

Output:

Email sent
SMS sent

Interview Key Point: The same method call executes different implementations depending on the actual object type. This is runtime polymorphism.

 

5. 🔴 How would you design multiple payment methods using interfaces and polymorphism?

I would use the Strategy Pattern, where each payment method implements a common interface.

Step 1: Create interface

public interface IPaymentService
{
    void Pay(decimal amount);
}

Step 2: Implement payment methods

public class UpiPayment : IPaymentService
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"UPI: {amount}");
    }
}

public class CardPayment : IPaymentService
{
    public void Pay(decimal amount)
    {
        Console.WriteLine($"Card: {amount}");
    }
}

Step 3: Execute payment

IPaymentService payment = new UpiPayment();
payment.Pay(1000);

payment = new CardPayment();
payment.Pay(2000);

Flow:

Payment Request
      |
      v
IPaymentService
      |
      +---- UpiPayment
      |
      +---- CardPayment
      |
      +---- NetBankingPayment

In ASP.NET Core, a payment factory or resolver can select the appropriate registered implementation based on the requested payment method.

Interview Key Point: New payment methods can be added without changing existing payment implementations, supporting the Open/Closed Principle.

 

6. 🔴 When would you choose an abstract class instead of an interface in a banking application?

Choose an abstract class when multiple related classes share common state, validation, and implementation.

Example:

public abstract class BankAccount
{
    public decimal Balance { get; protected set; }

    public void Deposit(decimal amount)
    {
        if (amount <= 0)
            throw new ArgumentException("Invalid amount");

        Balance += amount;
    }

    public abstract decimal CalculateInterest();
}

Derived class:

public class SavingsAccount : BankAccount
{
    public override decimal CalculateInterest()
    {
        return Balance * 0.04m;
    }
}

When to choose:

Abstract Class

Interface

Shared state and implementation

Common contract

Related account types

Different service implementations

Supports constructors

No instance constructors

Single class inheritance

Multiple interfaces supported

Interview Key Point: Use abstract classes for shared behavior and state; interfaces for contracts and loose coupling.

 

7. 🔴 How does Clean Architecture apply OOP and SOLID principles?

Clean Architecture separates the application into layers with clear responsibilities and dependencies pointing inward.

Example: ASP.NET Core Web API

Presentation (Web API)
          |
          v
Application
  Interfaces, DTOs, Use Cases
          |
          v
Domain
  Entities, Business Rules

Infrastructure
  EF Core, SQL Server, External APIs
          |
          v
Application / Domain Contracts

At runtime, the Web API uses Dependency Injection to connect application interfaces to infrastructure implementations.

OOP and SOLID implementation:

Principle

Clean Architecture Example

Encapsulation

Domain entities protect business rules

Abstraction

Application defines interfaces

Polymorphism

Different implementations of contracts

SRP

Each layer/class has a focused responsibility

OCP

Extend behavior without modifying core logic

LSP

Implementations honor their contracts

ISP

Small, focused interfaces

DIP

High-level logic depends on abstractions

Interview Key Point: Clean Architecture combines OOP and SOLID to keep business logic independent of databases, frameworks, and external services.

 

8. 🟡 How do you design reusable services without tightly coupling components?

I use interfaces, Dependency Injection, and SRP to design reusable services.

Example:

public interface IEmailService
{
    Task SendAsync(string email, string message);
}
public class OrderService
{
    private readonly IEmailService _email;

    public OrderService(IEmailService email)
    {
        _email = email;
    }
}

Benefits:

  • OrderService does not depend on a specific email provider.

  • Email implementation can be replaced.

  • The service can be reused by other modules.

  • Unit tests can use mock implementations.

Interview Key Point: Depend on interfaces instead of concrete classes to achieve loose coupling and reusability.

 

9. 🟡 How would you refactor a large class that violates the Single Responsibility Principle?

First, identify the different responsibilities handled by the class, then extract them into focused services.

Before refactoring:

public class OrderService
{
    public void CreateOrder() { }
    public void ProcessPayment() { }
    public void SendEmail() { }
    public void GenerateInvoice() { }
}

After refactoring:

OrderService
    |
    +---- IPaymentService
    |
    +---- IEmailService
    |
    +---- IInvoiceService

Each service handles one responsibility.

The OrderService coordinates the workflow through injected interfaces.

Interview Key Point: Refactoring using SRP improves maintainability, testability, and reduces the impact of future changes.

 

10. 🟡 How do you write unit tests for classes that depend on interfaces?

We use mock objects to replace external dependencies during unit testing.

Example using xUnit and Moq:

Service:

public class UserService
{
    private readonly IUserRepository _repository;

    public UserService(IUserRepository repository)
    {
        _repository = repository;
    }

    public string GetName(int id)
    {
        return _repository.GetName(id);
    }
}

Unit test:

[Fact]
public void GetName_ReturnsUserName()
{
    var mock = new Mock<IUserRepository>();

    mock.Setup(x => x.GetName(1))
        .Returns("John");

    var service = new UserService(mock.Object);

    Assert.Equal("John", service.GetName(1));
}

Benefits:

  • No real database required.

  • Tests execute quickly.

  • Dependencies can be controlled.

  • Business logic can be tested independently.

Interview Key Point: Interfaces and DI make unit testing easier by allowing real dependencies to be replaced with mocks or fakes.

 

11. 🟡 How would you replace a long if-else or switch statement using polymorphism?

I would use the Strategy Pattern to replace conditional business logic with separate implementations.

Before:

if (type == "Email")
    SendEmail();
else if (type == "SMS")
    SendSMS();
else if (type == "Push")
    SendPush();

After:

public interface INotification
{
    void Send();
}

Implementations:

public class EmailNotification : INotification
{
    public void Send() => Console.WriteLine("Email");
}

public class SmsNotification : INotification
{
    public void Send() => Console.WriteLine("SMS");
}

Usage:

INotification notification = new EmailNotification();
notification.Send();

A factory or DI-based resolver selects the implementation at runtime. This may still require a small selection mechanism, but the business logic no longer depends on a growing chain of conditions.

Interview Key Point: Polymorphism replaces complex conditional behavior with extensible implementations and supports OCP.

 

12. 🟡 How do you decide between inheritance, composition, and Dependency Injection?

The decision depends on the relationship between classes and how dependencies should be managed.

Concept

When to Use

Example

Inheritance

IS-A relationship

SavingsAccount IS-A BankAccount

Composition

HAS-A relationship

OrderService HAS-A PaymentProcessor

Dependency Injection

External dependency supplied to a class

Inject IPaymentService into OrderService

Inheritance:

public class SavingsAccount : BankAccount
{
}

Composition:

public class Car
{
    private readonly Engine _engine = new();
}

Dependency Injection:

public class OrderService
{
    private readonly IPaymentService _payment;

    public OrderService(IPaymentService payment)
    {
        _payment = payment;
    }
}

Interview Key Point:

  • Use Inheritance for genuine IS-A relationships.

  • Prefer Composition to combine functionality without rigid inheritance hierarchies.

  • Use Dependency Injection to supply dependencies externally and reduce coupling.

Dependency Injection is often a way of implementing composition, rather than an alternative to it.

 

Quick Interview Revision – All 12 Questions

#

Topic

Key Points to Remember

1

Four OOP Pillars

Encapsulation, Abstraction, Inheritance, Polymorphism

2

Interface + DI

Contract + Implementation + DI Container

3

Controller / Service / Repository

HTTP + Business Logic + Data Access

4

Polymorphism

Same contract, different behavior

5

Multiple Payments

Interface + Strategy Pattern

6

Abstract Class vs Interface

Shared implementation vs Contract

7

Clean Architecture

OOP + SOLID + Dependency Rule

8

Reusable Services

Interfaces + DI + Loose Coupling

9

SRP Refactoring

Split responsibilities into focused classes

10

Unit Testing

xUnit + Moq + Mock Dependencies

11

Replace if-else

Strategy Pattern + Polymorphism

12

Inheritance vs Composition vs DI

IS-A vs HAS-A vs Injected Dependency

Explain association in C# with simple example.

Association in C#

Association is an "uses-a" relationship between two independent classes. One object can use or communicate with another object, but both objects can exist independently.

  • One class knows about another class.
  • There is no ownership between them.
  • If one object is destroyed, the other object still exists.

Real-Life Example

A Teacher teaches a Student.

  • A Teacher can exist without a Student.
  • A Student can exist without a Teacher.
  • They are simply associated with each other.

C# Example

using System;

public class Student
{
    public string Name { get; set; }

    public Student(string name)
    {
        Name = name;
    }
}

public class Teacher
{
    public string Name { get; set; }

    public Teacher(string name)
    {
        Name = name;
    }

    public void Teach(Student student)
    {
        Console.WriteLine($"{Name} is teaching {student.Name}");
    }
}

class Program
{
    static void Main()
    {
        Student student = new Student("John");
        Teacher teacher = new Teacher("David");

        teacher.Teach(student);
    }
}

Output

David is teaching John

Explanation

  • Teacher and Student are independent classes.
  • The Teacher object only uses the Student object in the Teach() method.
  • Neither object owns the other.
  • If the Teacher object is deleted, the Student object still exists.
  • If the Student object is deleted, the Teacher object still exists.

Another Example

A Customer places an Order.

public class Customer
{
    public string Name { get; set; }
}

public class Order
{
    public void PlaceOrder(Customer customer)
    {
        Console.WriteLine($"{customer.Name} placed an order.");
    }
}

Here, Order uses Customer, but neither owns the other.

UML Representation

+---------+        Uses        +---------+
| Teacher | -----------------> | Student |
+---------+                    +---------+

Key Points

  • Association means one object uses another object.
  • It represents a "uses-a" relationship.
  • Both classes are independent.
  • There is no ownership.
  • Association can be one-to-one, one-to-many, or many-to-many.

Interview Definition

Association is a relationship between two independent classes where one class uses or communicates with another class, but neither class owns the other. Both objects have independent lifecycles.

Aggregation in C#

Aggregation is a special type of Association that represents a "has-a" relationship with weak ownership.

The parent object contains a reference to the child object, but the child can exist independently of the parent.

  • Parent has child.
  • Child can exist without the parent.
  • Parent does not own the child's lifetime.

Real-Life Example

A Department has Teachers.

  • A Teacher can exist without a Department.
  • If a Department is deleted, the Teacher still exists and can join another Department.

C# Example

using System;
using System.Collections.Generic;

public class Teacher
{
    public string Name { get; set; }

    public Teacher(string name)
    {
        Name = name;
    }
}

public class Department
{
    public string Name { get; set; }

    public List<Teacher> Teachers { get; }

    public Department(string name, List<Teacher> teachers)
    {
        Name = name;
        Teachers = teachers;
    }

    public void ShowTeachers()
    {
        Console.WriteLine($"Department: {Name}");

        foreach (var teacher in Teachers)
        {
            Console.WriteLine(teacher.Name);
        }
    }
}

class Program
{
    static void Main()
    {
        Teacher t1 = new Teacher("David");
        Teacher t2 = new Teacher("John");

        List<Teacher> teachers = new List<Teacher>
        {
            t1,
            t2
        };

        Department department = new Department("Computer Science", teachers);

        department.ShowTeachers();

        // Department object is destroyed
        department = null;

        // Teachers still exist
        Console.WriteLine(t1.Name);
        Console.WriteLine(t2.Name);
    }
}

Output

Department: Computer Science
David
John
David
John

Explanation

  • Department has Teacher objects.
  • Teacher objects are created outside the Department.
  • The Department only stores references to the teachers.
  • If the Department object is destroyed, the Teacher objects still exist.
  • This is weak ownership.

Another Example

A Team has Players.

public class Player
{
    public string Name { get; set; }
}

public class Team
{
    public List<Player> Players { get; set; }
}

Even if the Team object is deleted, the Player objects can join another team.

UML Representation

+------------+      ◇-------->     +---------+
| Department |                    | Teacher |
+------------+                    +---------+

◇ = Hollow Diamond (Aggregation)

Characteristics

  • Represents a Has-A relationship.
  • Parent and child have independent lifecycles.
  • Child objects are created externally.
  • Parent stores only references to child objects.
  • Also called weak ownership.

Association vs Aggregation

Association Aggregation
Uses-a relationship Has-a relationship
No ownership Weak ownership
Objects are independent Objects are independent
One object uses another Parent contains child reference
Example: Teacher teaches Student Example: Department has Teachers

Interview Definition

Aggregation is a special type of association that represents a "has-a" relationship with weak ownership. The parent contains references to child objects, but the child objects can exist independently of the parent.

Composition in C#

Composition is a special type of Aggregation that represents a "has-a" relationship with strong ownership.

The parent object owns the child object. If the parent is destroyed, the child is also destroyed.

  • Parent creates the child.
  • Parent owns the child.
  • Child cannot exist independently.
  • Child's lifetime depends on the parent.

Real-Life Example

A House has Rooms.

  • A Room cannot exist without a House.
  • If the House is demolished, its Rooms also cease to exist.

C# Example

using System;

public class Engine
{
    public void Start()
    {
        Console.WriteLine("Engine Started");
    }
}

public class Car
{
    // Car owns the Engine
    private Engine engine;

    public Car()
    {
        engine = new Engine();   // Created inside Car
    }

    public void StartCar()
    {
        engine.Start();
        Console.WriteLine("Car Started");
    }
}

class Program
{
    static void Main()
    {
        Car car = new Car();
        car.StartCar();
    }
}

Output

Engine Started
Car Started

Explanation

  • Car creates the Engine object using new Engine().
  • The Engine object is private to the Car.
  • No other class can directly use or share this Engine.
  • If the Car object is destroyed, its Engine is also destroyed.
  • This is strong ownership.

Another Example

A House has Rooms.

using System.Collections.Generic;

public class Room
{
    public string Name { get; set; }

    public Room(string name)
    {
        Name = name;
    }
}

public class House
{
    public List<Room> Rooms { get; }

    public House()
    {
        Rooms = new List<Room>
        {
            new Room("Living Room"),
            new Room("Bedroom"),
            new Room("Kitchen")
        };
    }
}

Here:

  • House creates the Room objects.
  • Room objects belong only to that House.
  • They are not shared with another House.

UML Representation

+------+      ◆-------->      +--------+
| Car  |                     | Engine |
+------+                     +--------+

◆ = Filled Diamond (Composition)

Characteristics

  • Represents a Has-A relationship.
  • Strong ownership.
  • Parent creates the child object.
  • Child cannot exist without the parent.
  • Child is usually private to the parent.
  • Child is not shared with other objects.

Aggregation vs Composition

Aggregation Composition
Weak ownership Strong ownership
Child exists independently Child depends on parent
Child created outside parent Child created inside parent
Child can be shared Child is not shared
Parent stores reference Parent owns the object
Example: Department has Teachers Example: Car has Engine

Association vs Aggregation vs Composition

Feature Association Aggregation Composition
Relationship Uses-A Has-A Has-A
Ownership No ownership Weak ownership Strong ownership
Independent lifecycle Yes Yes No
Child created by parent No No Yes
Child survives parent Yes Yes No
Example Teacher teaches Student Department has Teachers Car has Engine

Interview Definition

Composition is a special type of aggregation that represents a "has-a" relationship with strong ownership. The parent creates and owns the child object, and the child cannot exist independently of the parent.

 

 

For a Senior .NET Developer / Technical Lead interview, questions 2, 3, 5, 7, 9, and 12 deserve particular attention because they test architecture decisions, maintainability, extensibility, and real-world design experience.

← Back to Articles