DEV Community

Code Today
Code Today

Posted on

What Are .NET PO Extension Methods?

For example, you can add a ToTitleCase method to the string class to convert a sentence into title case without altering the string class itself.

How to Create an Extension Method

Creating an extension method is straightforward. Here’s a step-by-step guide:

Define a Static Class
The class that holds your extension methods must be static.

Write a Static Method
The method itself must be static and take the type you want to extend as the first parameter, prefixed with the this keyword.

using Microsoft.EntityFrameworkCore;
using PetShopSimulation.DAL.Repositories.Ports;
using System.Linq.Expressions;

namespace PetShopSimulation.DAL.Repositories
{
    public class PositionRepository : IRepository<Position>
    {
        private readonly SafeCamDbContext _context;

        public PositionRepository(SafeCamDbContext context)
        {
            _context = context;
        }

        public DbSet<Position> Table => _context.Positions;

        public async Task<Position?> GetByIdAsync(int id, params Expression<Func<Position, object>>[] includes)
        {
            IQueryable<Position> query = Table;
            foreach (var include in includes)
            {
                query = query.Include(include);
            }
            return await query.FirstOrDefaultAsync(x => x.Id == id);
        }

        public IQueryable<Position> GetAll(params Expression<Func<Position, object>>[] includes)
        {
            IQueryable<Position> query = Table;
            foreach (var include in includes)
            {
                query = query.Include(include);
            }
            return query;
        }

        public async Task<Position> AddAsync(Position entity)
        {
            await Table.AddAsync(entity);
            await _context.SaveChangesAsync();
            return entity;
        }

        public async Task UpdateAsync(Position entity)
        {
            Table.Update(entity);
            await _context.SaveChangesAsync();
        }

        public async Task DeleteAsync(Position entity)
        {
            Table.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Best Practices for Writing Extensions

To make the most of extension methods, follow these guidelines:

Keep It Simple
Extension methods should perform a single, well-defined task. Avoid overloading them with too much logic.

Ensure Compatibility
Use extension methods for functionality that is universally applicable to the type. Avoid adding niche behavior that’s only relevant in specific contexts.

Handle Null Gracefully
Always consider null inputs to avoid runtime exceptions.

Name Methods Intuitively
Choose method names that clearly describe their purpose to improve code readability.

using System.Linq.Expressions;

namespace PetShopSimulation.BLL.Services
{
    public class PositionService
    {
        private readonly IRepository<Position> _repository;

        public PositionService(IRepository<Position> repository)
        {
            _repository = repository;
        }

        public async Task<IEnumerable<Position>> GetAllPositionsAsync()
        {
            return await _repository.GetAll().ToListAsync();
        }

        public async Task<Position?> GetPositionByIdAsync(int id)
        {
            return await _repository.GetByIdAsync(id);
        }

        public async Task AddPositionAsync(PositionCreateDto dto, IMapper mapper)
        {
            var position = mapper.Map<Position>(dto);
            await _repository.AddAsync(position);
        }

        public async Task UpdatePositionAsync(PositionUpdateDto dto, IMapper mapper)
        {
            var position = mapper.Map<Position>(dto);
            await _repository.UpdateAsync(position);
        }

        public async Task DeletePositionAsync(int id)
        {
            var position = await _repository.GetByIdAsync(id);
            if (position == null)
            {
                throw new NotPositionException();
            }
            await _repository.DeleteAsync(position);
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Why and When to Use Extension Methods

Extension methods are incredibly versatile and can be used in various scenarios:

Utility Functions: Create helper methods for common operations, such as string manipulations or date calculations.

Framework Integration: Add functionality to types from external libraries without modifying their source code.

Improved Readability: Make your code more expressive and easier to understand by encapsulating logic in extension methods.

using PetShopSimulation.BLL.Services;

namespace PetShopSimulation.Controllers
{
    public class PositionController : Controller
    {
        private readonly PositionService _service;
        private readonly IMapper _mapper;

        public PositionController(PositionService service, IMapper mapper)
        {
            _service = service;
            _mapper = mapper;
        }

        public async Task<IActionResult> Index()
        {
            var positions = await _service.GetAllPositionsAsync();
            return View(positions);
        }

        [HttpGet]
        public IActionResult Create()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Create(PositionCreateDto dto)
        {
            if (!ModelState.IsValid) return View();

            await _service.AddPositionAsync(dto, _mapper);
            return RedirectToAction("Index");
        }

        [HttpGet]
        public async Task<IActionResult> Update(int id)
        {
            var position = await _service.GetPositionByIdAsync(id);
            if (position == null) throw new NotPositionException();

            var positionDto = _mapper.Map<PositionUpdateDto>(position);
            return View(positionDto);
        }

        [HttpPost]
        public async Task<IActionResult> Update(PositionUpdateDto dto)
        {
            if (!ModelState.IsValid) return View(dto);

            await _service.UpdatePositionAsync(dto, _mapper);
            return RedirectToAction("Index");
        }

        [HttpPost]
        public async Task<IActionResult> Delete(int id)
        {
            await _service.DeletePositionAsync(id);
            return RedirectToAction("Index");
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay