Test Controller with unitofwork in asp.net mvc - asp.net-mvc

I have a Model :
public class Post:
{
public string Description { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public Guid UniqId { get; set; }
public DateTime CreatedDate { get; set; }
public byte[] RowVersion { get; set; }
}
and i have a DataLayer that has EfContext and Iunitofwok pattern
using System.Data.Entity;
namespace Data
{
public interface IUnitOfWork
{
IDbSet<TEntity> Set<TEntity>() where TEntity : class;
int SaveChanges();
}
}
using System.Data.Entity;
using DomainModel;
namespace Data
{
public class EfContext : DbContext, IUnitOfWork
{
public DbSet<Post> Post { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Category> Categories { get; set; }
public EfContext()
: base("TavanGruop")
{
}
#region IUnitOfWork Members
public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
{
return base.Set<TEntity>();
}
#endregion
}
}
in another project i have repository
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using Data;
namespace ServiceLayer.ServiceDbSet
{
public class ServiceContext<T> : IServiceDbSet<T> where T : class
{
private readonly IDbSet<T> _dbSet;
public ServiceContext(IUnitOfWork iUnitOfWork)
{
_dbSet = iUnitOfWork.Set<T>();
}
#region IContext<T> Members
public bool TryGet(Func<T, bool> predicate, out T entity)
{
entity = List(predicate).SingleOrDefault();
return entity != null;
}
public T Get(Func<T, bool> predicate)
{
return List(predicate).Single();
}
public virtual List<T> List(Func<T, bool> predicate = null)
{
IEnumerable<T> result = _dbSet.AsEnumerable();
if (predicate != null)
result = result.Where(predicate);
return result.ToList();
}
public T Add(T t)
{
_dbSet.Add(t);
return t;
}
public void Delete(Func<T, bool> predicate)
{
List(predicate).ToList().ForEach(p => _dbSet.Remove(p));
}
public void Delete(T t)
{
_dbSet.Remove(t);
}
#endregion
}
}
and service
using Data;
using DomainModel;
using ServiceLayer.ServiceDbSet;
namespace ServiceLayer.EfServices
{
public class EfPostService : ServiceContext<Post>
{
public EfPostService(IUnitOfWork uow)
: base(uow)
{
}
}
}
and this my services
using Data;
using ServiceLayer.EfServices;
namespace ServiceLayer
{
public class Services
{
private readonly IUnitOfWork _unitOfWork;
private EfPostService _post;
private EfCommentService _comment;
public Services(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public EfPostService Post
{
get { return _post ?? new EfPostService(_unitOfWork); }
set { _post = value; }
}
public EfCommentService Comment
{
get { return _comment ?? new EfCommentService(_unitOfWork); }
set { _comment = value; }
}
}
}
I use tructuremap for dependency injection
using System;
using System.Web.Mvc;
using System.Web.Routing;
using Data;
using StructureMap;
namespace MVCTemplateProject
{
public static class StructuremapMvc
{
public static void InitStructureMap()
{
ObjectFactory.Initialize(x => x.For<IUnitOfWork>().HttpContextScoped().Use(() => new EfContext()));
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
}
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return ObjectFactory.GetInstance(controllerType) as Controller;
}
}
}
in base controller i get Iunitofwork
using System.Web.Mvc;
using Data;
using ServiceLayer;
namespace MVCTemplateProject.Controllers
{
public class BaseController : Controller
{
public readonly IUnitOfWork Context;
public readonly Services DataContext;
public BaseController(Data.IUnitOfWork context)
{
Context = context;
DataContext = new Services(context);
}
}
}
and this my home controller
using System.Web.Mvc;
using Data;
using DomainModel;
namespace MVCTemplateProject.Controllers
{
public class HomeController : BaseController
{
public HomeController(IUnitOfWork context)
: base(context)
{
}
public ActionResult Index()
{
return View(DataContext.Post.List());
}
}
}
how can i test index action with moq
i write this test but i get error
public void IndxShouldReturnListOfPage()
{
var posts = new List<Post>
{
new Post {Name = "Test"},
new Post {Name = "Test"},
new Post {Name = "Test"},
new Post {Name = "Test"}
};
var efContext = new Mock<EfContext>();
var mockRepository = new Mock<ServiceLayer.Services>(efContext);
mockRepository.Setup(x => x.Post.List(It.IsAny<Func<Post, bool>>())).Returns(posts);
var controller = new HomeController(efContext.Object);
List<Post> model = controller.DataContext.Post.List();
var result = controller.Index() as ViewResult;
Assert.AreEqual(model.Count, 4);
Assert.AreEqual(string.Empty, result.ViewName);
}

i get it and i test the project
[TestFixture]
public class PostControllerTest
{
#region Setup/Teardown
[SetUp]
public void Setup()
{
UnitOfWork = TestHelper.TestHelper.GetMockUnitOfWork();
PostDbSet = TestHelper.TestHelper.GetMockPostDbSet();
Posts = TestHelper.TestHelper.GetFakePosts();
TagDbSet = TestHelper.TestHelper.GetMockTagDbSet();
CategoryDbSet = TestHelper.TestHelper.GetMockCategoryDbSet();
PostController = new PostController(UnitOfWork.Object, PostDbSet.Object, CategoryDbSet.Object, TagDbSet.Object);
}
#endregion
private Mock<IServiceDbSet<Post>> PostDbSet { get; set; }
private Mock<IServiceDbSet<Tag>> TagDbSet { get; set; }
private Mock<IServiceDbSet<Category>> CategoryDbSet { get; set; }
private PostController PostController { get; set; }
private List<Post> Posts { get; set; }
private Mock<IUnitOfWork> UnitOfWork { get; set; }
[Test]
public void DetailShouldRedirectToHomePageWhenNotFoundPostOrPostIdIs0()
{
PostDbSet.Setup(x => x.Get(It.IsAny<Func<Post, bool>>())).Returns(Posts.Find(post => post.Id == 100));
var redirectToRoutResult =
(RedirectToRouteResult) PostController.Details(100);
Assert.AreEqual("Index", redirectToRoutResult.RouteValues["action"]);
Assert.AreEqual("Home", redirectToRoutResult.RouteValues["Controller"]);
}
[Test]
public void DetailShouldShowPostById()
{
PostDbSet.Setup(x => x.Get(It.IsAny<Func<Post, bool>>())).Returns(Posts.First());
var result = PostController.Details(1) as ViewResult;
var model = result.Model as PostViewModel;
Assert.AreNotEqual(null, model);
Assert.AreEqual("I Can", model.Title);
Assert.AreEqual(string.Empty, result.ViewName);
}
[Test]
public void ListOfStringTagMustConvertToListOfTagCollection()
{
PostViewModel postViewModel = TestHelper.TestHelper.GetFakePostViewModel();
PostController.Create(postViewModel);
//Assert.AreEqual(postViewModel.RawTags[0], postViewModel.RawTags.First().Name);
}

Related

xUnit with Moq. Test CRUD operation (generic dataservice) Entity Framework Core 6

I am trying to test my project using ef 6. here is the situation: I have the mold class and have some generic services like GetAll,GetById,Create,Update, Delete. trying to test these methods using xUnit. Stuck in mocking.
public partial class TblPtsVMold :IMoldObject
{
public int MoldId { get; set; }
public string? MoldType { get; set; }
public string? Plant { get; set; }
}
public partial class PTSProdContext : DbContext
{
private IConfiguration _configuration { get; set; }
public PTSProdContext()
{
}
public PTSProdContext(DbContextOptions<PTSProdContext> options)
: base(options)
{
}
public virtual DbSet<TblPtsVMold> TblPtsVMolds { get; set; } = null!;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer
(_configuration.GetConnectionString
(_configuration["EnvionmentString:ENVIRONMENT"]));
}
}
}
public class PTSContextFactory
{
public string DbConnectionString { get; set; }
public PTSContextFactory(string dbConnectionString)
{
DbConnectionString = dbConnectionString;
}
public PTSProdContext CreateDbContext()
{
DbContextOptionsBuilder<PTSProdContext> options = new DbContextOptionsBuilder<PTSProdContext>();
options.UseSqlServer(DbConnectionString);
return new PTSProdContext(options.Options);
}
public interface IDataService<T>
{
IEnumerable<T> GetAll();
IEnumerable<T> GetAllWithID(List<int> Ids);
T Get(int id);
T Create(T entity);
}
generic dataservice class
public class GenericDataService<T> : IDataService<T> where T : class, IDomainObject
{
public readonly PTSContextFactory _contextFactory;
public GenericDataService(PTSContextFactory contextFactory)
{
_contextFactory = contextFactory;
}
public GenericDataService()
{
}
public IEnumerable<T> GetAllWithID(List<int> Ids)
{
using (PTSProdContext context = _contextFactory.CreateDbContext())
{
IEnumerable<T> entities = context.Set<T>().Where(e => Ids.Contains(e.Id)).ToList();
if (entities == null)
{
WeakReferenceMessenger.Default.Send(new LookupExceptionMessage(string.Format("Can't find record.")));
return default;
}
return entities;
}
}
public IEnumerable<T> GetAll()
{
using (PTSProdContext context = _contextFactory.CreateDbContext())
{
IEnumerable<T> results = context.Set<T>().ToList();
if (results == null)
{
return default;
}
return results;
}
}
Test:
[Fact]
public void GetAll_TestClassObjectPassed_ProperMethodCalled()
{
// Arrange
var testObject = new TblPtsVMold() { Id = 1 };
var testList = new List<TblPtsVMold>() { testObject };
var data = new List<TblPtsVMold>
{
new TblPtsVMold { MoldType = "test",Plant="testpass1" },
new TblPtsVMold { MoldType = "ZZZ",Plant="testpass2" },
new TblPtsVMold { MoldType = "AAA",Plant="testpass3" },
}.AsQueryable();
var dbSetMock = new Mock<DbSet<TblPtsVMold>>();
dbSetMock.As<IQueryable<TblPtsVMold>>().Setup(x => x.Provider).Returns(testList.AsQueryable().Provider);
dbSetMock.As<IQueryable<TblPtsVMold>>().Setup(x => x.Expression).Returns(testList.AsQueryable().Expression);
dbSetMock.As<IQueryable<TblPtsVMold>>().Setup(x => x.ElementType).Returns(testList.AsQueryable().ElementType);
dbSetMock.As<IQueryable<TblPtsVMold>>().Setup(x => x.GetEnumerator()).Returns(testList.AsQueryab`your text`le().GetEnumerator());
var context = new Mock<PTSProdContext>();
context.Setup(x => x.Set<TblPtsVMold>()).Returns(dbSetMock.Object);
// Act
var context = new Mock<PTSContextFactory>();
context.Setup(x => x.DbConnectionString).Returns(string.Empty);
var service = new GenericDataService<TblPtsVMold>(context.Object);
var result = service.GetAll();
// Assert
Assert.Equal(testList, result.ToList());
}
context.Setup(x => x.DbConnectionString).Returns(string.Empty); is not correct.
getting error:pportedException : Unsupported expression: x => x.DbConnectionString Non-overridable members (here: PTSContextFactory.get_DbConnectionString) may not be used in setup verification expressions.
How to test GetAll or create method. Is anything wrong here?

Unable to retrieve data from database using repository pattern

I'm currently learning interfaces and repository pattern and have difficulties with it. I have domain class "VehicleMake"
public class VehicleMake
{
public VehicleMake()
{
}
[Key]
[Column(Order = 1)]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Name { get; set; }
public virtual ICollection<VehicleModel> VehicleModels { get; set; }
}
I also have an Interface "IVehicleRepository"
public interface IVehicleRepository
{
IEnumerable<VehicleMake> All { get; }
}
and a class "VehicleRepository" which implements that interface
public class VehicleRepository : IVehicleRepository
{
private readonly VehicleDbContext _context;
public VehicleRepository(VehicleDbContext context)
{
_context = context;
}
public IEnumerable<VehicleMake> All => _context.VehicleMakes;
}
My DbContext class is following
public class VehicleDbContext : DbContext
{
public VehicleDbContext() : base("VehicleDbContext")
{
}
public DbSet<VehicleMake> VehicleMakes { get; set; }
public DbSet<VehicleModel> VehicleModels { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
}
And my "VehicleController" is following
public class VehicleController : Controller
{
private readonly IVehicleRepository _vehicleRepository;
public VehicleController()
{
}
public VehicleController(IVehicleRepository vehicleRepository)
{
_vehicleRepository = vehicleRepository;
}
// GET: VehicleMakes
public ActionResult Index()
{
return View(_vehicleRepository.All);
}
}
So the problem is that when I try in my controller to retrieve "Vehicle Makes", I get null reference exception and I don't why. Did I implemented this properly? If not, what is the proper way to do this?
You are getting NullReferenceException because it's calling your parameterless constructor where you don't have initialization of _vehicleRepository field. Your initialization is in constructor where you are passing IVehicleRepository object.
I believe, you don't have dependedency injection framework registered for correctly getting instance. So, you can simply initialize _vehicleRepository in default constructor :
public class VehicleController : Controller
{
private readonly IVehicleRepository _vehicleRepository;
public VehicleController()
{
_vehicleRepository = new VehicleRepository();
}
// GET: VehicleMakes
public ActionResult Index()
{
return View(_vehicleRepository.All);
}
}
Change your VehicleRepository to support default constructor in following way :
public class VehicleRepository : IVehicleRepository
{
private readonly VehicleDbContext _context;
public VehicleRepository() : this(new VehicleDbContext())
{
}
public VehicleRepository(VehicleDbContext context)
{
_context = context;
}
public IEnumerable<VehicleMake> All => _context.VehicleMakes;
}

EF. AutoFac. Constantly got error DBContext has been disposed

Initial data. Code First, Autofac
Before was Linq2Sql and the entire data layer was in the main project.
I rewrote all on EF CodeFirst.
Now I keep getting an error: DBContext has been disposed
There is a class:
public class DataManager: IDataManager
{
private IModelDataContextWrapper _dataContext;
public IAuditRepository Audits { get; set; }
public ICDMRepository CDMs { get; set; }
public ICommandRepository Commands { get; set; }
public IMonitoringRepository Monitorings { get; set; }
public IRoleRepository Roles { get; set; }
public ISettingRepository Settings { get; set; }
public IUserRepository Users { get; set; }
public DataManager(IModelDataContextWrapper dataContext)
{
_dataContext = dataContext;
}
public IModelDataContextWrapper DataContext
{
get
{
return _dataContext;
}
}
public void Dispose()
{
if (_dataContext != null)
{
_dataContext.Dispose();
_dataContext = null;
}
GC.SuppressFinalize(this);
}
public void SaveChanges()
{
try
{
DataContext.SaveChanges();
}
catch (Exception ex)
{
string err = string.Format("exception: {0} stacktrace: {1}", ex.Message, ex.StackTrace);
Logger.Instance.WriteLine(err);
}
}
}
public class UserRepository : IUserRepository
{
private readonly IModelDataContext _context;
public UserRepository(IModelDataContext context)
{
_context = context;
}
}
Autofac registration:
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<ModelDataContext>().As<IModelDataContext>().InstancePerLifetimeScope();
builder.RegisterType<ModelDataContextWrapper>().As<IModelDataContextWrapper>().InstancePerLifetimeScope();
builder.RegisterType<ArchiveModelDataContext>().As<IArchiveModelDataContext>().InstancePerLifetimeScope();
builder.RegisterType<DataManager>().As<IDataManager>().PropertiesAutowired().InstancePerLifetimeScope();
builder.RegisterType<AuditRepository>().As<IAuditRepository>().InstancePerLifetimeScope();
builder.RegisterType<CommandRepository>().As<ICommandRepository>().InstancePerLifetimeScope();
builder.RegisterType<CDMRepository>().As<ICDMRepository>().InstancePerLifetimeScope();
builder.RegisterType<MonitoringRepository>().As<IMonitoringRepository>().InstancePerLifetimeScope();
builder.RegisterType<RoleRepository>().As<IRoleRepository>().InstancePerLifetimeScope();
builder.RegisterType<SettingRepository>().As<ISettingRepository>().InstancePerLifetimeScope();
builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerLifetimeScope();
builder.RegisterType<ThemedViewEngine>();
builder.RegisterFilterProvider();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var lifetimeScope = DependencyResolver.Current.GetService<ILifetimeScope>();
lifetimeScope.InjectProperties(Membership.Provider);
lifetimeScope.InjectProperties(Roles.Provider);
What is wrong?
Personally I use .InstancePerRequest(); in web context.
And you need avoid IQueryable in you view, be sure you have ToList() or request trigger in your controller and not in your view
Updated:
builder.RegisterType<ModelDataContextWrapper>()
.As<IModelDataContextWrapper >()
.InstancePerRequest();

How to eager load child entities using repository pattern

I have an entity named Tour which can have many Agents. I am able to add agents, but I cannot remove them.
// _repo is injected....
var tour = _repo.GetById(tourId);
tour.AddAgent(new Agent(tour.TourId));
When I attempt to call the Tour.RemoveAgent() method nothing is actually removed. I set a breakpoint inside the Tour.RemoveAgent() method I see that the _agents property has a count of 0.
tour.RemoveAgent(agentId); // This doesn't work because _agents is empty
Do I have to do something special for EF to populate the _agents property when I retrieve the Tour from my repository?
UPDATE: PROBLEM SOLVED (thanks to Paul's answer)
I decided to just create a Repository unique to each aggregate, that way it is easy to define exactly what needs to be included using the Include() function. This is an example where I inherit from the GenericRepository<T> class (which is also included at the bottom of this question).
public class TourRepository : GenericRepository<Tour>
{
public TourRepository(IDatabaseFactory databaseFactory) : base (databaseFactory)
{
}
public override Tour GetById(Guid id)
{
return dataContext.Tours
.Include(x => x.Agents)
.Single(x => x.TourId == id);
}
}
Tour Class
public partial class Tour
{
public Guid TourId { get; private set; }
protected virtual List<Agent> _agents { get; set; }
public Tour()
{
TourId = Guid.NewGuid();
_agents = new List<Agent>();
}
public void AddAgent(Agent agent)
{
_agents.Add(agent);
}
public void RemoveAgent(Guid agentId)
{
_agents.RemoveAll(a => a.AgentId == agentId);
}
}
Agent Class
public partial class Agent
{
public Guid AgentId { get; private set; }
public Guid TourId { get; private set; }
public Tour Tour { get; private set; }
public Agent(Guid tourId)
{
TourId = tourId;
AgentId = Guid.NewGuid();
}
}
OnModelCreating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// AGENTS ============================
modelBuilder.Entity<Agent>()
.HasKey(x => x.AgentId)
.Property(p => p.AgentId);
modelBuilder.Entity<Agent>()
.HasRequired(p => p.Tour)
.WithMany(t => t.Agents);
// TOURS =============================
modelBuilder.Entity<Tour>()
.HasKey(x => x.TourId)
.Property(x => x.TourId);
}
Repository Class
public class GenericRepository<T> : IRepository<T> where T : class {
private MyContext dataContext;
private readonly IDbSet<T> dbset;
public GenericRepository(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected MyContext DataContext
{
get { return dataContext ?? (dataContext = DatabaseFactory.Get()); }
}
// ... stuff removed for brevity ...
public T GetById(Guid id)
{
return dbset.Find(id);
}
}
Try making protected virtual List _agents { get; set; } public
public virtual List<Agent> _agents { get; set; }
You can also eager load by doing something like this:
_databaseContext.Tours.Include(x => x.Agents).Single(x => x.TourId == tourId)
you can read more here: http://blogs.msdn.com/b/adonet/archive/2011/01/31/using-dbcontext-in-ef-feature-ctp5-part-6-loading-related-entities.aspx

Container Resolve based on criteria

I'm trying to implement the Strategy pattern while using Windsor container. Here is what I have:
public class OrderProcessor {
...
public OrderProcessor(ITaxStrategy strategy) {}
public void Process(Order order)
{
order.Tax = strategy.CalcTax(order);
}
}
The problem is, how do I configure my container (other container examples welcome) to have, essentially, criteria for choosing the appropriate dependency. So if I register the following
public class USTaxStrategy : ITaxStrategy { ... }
public class CanadaTaxStrateg : ITaxStrategy { ... }
how do I use the Order.Destination (address) as the criteria for the injected dependency?
Here are a few options, pick the one you like best. I usually use the first one, it's the simplest.
[TestFixture]
public class TaxStrategyTests {
[Test]
public void InjectWithFactory() {
var container = new WindsorContainer();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessor>();
container.AddComponent<ITaxStrategyFactory, TaxStrategyFactory>();
var order = new Order {Country = "US"};
container.Resolve<OrderProcessor>().Process(order);
Assert.AreEqual(10, order.Tax);
}
[Test]
public void InjectWithFactoryFromDictionary() {
var container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessor>();
container.Register(Component.For<ITaxStrategyFactory>()
.UsingFactoryMethod(kernel => new TaxStrategyFactory2(new Dictionary<string, ITaxStrategy> {
{"US", kernel.Resolve<USTaxStrategy>()},
{"CA", kernel.Resolve<CanadaTaxStrategy>()},
})));
var order = new Order { Country = "US" };
container.Resolve<OrderProcessor>().Process(order);
Assert.AreEqual(10, order.Tax);
}
[Test]
public void InjectWithProxy() {
var container = new WindsorContainer();
container.AddComponent<USTaxStrategy>();
container.AddComponent<CanadaTaxStrategy>();
container.AddComponent<OrderProcessorInterceptor>();
container.AddComponent<ITaxStrategyFactory, TaxStrategyFactory>();
container.Register(Component.For<OrderProcessor2>()
.LifeStyle.Transient
.Interceptors(InterceptorReference.ForType<OrderProcessorInterceptor>()).First);
var order = new Order {Country = "CA"};
container.Resolve<OrderProcessor2>().Process(order);
Assert.AreEqual(5, order.Tax);
}
public class OrderProcessorInterceptor : IInterceptor {
private readonly ITaxStrategyFactory strategyFactory;
public OrderProcessorInterceptor(ITaxStrategyFactory strategyFactory) {
this.strategyFactory = strategyFactory;
}
public void Intercept(IInvocation invocation) {
if (invocation.MethodInvocationTarget.Name == "Process") {
var processor = (OrderProcessor2) invocation.InvocationTarget;
var order = (Order) invocation.Arguments[0];
processor.Strategy = strategyFactory.Create(order);
}
invocation.Proceed();
}
}
public interface IOrderProcessor {
void Process(Order order);
}
public class OrderProcessor2 : IOrderProcessor {
public ITaxStrategy Strategy { get; set; }
public virtual void Process(Order order) {
order.Tax = Strategy.CalcTax(order);
}
}
public class OrderProcessor : IOrderProcessor {
private readonly ITaxStrategyFactory strategyFactory;
public OrderProcessor(ITaxStrategyFactory strategyFactory) {
this.strategyFactory = strategyFactory;
}
public void Process(Order order) {
var strategy = strategyFactory.Create(order);
order.Tax = strategy.CalcTax(order);
}
}
public interface ITaxStrategyFactory {
ITaxStrategy Create(Order o);
}
public class TaxStrategyFactory : ITaxStrategyFactory {
private readonly IKernel kernel;
public TaxStrategyFactory(IKernel kernel) {
this.kernel = kernel;
}
public ITaxStrategy Create(Order o) {
if (o.Country == "US")
return kernel.Resolve<USTaxStrategy>();
return kernel.Resolve<CanadaTaxStrategy>();
}
}
public class TaxStrategyFactory2: ITaxStrategyFactory {
private readonly IDictionary<string, ITaxStrategy> strategies;
public TaxStrategyFactory2(IDictionary<string, ITaxStrategy> strategies) {
this.strategies = strategies;
}
public ITaxStrategy Create(Order o) {
return strategies[o.Country];
}
}
public interface ITaxStrategy {
decimal CalcTax(Order order);
}
public class USTaxStrategy : ITaxStrategy {
public decimal CalcTax(Order order) {
return 10;
}
}
public class CanadaTaxStrategy : ITaxStrategy {
public decimal CalcTax(Order order) {
return 5;
}
}
public class Order {
public string Country { get; set; }
public decimal Tax { get; set; }
}
}

Resources