How can I inject all instances as collection IEnumerable<T> that implement a common interface in Prism? - prism

I want to inject all instances as IEnumerable<T> that implement a common interface. It is for using it in a strategy pattern resolver. How can I do it? I googled that unity container has a way.
I need this to do the same job as link below.
https://ufukhaciogullari.com/blog/strategy-pattern-with-dependency-injection/
public interface ITest
{
string Name { get; set; }
}
public class TestA : ITest
{
public string Name { get; set; } = "A";
}
public class TestB : ITest
{
public string Name { get; set; } = "B";
}
public class TestC : ITest
{
public string Name { get; set; } = "C";
}
public class SomeResolver
{
IEnumerable<ITest> _tests;
public SomeResolver(IEnumerable<ITest> tests)
{
_tests = tests;
}
}
In unity, I can register the following way:
container.RegisterType<IEnumerable<IParserBuilder>, IParserBuilder[]>();
I tried to do the same in Prism, but it fails. How to do it in Prism?

I tried to do the same in Prism, but it fails. How to do it in Prism?
Prism's no dependency injection container, it just tries to hide IUnityContainer from you.
That being said, there's no need to register the IEnumerable<IParserBuilder> in the first place.
container.Resolve<SomeResolver>()
will call the constructor and pass it instances of TestA, TestB and TestC, given you registered them first.
container.Register<ITest, TestA>( "A" );
container.Register<ITest, TestB>( "B" );
container.Register<ITest, TestC>( "C" );
Unfortunately, there's no way to have those A, B and C injected, too, so you have to keep the Name property if you need to identify a specific service (I'd make it read-only, though). I'd love to be able to inject IEnumerable<(string, ITest)> and get the names, too...

Related

Optional string input when following string inputs are not optional?

I am trying to implement an interface as a service controller. I do not maintain this interface, so I am unable to modify it. For simplicity, let's say the interface looks like this:
public interface IFoo
{
string Bar(string A, int B);
}
For my controller, let's say it looks like this:
public class FooController : ApiController, IFoo
{
[Route("~/Foo/Bar")]
[HttpGet]
public string Bar(string optionalA, int requiredB)
{
return DoStuff(optionalA, requiredB);
}
}
With this setup, how can I decorate A as Optional and B as Required without changing IFoo (i.e. cannot reorder A and B) and while still having my controller implement IFoo? By default, all string parameters are considered Required unless I pull them into a class at which point they revert to defaulting to Optional unless I decorate them with a RequiredAttribute but I cannot do that here because that would require either changing IFoo or would break my requirement to implement IFoo with this controller class.
Is there a straight up way to do this in a way that Swagger & Swagger UI honors it? I'd like to avoid this hacky solution:
public class FooController : ApiController, IFoo
{
[Route("~/Foo/Bar")]
[HttpGet]
public string FakeBar(MyDto data)
{
return Bar(data.optionalA, data.requiredB);
}
[ApiExplorerSettings(IgnoreApi = true)]
public string Bar(string optionalA, int requiredB)
{
return DoStuff(optionalA, requiredB);
}
}
public class MyDto
{
// defaults to optional here
public string optionalA { get; set; }
[Required]
public int requiredB { get; set; }
}
I do understand that if I could reorder A and B (that's not an option) then the simple solution is this:
public string Bar(int requiredB, string optionalA = null)
I have found that I am unable to accomplish this. I am forced to either change the interface or not implement the interface or some other nasty thing that causes way too much additional code. At this time, I think there is just no other way to directly control the requiredness of a parameter to an action handler.
Will gladly defer to anybody who corrects me though! ;-)

Configure AutoMapper to return Mock in test layer

In my app, all domain classes follow the standardization:
All implement the interface IEntity
Id properties are protected*
The properties of type IList are protected and initialized in the constructor.
Below is a classic example of a domain entity:
public class CheckListItemTemplate : IEntity
{
public virtual int Id { get; protected set; }
public virtual string Text { get; set; }
public virtual CheckListItemTemplate Parent { get; set; }
public virtual IList<CheckListItemTemplate> Itens { get; protected set; }
public CheckListItemTemplate()
{
Itens = new List<CheckListItemTemplate>();
}
public void AddItem(CheckListItemTemplate item)
{
item.Parent = this;
Itens.Add(item);
}
}
*This is because the id is generated by the database and not run the risk of some developer trying to set this property.
Test project
We have a fake generic repository used in the tests:
public class Repository<T> : IRepository<T>
where T : class, IEntity
{
private readonly IDictionary<int, T> _context = new Dictionary<int, T>();
public void Delete(T obj)
{
_context.Remove(obj.Id);
}
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stub = Mock.Get<T>(obj);
stub.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stub.Object);
}
}
// ..
}
As you can see in the Store*, all test objects (of type IEntity) should be a Mock**. This is because in UI project, when we save an object NHibernate updating the property Id. In testing project we have to do this manually, and we have no way to set the property Id with a new value, so the solution was mock the entire object to the Get property Id correspond to the new Id . Exactly what does this line stub.Setup(s => s.Id).Returns(generateId).
*By convention, objects with Id <= 0 are new and Id> 0 are existing objects in the database.
**For Mock I use Moq.
Id as protected
The biggest problem occurs because of Id property and the fact that is protected.
When we talk about the designer, is a great approach but this brings huge inconvenience when we test our application.
For example, in a test that I'm writing I need my Fake repository with some data already populated.
Code
Follow me. I have the following classes (+ CheckListItemTemplate shown above.)
public class Passo : IEntity
{
public int Id { get; protected set; }
public virtual IList<CheckListItemTemplate> CheckListItens { get; protected set; }
}
public class Processo : IEntity
{
public virtual int Id { get; protected set; }
public virtual Passo Passo { get; set; }
public virtual IList<CheckListItem> CheckListItens { get; protected set; }
}
After saving the Processo, the first Passo is associated with the Processo: (sorted by Ordem field following field CreateAt)
model.Passo = PassoRepositorio.All().OrderBy(p => p.Ordem).ThenBy(p => p.CreateAt).First();
model.CheckListItens.Clear();
Parallel.ForEach(Mapper.Map<IList<CheckListItem>>(model.Passo.CheckListItens), (it) => model.AddCheckListItem(it));
This code is running whenever you save a new Processo. For any test that creates a new Processo, this code will be executed!
Test
If we have to create a test that creates a new Processo, our first goal is to populate the PassoRepositorio repository with some dummy data*, with Passos and CheckListItemTemplates specifically for the above code does not fail**.
*To populate objects with dummy data I use AutoFixture.
** Will fail if no Passo is found in the repository .First() and this Passo has no checklist Mapper.Map(model.Passo.CheckListItens).
So we need a repository of Passos and each Passo with a list of CheckListItens.
Remember that every object IEntity should be an Mock<> so we can mock property Id
First attempt
First configure my TestInitialize to populate my repository with some dummy data:
var fix = new Fixture();
var listPassos = fix.Build<Mock<Passo>>()
.Do((passo) => {
passo.SetupProperty(x => x.Nome, fix.Create<string>());
passo.SetupGet(x => x.CheckListItens).Returns(
fix.Build<CheckListItemTemplate>() // Needs to a Mock<>
.With(p => p.Texto)
.OmitAutoProperties()
.CreateMany(5).ToList()
);
})
.OmitAutoProperties()
.CreateMany(10);
foreach (var item in listPassos)
passoRepository.Store(item.Object);
Then I can run the tests:
[TestMethod]
public void Salvar_novo_processo_modificar_data_atendimento_passo_atual()
{
// Arrange
var fix = new Fixture();
var vm = fix.Create<ProcessoViewModel>();
//Act
Controller.salvar(vm); // Problem here. (For convert ProcessoViewModel to Processo I use a AutoMaper. In repository needs destination to be a Mock<Processo>
var processo = Repository.Get(p => p.DataEntrada == vm.DataEntrada && p.ProximoAtendimento == vm.ProximoAtendimento);
//Asserts
processo.Should().NotBeNull();
processo.Passo.Should().NotBeNull();
}
Questions
We create a list of 10 Passo where each Passo is actually is a Mock<>, great! But:
For each Passo have a list of 5 'Mock' items, and each Id should be 1, 2, 3, 4 and 5 (in that order). How to achieve this? How to obtain this list of IList<Mock<>> inside a Mock<> with Id already filled? That is, the configuration
passo.SetupGet(x => x.CheckListItens).Returns( ???
The responsible for creating objects in my controller, basically uses AutoMapper to convert my ViewModel object to an object that can be persisted Model in my repository:
model = Mapper.Map<TModel>(vm);
The problem is that my repository Fake can not save an object IEntity, just Mock<IEntity>. How to configure AutoMapper to always return a Mock<>?
Answer for Question 1: In case this helps, you can use a closure to maintain a running counter to use as an id. For example:
class MyTestClass
{
int _runningCounter = 0;
public void SomeTest()
{
/* ... some other code including mock creation ...*/
someMock.Setup(m => m.ReturnNewWidgetEntity())
.Returns(() => new WidgetEntity{ Id= ++_runningCounter });
}
}
Each time ReturnNewWidgetEntity is called on the mocked object, the Id property will be set to an increased number.
Answer for Question 2: I would suggest that rather than having a concrete dependency on the Mapper class, you replace this with an injected dependency on IMapperEngine. Richard Dingwall explains the technique here: http://richarddingwall.name/2009/05/07/mocking-out-automapper-with-dependency-injection/
Basically you register Mapper.Engine as the singleton implementation of IMapperEngine in your container and then in your unit tests mock it so that it gives you the required Mock<> classes.
I hope one or both of these answers at least give you food for thought. It was a bit difficult to follow your whole example, to be honest!

using ninject to inject dependency to The Model classes or non-controller classes

I using Ninject 3 in Repository pattern in mvc 3 (steven sanderson Scaffolder).
and in ninject i have the class "NinjectWebCommon" which in the "RegisterServices" method i resolved the dependencies and i think im ready to go.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICityRepository>().To<CityRepository>();
kernel.Bind<IVillageRepository >().To<VillageRepository>();
}
i using my repositories in controllers using constructor injection and everything is fine.
public class CityController : Controller
{
private readonly ICityRepository cityRepository;
// If you are using Dependency Injection, you can delete the following constructor
//public CityController() : this(new CityRepository())
//{
//}
public CityController(ICityRepository cityRepository)
{
this.cityRepository = cityRepository;
}
// .........
}
but when i use this repositories in other classes like Model(Entity) classes using property injection or field injection the dependency doesn't resolved and i get null reference exception on my Property or field.
[MetadataType(typeof(CityMetadata))]
public partial class City : IValidatableObject
{
[Inject]
public IVillageRepository VillageRepo { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var village = VillageRepo.Find(5); // will throw null reference exception on "VillageRepo"
}
}
public partial class CityMetadata
{
[ScaffoldColumn(false)]
public int ID { get; set; }
[Required(ErrorMessage = MetadataErrorMessages.Required)]
[StringLength(50, ErrorMessage = MetadataErrorMessages.ExceedMaxLength)]
public string Name { get; set; }
}
i don't know why this happening. so whats the problem and how can i use the repositories in non-controller classes?
thanks in advance.
Your problem is, you're expecting magic. You inject an implementation for your repository, and then you expect that data objects created by that repository are injected with references of the creating repository.
First of all, that doesn't work like that. The implementation of the repository will call new() (or Activator.CreateInstance) on your entities, not ask for an instance from a Ninject Kernel or Factory. You could rewrite the repository (it'll get trickier if you're using EF there...) but it's probably not worth the hassle.
On the top of it all, you shouldn't be needing that at all. Entities shouldn't depend on repositories, imho not even their interfaces.
EDIT: now I see why you want to see a repo in your model. What I recommend is a static factory maybe.
public class Factories
{
public static readonly Instance = new Factories();
[Inject]
public Func<IVillageRepository> VillageRepo {get; set;}
}
Then call Kernel.Inject(Factories.Instance); from your Ninject initialization code (where you bind IVillageRepository). Then modify your validatable implementation to Factories.Instance.VillageRepo().Find(...);

NHibernate 3 Linq and IUserType

I have a table:
Page (
Id int,
Name nvarchar(50),
TemplateName varchar(50)
...
)
and it's mapped to domain model:
public class Page {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Template Template { get; set; }
}
Note that in the domain model, "Template" property is not of type "string".
The Template class is like this:
public class Template {
public string Name { get; set; }
// other properties...
}
"Templates" are loaded from file system. I have a TemplateManager class:
public class TemplateManager {
public static Template LoadTemplate(string templateName) {
// check if there's a folder named <templateName>
}
}
I can use IUserType to map the "Template" property.
public class PageMap : ClassMapping<Page> {
public PageMap() {
...
Property(c => c.Template, m => {
m.Column("TemplateName");
m.Type<TemplateUserType>();
}
}
}
public class TemplateUserType : IUserType {
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
var templateName = rs[names[0]].AsString();
if (!String.IsNullOrEmpty(templateName))
{
return TemplateManager.LoadTemplate(templateName);
}
return null;
}
}
Okay, so far so good. But the problem is, how can I use Template property in Linq queries?
For exmaple:
var pages = session.Query<Page>().Where(it => it.Template.Name == "MyTemplate");
I think the solution might be to write a class (say TemplatePropertyHqlGenerator) implementing IHqlGeneratorForProperty. This is the linq query extension point provided by NHibernate 3. But how to write this TemplatePropertyHqlGenerator class?
Thanks in advanced!
The IUserType interface lets you define a type which is considered atomic. That is to say, you can then perform direct comparisons between instances of the type and NHibernate will know how to translate them.
E.g. the following query would evaluate:
var template = new Template();
session.Query<Page>().Where(it => it.Template == template);
If you want to define a type which has component values which you can then manipulate, you need to implement the ICompositeUserType interface. This interface requires you define the properties of the type as atomic elements, giving NHibernate the information it needs to understand the specific properties of the type.
As a result, it's a little more complex than IUserType to implement, but it should facilitate what you want to achieve.
Here's an understandable example of implementing the interface for a Money type: http://geekswithblogs.net/opiesblog/archive/2006/08/05/87218.aspx

Can Ninject resolve abstract dependencies after the object is initialised?

Does anyone know if it's possible to use Ninject to resolve any unresolved abstract dependencies outside of the instantiation process? I've just been looking into constructor injection vs property/method/field injection, but it looks to me as though Ninject is still expecting to be the creator of the type using the IKernel.Get<>() method.
Basically, we're using MVC3 to build our product, and we've come up against a situation where we want the default ModelBinder to map form values to an instance of the object, and then be able to call a method on the submitted ViewModel that is dependent on an abstract interface e.g.
public class InviteFriend {
[Required]
public string EmailAddress { get; set; }
public void Execute() {
var user = IUserRepository.GetUser(this.EmailAddress);
if (user == null) {
IUserRepository.SaveInvite(this.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
SmtpClient.Send(toSend);
}
}
where the controller action would receive InviteFriend as the method argument. We want Ninject to be able to resolve that IUserRepository dependency, but I can't quite work out how to since the object itself is instantiated by the MVC ModelBinder rather than Ninject IKernel.Get<>().
Maybe the solution is a Ninject-based ModelBinder, or does that seem a really bad idea?
EDIT TO ADD: After the comments below, I realise that my hastily mocked-up code sample doesn't really reflect what we're facing. I've updated the code sample to reflect that the logic for InviteFriend.Execute() is more complex than just calling a method on one repository. Potentially, this is logic representing a discrete task that could co-ordinate interactions between multiple different domain objects and multiple repositories. The repositories are defined abstractly, and ideally would be resolved by Ninject.
I think what you are looking for is somewhat the following scenario:
public class InviteFriend {
[Required]
public string EmailAddress { get; set; }
// More information
}
public interface ICommand {
void Execute();
}
public class InviteFriendCommand : ICommand
{
public InviteFriend(InviteFriend info, IUserRepository userRepo, IMailSender mailSender) {
this.inviteFriend = info;
this.userRepo = userRepo;
this.mailSender = mailSender;
}
public void Execute() {
var user = this.userRepo.GetUser(this.inviteFriend.EmailAddress);
if (user == null) {
this.userRepo.SaveInvite(this.inviteFriend.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
this.mailSender.Send(toSend);
}
}
public interface ICommandFactory {
ICommand CreateInviteFriendCommand(InviteFriend info);
}
public class CommandFactory {
public CommandFactory(IResolutionRoot resolutionRoot) {
this.resolutionRoot = resolutionRoot;
}
ICommand CreateInviteFriendCommand(InviteFriend info) {
this.resolutionRoot.Get<InviteFriendCommand>(new ConstructorArgument("info", info));
}
}
public class YourController {
// Somewhere
var command = this.commandFactory.CreateInviteFriendCommand(info);
command.Execute();
}
public class YourModule : NinjectModule {
override Load() {
Bind<IUserRepository>().To<UserRepo>().InRequestScope();
Bind<ICommandFactory>().To<CommandFactory>().InRequestScope();
Bind<InviteFriendCommand>().ToSelf().InRequestScope();
}
}
Forgive me when you need to tweak it a bit. I hacked it together with my out of brain compiler ;)
Thank you for all your comments, but I've subsequently found the information I was looking for.
The answer is that it is possible to inject dependencies post-instantiation with Ninject. The solution is as follows:
public class InviteFriend {
[Inject]
public IUserRepository UserRepo { get; set; }
[Required]
public string EmailAddress { get; set; }
public void Execute() {
var user = UserRepo.GetUser(this.EmailAddress);
if (user == null) {
UserRepo.SaveInvite(this.EmailAddress);
}
MailMessage toSend = new MailMessage(); // Obviously some logic to prepare the body, subject and other mail properties
SmtpClient.Send(toSend);
}
}
With client code then using the Ninject kernel as follows:
IKernel container = new StandardKernel(new ModuleWithMyBindings());
container.Inject(instanceOfInviteFriend);
The code itself is a bit more sophisticated than that i.e. I'm not instantiating a new IKernel each time I need it.
I realise that this is architecturally less pure than some of the suggestions put forward in comments, but in the spirit of YAGNI, this is good enough for now and we can always refactor later on with some of the good suggestions in Daniel's answer. However, this was a question about the capabilities of Ninject rather than an architectural review question, and this is what I consider the answer to my own question :)

Resources