Hi im working of a text book called: Microservices in dotnet book second edition, and have reached a part in chapter where the author talks about Dependency Injection (DI) using a package called Scrutor. However, examples of the book are done in .Net 5 (netcoreapp3.0) and I've been working with .Net 6 which does not have a StartUp file but rather has a Program File as the main file, when a project is generated.
so in the author's code for DI there is the following in StartUp.cs
...
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.Scan(selector =>
selector
.FromAssembly<StartUp>()
.AddClasses()
.AsImplementedInterfaces());
}
...
And my .net 6 code is as follows in my Program.cs file
...
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.Scan(scan =>
scan.FromAssemblyOf<Program>()
.AddClasses()
.AsImplementedInterfaces());
...
With my controller code implementation:
namespace ShoppingCartMicroservice.ShoppingCart
{
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("/shoppingcart")]
public class ShoppingCartController : ControllerBase
{
private readonly IShoppingCartStore shoppingCartStore;
public ShoppingCartController(IShoppingCartStore shoppingCartStore)
{
this.shoppingCartStore = shoppingCartStore;
}
[HttpGet("{userId:int}")]
public ShoppingCart Get(int userId) =>
this.shoppingCartStore.Get(userId);
}
}
The interface:
using ShoppingCartMicroservice.ShoppingCart;
public interface IShoppingCartStore
{
ShoppingCart Get(int userId);
void save(ShoppingCart shoppingCart);
}
My In memory Shopping car store:
using ShoppingCartMicroservice.ShoppingCart;
public class ShoppingCartStore : IShoppingCartStore
{
private static readonly Dictionary<int, ShoppingCart> Database = new Dictionary<int, ShoppingCart>();
public ShoppingCart Get(int userId) =>
Database.ContainsKey(userId) ? Database[userId] : new ShoppingCart(userId);
public void save(ShoppingCart shoppingCart) =>
Database[shoppingCart.UserId] = shoppingCart;
}
And my logic
namespace ShoppingCartMicroservice.ShoppingCart
{
using System.Collections.Generic;
using System.Linq;
public class ShoppingCart
{
private readonly HashSet<ShoppingCartItem> items = new();
public int UserId { get; }
public IEnumerable<ShoppingCartItem> Items => this.items;
public ShoppingCart(int UserId) => this.UserId = UserId;
public void AddItems(IEnumerable<ShoppingCartItem> shoppingCartItems)
{
foreach (var item in shoppingCartItems)
{
this.items.Add(item);
}
}
public void RemoveItems(int[] productCatalogueIds) =>
this.items.RemoveWhere(i => productCatalogueIds.Contains(i.ProductCatalogueId));
}
public record ShoppingCartItem
(
int ProductCatalogueId,
string ProductName,
string Description,
Money Price
)
{
public virtual bool Equals(ShoppingCartItem? obj) =>
obj != null && this.ProductCatalogueId.Equals(obj.ProductCatalogueId);
public override int GetHashCode() =>
this.ProductCatalogueId.GetHashCode();
}
public record Money(string Currency, decimal Amount);
}
However with my implementation, at run time I get the following error:
Exception has occurred: CLR/System.AggregateException
An unhandled exception of type 'System.AggregateException' occurred in Microsoft.Extensions.DependencyInjection.dll: 'Some services are not able to be constructed'
Inner exceptions found, see $exception in variables window for more details.
Innermost exception System.InvalidOperationException : Unable to resolve service for type 'System.Int32' while attempting to activate 'ShoppingCartMicroservice.ShoppingCart.ShoppingCartItem'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
Link to project: https://github.com/dot-net-microservices-in-action/chapter-02