Injecting multiple matching classes with structuremap - c#

interface IRecipe<T>
{
ICollection<IIngredient<T>> Ingredients { get; set; }
T Cook();
}
interface IIngredient<T> {}
public class Cheese : IIngredient<Pizza> {}
public class Tomato : IIngredient<Pizza> {}
public class Egg : IIngredient<Omlette> {}
I want that when I request an instance of IRecipe<SomeType> StructureMap finds all implementations of IIngredient<SomeType> and registers them with Recipe somehow.
So e.g. if I request interface IRecipe<Pizza> I will get concrete instance of Recipe<Pizza> that has the correct ingredients.
Is there any way to achieve this?

Yes this can be done with StructureMap.
I've made ICollection<IIngredient<T>> Ingredients readonly, added concrete implementations of Pizza and Omlette and extended Cheese and Tomato to be available for both Recipe's
public class Pizza { }
public class Omlette { }
public class Recipe<T> : IRecipe<T> where T : class, new()
{
private readonly IEnumerable<IIngredient<T>> _ingredients;
public Recipe(IEnumerable<IIngredient<T>> ingredients)
{
_ingredients = ingredients;
}
public ICollection<IIngredient<T>> Ingredients
{
get { return _ingredients.ToList(); }
}
public T Cook()
{
return new T();
}
}
public interface IRecipe<T>
{
ICollection<IIngredient<T>> Ingredients { get; }
T Cook();
}
public interface IIngredient<T> { }
public class Cheese : IIngredient<Pizza>, IIngredient<Omlette> { }
public class Tomato : IIngredient<Pizza>, IIngredient<Omlette> { }
public class Egg : IIngredient<Omlette> { }
Here's the method for registration
public StructureMap.IContainer ConfigureStructureMap()
{
StructureMap.IContainer structureMap;
StructureMap.Configuration.DSL.Registry registry =
new StructureMap.Configuration.DSL.Registry();
registry.Scan(scanner =>
{
scanner.TheCallingAssembly();
scanner.ConnectImplementationsToTypesClosing(typeof(IIngredient<>));
});
structureMap = new StructureMap.Container(registry);
structureMap.Configure(cfg =>
cfg.For(typeof(IRecipe<>)).Use(typeof(Recipe<>)));
return structureMap;
}
And two test methods
[Test]
public void StructureMapGetInstance_Pizza_ReturnsTwoIngredients()
{
StructureMap.IContainer structureMap = ConfigureStructureMap();
var pizza = structureMap.GetInstance<IRecipe<Pizza>>();
Assert.That(pizza.Ingredients.Count, Is.EqualTo(2));
}
[Test]
public void StructureMapGetInstance_Omlette_ReturnsThreeIngredients()
{
StructureMap.IContainer structureMap = ConfigureStructureMap();
var omlette = structureMap.GetInstance<IRecipe<Omlette>>();
Assert.That(omlette.Ingredients.Count, Is.EqualTo(3));
}

Related

How do I fix a proxy when the base interfaces are not shared?

I have inherited a project that has a ton of duplicate Repositories and duplicate Units of Work objects. For instance:
namespace MyProject.Domain.Plant.Repositories
{
public interface IPlantEmployeeRepository : IRepository<Employee>
{
}
}
namespace MyProject.Domain.Plant.UnitOfWorks
{
public interface IPlantUnitOfWork : Common.IUnitOfWork
{
public IPlantEmployeeRepository EmployeeRepository { get; }
public IPlantEmployeeFacilityRepository EmployeeFacilityRepository { get; }
// ...
}
}
namespace MyProject.Infrastructure.Persistence.Plant.Repositories
{
public class PlantEmployeeRepository : Repository<Employee>, IPlantEmployeeRepository
{
public PlantEmployeeRepository(PlantContext context) : base(context)
{
}
}
}
namespace MyProject.Infrastructure.Persistence.Plant.UnitOfWorks
{
public class PlantUnitOfWork : UnitOfWork, IPlantUnitOfWork
{
public IPlantEmployeeRepository EmployeeRepository => ServiceProvider.GetService<IPlantEmployeeRepository>();
public IPlantEmployeeFacilityRepository EmployeeFacilityRepository => ServiceProvider.GetService<IPlantEmployeeFacilityRepository>();
// ...
public PlantUnitOfWork(PlantContext context, IServiceProvider serviceProvider) : base (context, serviceProvider) { }
}
}
// ----------------------------------------------------------------------------------------------
namespace MyProject.Domain.Garage.Repositories
{
public interface IGarageEmployeeRepository : IRepository<Employee>
{
}
}
namespace MyProject.Domain.Garage.UnitOfWorks
{
public interface IGarageUnitOfWork : Common.IUnitOfWork
{
public IGarageEmployeeRepository EmployeeRepository { get; }
public IGarageEmployeeFacilityRepository EmployeeFacilityRepository { get; }
// ...
}
}
namespace MyProject.Infrastructure.Persistence.Garage.Repositories
{
public class GarageEmployeeRepository : Repository<Employee>, IGarageEmployeeRepository
{
public GarageEmployeeRepository(GarageContext context) : base(context)
{
}
}
}
namespace MyProject.Infrastructure.Persistence.Garage.UnitOfWorks
{
public class GarageUnitOfWork : UnitOfWork, IGarageUnitOfWork
{
public IGarageEmployeeRepository EmployeeRepository => ServiceProvider.GetService<IGarageEmployeeRepository>();
public IGarageEmployeeFacilityRepository EmployeeFacilityRepository => ServiceProvider.GetService<IGarageEmployeeFacilityRepository>();
// ...
public GarageUnitOfWork(GarageContext context, IServiceProvider serviceProvider) : base (context, serviceProvider) { }
}
}
Yes - there is no conceptual difference between these 2 representations of the DB. Both address the Employee, EmployeeFacility and other Employee related DB tables. There is no contexual boundaries, no root aggregates, no values and nothing else DDD related except the UoWs and Repositories.
Now, my plan was to create proxy objects that wrapped the UoW/Repositories. II am trying to write a single set of code that does the exact same thing on any collection of Employees, be it the Plant or the Garage or Corporate, etc.
namespace MyProject.Application.Engine.Zone.Proxies
{
public abstract class BaseProxy : IZoneProxyUnitOfWork
{
public IUnitOfWork UnitOfWork { get; internal set; }
public IRepository<IEmployee> RepositoryEmployee { get; internal set; }
public IRepository<IEmployeeFacility> RepositoryEmployeeFacility { get; internal set; }
// ...
}
public class PlantUnitOfWorkProxy : BaseProxy
{
public PlantUnitOfWorkProxy(IPlantUnitOfWork plantUnitOfWork)
{
UnitOfWork = plantUnitOfWork;
RepositoryEmployee = (IRepository<IEmployee>)plantUnitOfWork.EmployeeRepository;
RepositoryEmployeeFacility = (IRepository<IEmployeeFacility>)plantUnitOfWork.EmployeeFacilityRepository;
// ...
}
}
public class GarageUnitOfWorkProxy : BaseProxy
{
public GarageUnitOfWorkProxy(IGarageUnitOfWork garageUnitOfWork)
{
UnitOfWork = garageUnitOfWork;
RepositoryEmployee = (IRepository<IEmployee>)garageUnitOfWork.EmployeeRepository;
RepositoryEmployeeFacility = (IRepository<IEmployeeFacility>)garageUnitOfWork.EmployeeFacilityRepository;
// ...
}
}
}
However, while all of this actually compiles the proxies will not initialize. Conversion from IPlantEmployeeRepository EmployeeRepository to IRepository<IEmployee> RepositoryEmployee is failing (which makes sense). However, my brain is broken enough now that fixing this is putting me in a tailspin: mainly trying to keep track of all the interfaces and how they are being used.
I will say this is a .NET Core solution utilizing C# though I don't think language is the really important here. Just humbly asking for some help.

c# change GET implementation get<typed>() to get()

I have some problem I can not resolve.
I have a class GlobalTest derived from GlobalObjectImpl:
public class GlobalTest : GlobalObjectImpl
{
public string LastProcessDay { get; set; }
}
It was called from this:
var global = GlobalTest.Get<GlobalTest>();
The GlobalObjectImpl is declared like this:
public abstract class GlobalObjectImpl
{
public bool Save()
{
return DataStore.SaveGlobal(this);
}
public static T Get<T>() where T : GlobalObjectImpl
{
return DataStore.GetGlobal<T>();
}
}
I want to get my LastProceedDate like this:
var global = GlobalTest.Get();
But it fails.
You can make your abstract class generic like the following:
public abstract class Base<T>
{
public static T Get() => throw new NotImplementedException();
}
public class Derived : Base<Derived> { }
And then just call Get
var foo = Derived.Get();
I all, big thank to you, i have succesfully implemented my class
My Abstract Class
public abstract class GlobalTreeObjectImpl<T>
{
public bool Save()
{
return NeoStore.SaveGlobal(this);
}
public static T Get() => NeoStore.GetGlobal<T>();
}
}
Class use abstract class
public class GlobalTest : GlobalTreeObjectImpl<GlobalAntai>
{
public string LastProcessDay { get; set; }
}
Usage of this on my code
var global = GlobalTest.Get();
LoggerManager.LogInfo($"Global LastProcessDay : {global.LastProcessDay} - {DateTime.UtcNow}");
global.LastProcessDay = DateTime.Now.AddDays(10).ToString("yyyy-MM-ddThhh:mmm:ssZ");
global.Save();
global = GlobalTest.Get();
LoggerManager.LogInfo($"Global LastProcessDay : {global.LastProcessDay} - {DateTime.UtcNow}");

Implement an interface method with a concrete class

I have the following interfaces, one for the entity and one for some logic:
public interface IItem
{
int Id { get; set; }
}
public interface IGenerator
{
IList<IItem> Generate();
}
and implementation:
public class ItemA : IItem
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ItemAGenerator : IGenerator
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}
That implementation did not work, it says that it does not have the matching return type, so I also tried:
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
// do stuff
return List<ItemA>;
}
}
it does not work as well, it says: cannot implicitly convert type List<IItem> to List<ItemA>.
How to make it work? what am I missing here.
Just create the list as a List<IItem> but add ItemA's to it.
public class ItemAGenerator : IGenerator
{
public IList<IItem> Generate()
{
var list = new List<IItem>();
list.Add(new ItemA());
return list;
}
}
Just make IGenerator generic. Then you can specify the type that will be returned.
public interface IGenerator<T> where T : IItem
{
IList<T> Generate();
}
public class ItemAGenerator : IGenerator<ItemA>
{
public IList<ItemA> Generate()
{
// do stuff
return List<ItemA>;
}
}

Inherit from generic type as interface

I am attempting to do something similar to:
public interface IView<T> : T where T : class
{
T SomeParam {get;}
}
So that i can later do
public class SomeView : IView<ISomeView>
{
}
Is it possible to specify inheritance using generics in this way or do i have to go the long way round and explicitly specify both interfaces when defining the class and do:
public interface IView<T>
{
T SomeParam {get;}
}
public class SomeView : IView<ISomeView>, ISomeView
{
}
This isn't possible, but your goal may be achievable with conversion operators. It seems that what you're trying to do is make it possible to pass an IView<T> as the T object which it contains. You could write a base class like this:
public abstract class ViewBase<T> {
public abstract T SomeParam { get; }
public static implicit operator T(ViewBase<T> view) {
return view.SomeParam;
}
}
Then, if you define a class like:
public class SomeView : ViewBase<ISomeView> { }
It can be accepted anywhere an ISomeView is expected:
ISomeView view = new SomeView();
Short answer: It is not possible. See this post
An Interface can't derive from a class. However nothing prevent you from doing this:
public interface ISomeView
{
}
public interface IView<out T> where T:class
{
T SomeParam { get; }
}
public class SomeView:IView<ISomeView>
{
public ISomeView SomeParam { get; set; }
}
Edit:
If you don't want to implement the T SomeParam { get; } each time you need to have an implementation, Does this would work?
public interface ISomeView
{
}
public abstract class BaseView<T> where T : class
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<ISomeView>{
}
In both case this would work:
public class main
{
public class OneOfThoseView : ISomeView
{
}
public main()
{
OneOfThoseView oneOfThose = new OneOfThoseView();
SomeView x = new SomeView();
x.SomeParam = oneOfThose;
}
}
Edit 2:
Not exactly what you want to do but this would force your SomeView class to return a BaseView<SomeView> class
public interface ISomeView
{
}
public abstract class BaseView<T> where T : BaseView<T>
{
public T SomeParam { get; set; }
}
public class SomeView : BaseView<SomeView>
{
}
Now only this would work.
public main()
{
SomeView y= new SomeView ();
SomeView x = new SomeView();
x.SomeParam = y;
}

Factory pattern with 4 layer architecture

In my project i have 4 layers presentation,BL,DL, and dataObjects. i want to implement abstract factory pattern to get the object i want(doctor/Engineer). Is the code below implementing factory pattern?
public interface IProfessional //The Abstract Factory interface.
{
IProfession CreateObj();
}
// The Concrete Factory class1.
public class DocFactory : IProfessional
{
public IProfession CreateObj()
{
return new Doctor();
}
}
// The Concrete Factory class2.
public class EngFactory : IProfessional
{
public IProfession CreateObj()
{
// IMPLEMENT YOUR LOGIC
return new Engineer();
}
}
// The Abstract Item class
public interface IProfession
{
}
// The Item class.
public class Doctor : IProfession
{
public int MedicalSpecialty
{
get; set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Item class.
public class Engineer : IProfession
{
public string Title{
get;set;
}
public int AreaofExpertise
{
get; set;
}
}
// The Client class.
public class AssignProfession
{
private IProfession _data;
public AssignProfession(DataType dataType)
{
IProfessional factory;
switch (dataType)
{
case DataType.Doc:
factory = new EngFactory();
_data = factory.CreateObj();//from here i will get engineer
break;
case DataType.Eng:
factory = new DocFactory();
_data = factory.CreateObj();//from here i will get doctor
break;
}
}
public IProfession GiveProfessional()
{
return _data;
}
}
//The DataType enumeration.
public enum DataType
{
Doc,
Eng
}
Your code does implement the pattern but not to the full extent which C# allows, in other words - you are not using the important benefits of the C# language.
Here is an example of how you can do it better:
class Program
{
static void Main(string[] args)
{
var myEngineer = ProfessionFactory.CreateProffession<Engineer>();
var myDoctor = ProfessionFactory.CreateProffession<Doctor>();
myEngineer.EnginerringStuff();
myDoctor.HealingPeople();
var myEngineer2 = (Engineer)ProfessionFactory.CreateProffession("Engineer");
//using the other method I still have to cast in order to access Engineer methods.
//therefore knowing what type to create is essential unless we don't care about engineer specific methods,
//in that case we can do:
var myEngineer3 = ProfessionFactory.CreateProffession("Engineer");
//which is useless unless we start involving reflections which will have its own price..
}
public interface IProfessionFactory
{
IProfession CreateObj();
}
public interface IProfession : IProfessionFactory
{
string ProfessionName { get; }
}
public abstract class ProfessionFactory : IProfessionFactory
{
public abstract IProfession CreateObj();
public static T CreateProffession<T>() where T:IProfessionFactory, new()
{
return (T)new T().CreateObj();
}
public static IProfession CreateProffession(object dataObj)
{
if (dataObj == "Engineer")
return CreateProffession<Engineer>();
if (dataObj == "Doctor")
return CreateProffession<Doctor>();
throw new Exception("Not Implemented!");
}
}
public class Engineer : IProfession
{
public string ProfessionName
{
get { return "Engineer"; }
}
public IProfession CreateObj()
{
return new Engineer();
}
public void EnginerringStuff()
{}
}
public class Doctor : IProfession
{
public string ProfessionName
{
get { return "Doctor"; }
}
public IProfession CreateObj()
{
return new Doctor();
}
public void HealingPeople()
{}
}
}
It does seem to have all elements of the pattern, however your IProfession is empty. I am going to assume that is just a placeholder and you are going to fill it in with some methods that represent a behavior that is common to all professions.
Contrast that with the example given in Allen Holub's book
He mentions Collection as the AbstractFactory, Iterator as the abstract product, Tree as the concrete factory and the iterators that are returned as concrete products.

Categories

Resources