Call Interface Method from Console Application - c#

I have a Web Application where I have the class:
public class PTPostalCodeService : IPTPostalCodeService
{
private readonly IRepository<PTPostalCode> _ptPostalCodeRepository;
public PTPostalCodeService(IRepository<PTPostalCode> ptPostalCodeRepository)
{
_ptPostalCodeRepository = ptPostalCodeRepository;
}
public PTPostalCodeDto GetPTPostalCode(int postalCode, int? postalCodeExtension)
{
PTPostalCode ptPostalCodeDomain = new PTPostalCode();
ptPostalCodeDomain = _ptPostalCodeRepository.Get(
filter: p => p.PostalCode == postalCode && (postalCodeExtension.HasValue == false || p.PostalCodeExtension == postalCodeExtension),
includeProperties: "PTCouncil, PTCouncil.PTDistrict").FirstOrDefault();
var ptPostalCodeDto = Mapper.Map<PTPostalCode, PTPostalCodeDto>(ptPostalCodeDomain);
return ptPostalCodeDto;
}
}
Now I need to access the methid GetPTPostalCode from a ConsoleApplication, any idea?
EDIT:
I have AutoFac to manage constructors:
// Repository
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerHttpRequest();
The interface of the Repository:
public interface IRepository<T> where T : class
Thanks.

Related

Base and Inheritance class names/prefixes

I have a main class such as the following ( with extending class called Keys )
public class Engine : Keys, IEngine, IDisposable
{
private readonly Network _network;
public Engine(bool useMainNet = false) : base(useMainNet)
{
_network = useMainNet ? Network.Main : Network.TestNet;
}
public Network GetCurrentNetwork() => _network;
Where the Keys class has functions like GenerateKeys() as following
public class Keys : IDisposable, IKeys
{
public Keys(bool useMainNet = false)
{
_network = useMainNet ? Network.Main : Network.TestNet;
}
public string GenerateKeys()
{
return "KEY_GEN";
}
}
The problem is I can call the method as follows
using (Engine engine = new(true))
{
engine.GenerateKeys();
}
It works fine, but what I want is the following
using (Engine engine = new(true))
{
engine.Keys.GenerateKeys();
// OR engine.Keys().GenerateKeys();
}
So I want the Main_Method.Sub_Method.Function, It makes more sense this way, Is it possible?
As mentioned in the comments, you are probably mixing the principles of compositions and inheritance
Try this:
public class Engine : IEngine, IDisposable
{
private readonly Network _network;
public Engine(bool useMainNet = false) : base(useMainNet)
{
_network = useMainNet ? Network.Main : Network.TestNet;
}
public Network GetCurrentNetwork() => _network;
// by property
public Keys Keys => new Keys();
// by method (with parameters)
public Keys Keys(bool useMainNet = false) => new Keys(useMainNet);
...
}

Mock UnitOfWork interface with a Repository interface property

I am implementing a unit test to test a method in a helper class.
I have mocked my IRepository interface and passed its object to my mocked IUnitOfWork because this IRepository interface is a property to the UnitOfWork. While debugging the unit test, I found out that the call to '_unitOfWork.Booking.OverlappingBooking' in the helper class always return null. The OverlappingBooking()is not invoked at all.
public class BookingHelper
{
private IUnitOfWork _unitOfWork;
public BookingHelper(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public string OverlappingBookingsExist(Booking booking)
{
if (booking.Status == "Cancelled")
return string.Empty;
var bookings = _unitOfWork.Booking.GetActiveBookings<Booking>().Where(
b => b.Id != booking.Id && b.Status != "Cancelled");
var overlappingBooking = _unitOfWork.Booking.OverlappingBooking(bookings, booking);
return overlappingBooking;
}
}
my UnitOfWork
public interface IUnitOfWork
{
IBookingHelperRepository Booking { get; set; }
}
public class UnitOfWork: IUnitOfWork
{
public IBookingHelperRepository Booking { get; set; }
public UnitOfWork()
{
Booking = new BookingHelperRepository();
}
}
Repository
public interface IBookingHelperRepository
{
IQueryable<T> GetActiveBookings<T>();
string OverlappingBooking(IQueryable<Booking> bookings, Booking booking);
}
public class BookingHelperRepository: IBookingHelperRepository
{
public IQueryable<T> GetActiveBookings<T>()
{
var resp = new List<T>().AsQueryable();
return resp;
}
public string OverlappingBooking(IQueryable<Booking> bookings, Booking booking)
{
var overlappingBooking = bookings.FirstOrDefault(
b => booking.ArrivalDate >= b.ArrivalDate
&& booking.ArrivalDate < b.DepartureDate
|| booking.DepartureDate > b.ArrivalDate
&& booking.DepartureDate <= b.DepartureDate);
return overlappingBooking == null ? string.Empty : overlappingBooking.Reference;
}
}
I have set up my test class as below.
[TestClass]
public class BookingHelperTests
{
private Mock<IBookingHelperRepository> bookingHelperRepository;
private BookingHelper bookingHelper;
private Booking booking;
private Mock<IUnitOfWork> unitOfWork;
[TestInitialize]
public void Initialise()
{
unitOfWork = new Mock<IUnitOfWork>();
bookingHelper = new BookingHelper(unitOfWork.Object);
bookingHelperRepository = new Mock<IBookingHelperRepository>();
.....
}
[TestMethod]
public void OverlappingBookingsExist_BookingStartsAndFinishesBeforeAnExistingBooking_ShouldReturnEmptyString()
{
bookingHelperRepository.Setup(y => y.GetActiveBookings<Booking>()).Returns(bookingListBefore.AsQueryable());
unitOfWork.Setup(x => x.Booking).Returns(bookingHelperRepository.Object);
//Act
var result = bookingHelper.OverlappingBookingsExist(booking);
//Assert
Assert.AreEqual("", result);
}
The code you want to test calls (IBookingHelperRepository)(IUnitOfWork.Booking).OverlappingBooking(), which you don't mock. Because mocks are loose by default, they return null instead of throwing an exception.
If you'd set up new Mock<IBookingHelperRepository>() with MockBehavior.Strict, you'd receive an exception telling you that you haven't set up the method string OverlappingBooking(IQueryable<Booking> bookings, Booking booking).
In order to do so:
var queryableBookings = bookingListBefore.AsQueryable();
bookingHelperRepository.Setup(y => y.GetActiveBookings<Booking>()).Returns(queryableBookings);
bookingHelperRepository.Setup(y => y.OverlappingBooking(queryableBookings, booking).Returns(booking.Reference);

Inject different DbContexts into generic repository based on Domain class - Autofac

In my application, I need to interact with two databases. I have two domain classes which are located in two different databases. I also have a generic repository pattern which accepts an UoW in its constructor. I am looking a way to inject appropriate UoW based on Domain class. I do not want to write second generic repository for the second database.. Is there any neat solution?
public interface IEntity
{
int Id { get; set; }
}
Located in Database A
public class Team: IEntity
{
public int Id { get; set; }
public string Name{ get; set; }
}
Located in Database B
public class Player: IEntity
{
public int Id { get; set; }
public string FullName { get; set; }
}
I also have a generic repository pattern with UoW
public interface IUnitOfWork
{
IList<IEntity> Set<T>();
void SaveChanges();
}
public class DbADbContext : IUnitOfWork
{
public IList<IEntity> Set<T>()
{
return new IEntity[] { new User() { Id = 10, FullName = "Eric Cantona" } };
}
public void SaveChanges()
{
}
}
public class DbBDataContext: IUnitOfWork
{
public IList<IEntity> Set<T>()
{
return new IEntity[] { new Tender() { Id = 1, Title = "Manchester United" } };
}
public void SaveChanges()
{
}
public interface IRepository<TEntity> where TEntity: class, IEntity
{
IList<IEntity> Table();
}
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
protected readonly IUnitOfWork Context;
public BaseRepository(IUnitOfWork context)
{
Context = context;
}
IList<IEntity> IRepository<TEntity>.Table()
{
return Context.Set<TEntity>();
}
}
I've already found articles saying that Autofac overrides the registration with the last value. I know my problem is how DbContexts are registered.
var builder = new ContainerBuilder();
// problem is here
builder.RegisterType<DbADbContext >().As<IUnitOfWork>()
builder.RegisterType<DbBDbContext >().As<IUnitOfWork>()
builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IRepository<>));
var container = builder.Build();
I inspired from #tdragon's answer.
The first step is registering Named DbContext
builder.RegisterType<Database1>()
.Keyed<IUnitOfWork>(DbName.Db1)
.Keyed<DbContext>(DbName.Db1).AsSelf().InstancePerRequest();
builder.RegisterType<Database2>()
.Keyed<IUnitOfWork>(DbName.Db2)
.Keyed<DbContext>(DbName.Db2).AsSelf().InstancePerRequest();
Please note that DbName is just an enum.
The following code scans the data access layer assembly for finding Domain classes. Then, it registers ReadOnlyRepository and BaseRepository. the place of this code is in DIConfig
Type entityType = typeof(IEntity);
var entityTypes = Assembly.GetAssembly(typeof(IEntity))
.DefinedTypes.Where(t => t.ImplementedInterfaces.Contains(entityType));
var baseRepoType = typeof(BaseRepository<>);
var readOnlyRepoType = typeof(ReadOnlyRepository<>);
var baseRepoInterfaceType = typeof(IRepository<>);
var readOnlyRepoInterfaceType = typeof(IReadOnlyRepository<>);
var dbContextResolver = typeof(DbContextResolverHelper).GetMethod("ResolveDbContext");
foreach (var domainType in entityTypes)
{
var baseRepositoryMaker = baseRepoType.MakeGenericType(domainType);
var readonlyRepositoryMarker = readOnlyRepoType.MakeGenericType(domainType);
var registerAsForBaseRepositoryTypes = baseRepoInterfaceType.MakeGenericType(domainType);
var registerAsForReadOnlyRepositoryTypes = readOnlyRepoInterfaceType.MakeGenericType(domainType);
var dbResolver = dbContextResolver.MakeGenericMethod(domainType);
// register BaseRepository
builder.Register(c => Activator.CreateInstance(baseRepositoryMaker, dbResolver.Invoke(null, new object[] { c }))
).As(registerAsForBaseRepositoryTypes).InstancePerRequest(jobTag);
//register readonly repositories
builder.Register(c => Activator.CreateInstance(readonlyRepositoryMarker, dbResolver.Invoke(null, new object[] { c })))
.As(registerAsForReadOnlyRepositoryTypes).InstancePerRequest(jobTag);
}
The following methods try to find DbSet in each DbContext in order to find out the Domain Classes belongs to which DataContext/Database.
public class DbContextResolverHelper
{
private static readonly ConcurrentDictionary<Type, DbName> TypeDictionary = new ConcurrentDictionary<Type, DbName>();
public static DbContext ResolveDbContext<TEntity>(IComponentContext c) where TEntity : class, IEntity
{
var type = typeof(DbSet<TEntity>);
var dbName = TypeDictionary.GetOrAdd(type, t =>
{
var typeOfDatabase1 = typeof(Database1);
var entityInDatabase1 = typeOfDatabase1 .GetProperties().FirstOrDefault(p => p.PropertyType == type);
return entityInDatabase1 != null ? DbName.Db1: DbName.Db2;
});
return c.ResolveKeyed<DbContext>(dbName);
}
}
What about this:
builder.RegisterType<DbContextBase>().As<IUnitOfWork>()
And
DbADataContext: DbContextBase,IUnitOfWork
DbBDataContext: DbContextBase,IUnitOfWork
Or in your registration you can just do something like :
containerBuilder.RegisterGeneric(typeof(DbADataContext<>)).Named("DbADataContext", typeof(IUnitOfWork<>));
containerBuilder.RegisterGeneric(typeof(DbBDataContext<>)).Named("DbBDataContext", typeof(IUnitOfWork<>));
If you want to keep single BaseRepository and its interface, you have to somehow configure, with entity would be handled by which DbContext. It could be done in registration part of application, but in that case you cannot register your BaseRepostory<T> as open generic, but be explicit in your registrations, like this:
containerBuilder.RegisterType<DbADataContext>().Named<IUnitOfWork>("A");
containerBuilder.RegisterType<DbBDataContext>().Named<IUnitOfWork>("B");
containerBuilder.Register(c => new BaseRepository<Team>(c.ResolveNamed<IUnitOfWork>("A")).As<IRepostory<Team>>();
containerBuilder.Register(c => new BaseRepository<Player>(c.ResolveNamed<IUnitOfWork>("B")).As<IRepository<Player>>();
(just proof of concept, code not tested)
Autofac is not smart enough to know "automatically" which unit of work you want to use in each of your repository.

Invoking a different constructor with autofixture [duplicate]

I'm using AutoFixture and I'd like to use a specific constructor.
I have the following code and I like to select the constructor with ITemplateParameterHandler.
public sealed class TemplateSegmentHandler : ITemplateSegmentHandler
{
public TemplateSegmentHandler(ITemplateIterator iterator)
: this(new TemplateParameterHandler(iterator))
{
Contract.Requires(iterator != null);
}
public TemplateSegmentHandler(ITemplateParameterHandler parameterHandler)
{
Contract.Requires(parameterHandler != null);
_parameterHandler = parameterHandler;
_parameterHandler.Ending += EndingParameter;
}
// ...
}
EDIT:
I want to inject the following fake implementation. (I'm using NSubstitute to create the fake object.)
public sealed class CustomTemplateParameter : ICustomization
{
private readonly ITemplateParameterHandler _context;
public CustomTemplateParameter()
{
_context = Substitute.For<ITemplateParameterHandler>();
}
public void Customize(IFixture fixture)
{
fixture.Customize<ITemplateParameterHandler>(c => c.FromFactory(() => _context));
}
public CustomTemplateParameter SetCatchAll(bool isCatchAll)
{
_context.IsCatchAll.Returns(isCatchAll);
return this;
}
}
Here is the way I'm trying to use it.
[Fact]
public void Should_return_true_when_the_segment_has_a_catch_all_parameter()
{
TemplateSegmentHandler segmentHandler = new Fixture().Customize(new TemplateSegmentHandlerFixture())
.Customize(new CustomTemplateParameterHandler()
.SetCatchAll(true))
.Create<TemplateSegmentHandler>();
segmentHandler.Parameter.Start();
segmentHandler.Parameter.End();
segmentHandler.HasCatchAll.Should().BeTrue();
}
But it still selects the wrong constructor and I'm getting the following error.
Ploeh.AutoFixture.ObjectCreationExceptionAutoFixture was unable to create an instance from Somia.Web.Routing.Template.ITemplateIterator, most likely because it has no public constructor, is an abstract or non-public type.
Request path:
Somia.Web.Routing.Template.TemplateSegmentHandler -->
Somia.Web.Routing.Template.ITemplateIterator iterator -->
Somia.Web.Routing.Template.ITemplateIterator
I ended up implementing IMethodQuery and select the ctor I wanted.
public sealed class SelectedFirstConstructorQuery : IMethodQuery
{
private readonly Type _type;
public SelectedFirstConstructorQuery(Type type)
{
_type = type;
}
public IEnumerable<IMethod> SelectMethods(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
return from ci in type.GetConstructors()
let parameter = ci.GetParameters().First()
where parameter.ParameterType == _type
select new ConstructorMethod(ci) as IMethod;
}
}
Usage:
fixture.Customize<TemplateSegmentHandler>(c => c.FromFactory(new MethodInvoker(new SelectedFirstConstructorQuery(typeof(ITemplateParameterHandler)))));
One possible way:
var parameterHandler = fixture.Create<ITemplateParameterHandler>();
var segmentHandler = fixture.Build<TemplateSegmentHandler>()
.FromFactory(() => new TemplateSegmentHandler(parameterHandler));
fixture.Inject(segmentHandler);

Constructor dependency injection via unity with parameters from HttpContext

We're using domain to customize how our application behaves. I'll illustrate it on example:
// default behavior
public class CoreService : IService {
public virtual string Hello { get { return "Hello"; } }
public virtual string FavouriteDrink { get { return "Water"; } }
}
// german.site.com
public class GermanService : CoreService {
public override string Hello { get { return "Gutten tag"; } }
public override string FavouriteDrink { get { return "Beer"; } }
}
// usa.site.com
public class UsaService : CoreService {
public override string FavouriteDrink { get { return "Cofee"; } }
}
Services are bootstrapped as follow:
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
I use Unity to bootstrap mvc controllers. IE:
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - this resolves into "CoreService"
public HomeController([Dependency]IService service) {
if (service == null) {
throw new ArgumentNullException("service");
}
m_Service = service;
}
}
Is there a way how to change unity resolution so it'll take domain into account ? Right now I ended up with
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - a lot less magical
public HomeController() {
m_Service = DomainServiceLocator.Retrieve<IService>();
}
}
Support classes:
public static class DomainServiceLocator {
private static UnityContainerAdapter adapter;
public static T Retrieve<T>() {
string domain = HttpContext.Current.Request.Url.Host;
if (adapter.IsServiceRegistered(typeof(T), domain)) {
return adapter.Resolve<T>(domain);
}
return adapter.Resolve<T>();
}
}
public class QueryableContainerExtension : UnityContainerExtension {
private List<RegisterInstanceEventArgs> registeredInstances = new List<RegisterInstanceEventArgs>();
private List<RegisterEventArgs> registeredTypes = new List<RegisterEventArgs>();
protected override void Initialize() {
this.Context.Registering += (sender, e) => { this.registeredTypes.Add(e); };
this.Context.RegisteringInstance += (sender, e) => { this.registeredInstances.Add(e); };
}
public bool IsServiceRegistered(Type service, string name) {
return registeredTypes.FirstOrDefault(e => e.TypeFrom == service && e.Name == name) != null
|| registeredInstances.FirstOrDefault(e => e.RegisteredType == service && e.Name == name) != null;
}
}
public class UnityContainerAdapter {
private readonly QueryableContainerExtension queryableContainerExtension;
private readonly IUnityContainer unityContainer;
public UnityContainerAdapter()
: this(new UnityContainer()) {
}
public UnityContainerAdapter(IUnityContainer unityContainer) {
this.unityContainer = unityContainer;
// adding extensions to unity container
this.queryableContainerExtension = new QueryableContainerExtension();
unityContainer.AddExtension(this.queryableContainerExtension);
}
public T Resolve<T>(string name) {
return unityContainer.Resolve<T>(name);
}
public T Resolve<T>() {
return unityContainer.Resolve<T>();
}
public bool IsServiceRegistered(Type service, string name) {
return this.queryableContainerExtension.IsServiceRegistered(service, name);
}
}
I like to use an injection factory in these scenarios when resolving something at runtime. Essentially you're resolving your type via the domain name:
So in your composition root you could register like this:
container.RegisterType<Func<string, IService>>
(
new InjectionFactory(c => new Func<string, IService>(name => c.Resolve<IService>(name)))
);
Then in your HomeController you can inject the delegate
public class HomeController
{
private readonly Func<string,IService> _serviceFactory;
public HomeController(Func<string, IService> serviceFactory)
{
if(serviceFactory==null)
throw new ArgumentNullException("serviceFactory");
this._serviceFactory= serviceFactory;
}
public void DoSomethingWithTheService()
{
var domain = this.HttpContext.Uri.Host;
var service = this._serviceFactory(domain);
var greeting = service.Hello;
}
}
```
This is then still unit testable and you have not leaked the DI contain implementation outside of "composition root".
Also.. should CoreService be abstract to avoid direct instantiation of it?
Below is the solution I ended up with - it is based on #Spencer idea. I've created a factory, default implementation to the factory has a reference to DI container itself (IUnityContainer in my case), so it can perform the resolution based on domain once it is asked to. It is also more "modern friendly" since in current generation of ASP.NET (ASP.NET CORE) there is no such thing as magic singleton providing current HttpContext and DI is hard coded into the framework.
public interface IFactory<T>
{
T Retrieve(string domain);
}
internal sealed class Factory<T> : IFactory<T>
{
private readonly IUnityContainer _container;
public Factory(IUnityContainer container)
{
_container = container;
}
public T Resolve(string domain)
{
// this is actually more complex - we have chain inheritance here
// for simplicity assume service is either registered for given
// domain or it throws an error
return _container.Resolve<T>(domain);
}
}
// bootstrapper
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
container.RegisterInstance<IFactory<IService>>(new Factory<IService>(container));
And the home controller looks like
public class HomeController : Controller {
private IFactory<IService> m_Factory;
public HomeController(IFactory<IService> factory) {
m_Factory = factory;
}
private void FooBar() {
var service = m_Factory.Retrieve(this.HttpContext.Uri.Host);
var hello = service.Hello;
}
}
Its also a worth mentioning that - as I'm lazy - I've build a system of decorative attributes like
[Domain("german.site.com")]
public class GermanService : IService { ... }
[DomainRoot]
public class CoreService : IService { ... }
[Domain("usa.site.com")]
public class UsaService : CoreService { ... }
So the bootstrapping is done automatically across all types in given assembly. But that part is a bit lengthy - if anyone is interested I can post it on github.

Categories

Resources