Factory pattern with 4 layer architecture - c#

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.

Related

Generic type parameters C# - How to generic class return type

Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();

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>;
}
}

Generic Abstract Method

I ran into trouble when trying to create an abstract class and a method in it that was generic in nature.
class GameRoomManager : MonoBehaviour {
public GameRoom GetSomething(string s){
//do things here
return GameRoomvar;
}
}
Now I have another class that does something similar, but different classes involved
class PlayerManager : MonoBehaviour{
public Player GetSomething(string s){
//player related things here
return Playervar;
}
}
I want to have both classes GameRoomManager and PlayerManager inherit from an abstract class Abs
class GameRoomManager : Abs{
public override GameRoom GetSomething<GameRoom>(string s){
return GameRoomvar;
}
}
where
public abstract class Abs{
public T GetSomething<T>(string s);
}
I've seen a few answers on this topic when I was looking for solutions, and all suggested the abstract class itself be generic. I don't want to make the abstract class generic, since examples I saw would have me do class GameRoomManager : Abs<GameRoomManager>. But I want the method to return type GameRoom, not GameRoomManager.
I'm not totally familiar with generics, so please point me in the right direction if I'm going wrong
You have to have something in common with PQR and HIJ for the classes to use a common method.
Plan A
Connect things with interfaces.
public interface IPart
{
// put things here that are common between Part and GameRoom
int ID { get; }
}
public interface IAbs
{
IPart GetSomething(string name);
}
public class GameRoom : IPart
{
public int ID { get; set; }
}
public class GameRoomManager : IAbs
{
GameRoom part;
#region IAbs Members
public GameRoom GetSomething(string name)
{
return part;
}
IPart IAbs.GetSomething(string name)
{
return GetSomething(name);
}
#endregion
}
public class Player : IPart
{
public int ID { get; set; }
}
public class PlayerManager : IAbs
{
Player part;
#region IAbs Members
public Player GetSomething(string name)
{
return part;
}
IPart IAbs.GetSomething(string name)
{
return GetSomething(name);
}
#endregion
}
Plan B
Use a base class with a generic type & interfaces
public interface IItem
{
// put things here that are common between Part and GameRoom
int ID { get; }
}
public class GameRoom : IItem
{
public int ID { get; set; }
}
public class Player : IItem
{
public int ID { get; set; }
}
public interface IAbs
{
IItem GetItem(string guid);
}
public abstract class Abs<T> : IAbs
where T : IItem
{
protected abstract T GetItem(string name);
protected Abs(T item)
{
this.Item=item;
}
protected T Item { get; private set; }
#region IAbs Members
IItem IAbs.GetItem(string name)
{
return GetItem(name);
}
#endregion
}
public class GameRoomManager : Abs<GameRoom>
{
public GameRoomManager(GameRoom room) : base(room)
{
}
protected override GameRoom GetItem(string guid)
{
return Item;
}
public GameRoom GetRoom(string guid) { return GetItem(guid); }
}
public class PlayerManager : Abs<Player>
{
public PlayerManager(Player player)
: base(player)
{
}
protected override Player GetItem(string guid)
{
return Item;
}
public Player GetPlayer(string guid) { return GetItem(guid); }
}
here is some example usage:
class Program
{
static void Main(string[] args)
{
List<IAbs> managers=new List<IAbs>();
var pm=new PlayerManager(new Player() { ID=1001 });
var gm=new GameRoomManager(new GameRoom() { ID=2050 });
managers.Add(pm);
managers.Add(gm);
IItem part = managers[0].GetItem("0000");
}
}

C# Create Instance of Generic class which inheritance from base

I'm trying to create instance of class Bar but I'm receiving an error:
"Cannot implicitly convert type ConsoleApplication1.Bar to
ConsoleApplication1.BaseFoo<ConsoleApplication1.baseOutput,
ConsoleApplication1.baseInput>"
Any idea what I'm missing or what I'm doing wrong? Any advice will be nice.
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public class BaseFoo<baseOutput, baseInput>
{
protected virtual void DoSmth()
{
}
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
protected override void DoSmth()
{
base.DoSmth();
}
}
public class Test
{
public void Show()
{
}
private BaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar(); // Error right here
}
}
I'll give you an example of why you're prevented from doing that.
Imagine instead, your classes were written like this:
public class BaseFoo<TOutput, TInput>
where TOutput : BaseOutput
{
public TOutput Something { get; set; }
}
public class Bar : BaseFoo<ExtendOutput, ExtendInput>
{
}
public class BaseInput { }
public class BaseOutput { }
public class ExtendOutput : BaseOutput { }
public class SomethingElse : BaseOutput { }
Now, you have this method:
private BaseFoo<BaseOutput, BaseInput> CreateInstance()
{
//At this point, Something will be of type ExtendOutput.
return new Bar();
}
So, we call it like this:
var myBar = CreateInstance();
Now, mybar.Something is of type BaseOutput. That's fine, though, because ExtendOutput : BaseOutput, right? Not quite.
What happens when we do this:
myBar.Something = new SomethingElse();
That's valid, because Something expects a BaseOutput, and SomethingElse is a BaseOutput. However, the object is actually a Bar, which explicitly says it should be an ExtendOutput.
The problem is clearer if we attempt to cast it back:
var myBaseFoo = CreateInstance();
myBaseFoo.Something = new SomethingElse();
Bar myBar = (Bar)myBaseFoo;
myBar.Something; // Here, we're told it's going to be an `ExtendOutput`,
// but we get a `SomethingElse`?
That's clearly wrong. And that's why you're prevented from doing what you're trying to do. You can have this behavior with covariance.
Covariance makes it illegal to pass in a TOutput. So, this line
public TOutput Something { get; set; }
Would be invalid. We would only be allowed to expose the getter:
public TOutput Something { get; }
Which alleviates the above problem
Bar is BaseFoo<ExtendOutput, ExtendInput>, and CreateInstance() requires BaseFoo<baseOutput, baseInput> to be returned, so it can't return Bar which is BaseFoo<ExtendOutput, ExtendInput>.
Regardless ExtendOutput inherits baseOutput, when you inherit a generic class the inheritance is invariant.
Consider using interfaces with in and out generic modifiers:
public class baseOutput
{
public string output;
}
public class baseInput
{
public string input;
}
public class ExtendOutput : baseOutput
{
public long id;
}
public class ExtendInput : baseInput
{
public long id;
}
public interface IBaseFoo<out T1, out T2>
{
public void DoSmth();
}
public class Bar : IBaseFoo<ExtendOutput, ExtendInput>
{
public void DoSmth()
{
}
}
public class Test
{
public void Show()
{
}
private IBaseFoo<baseOutput, baseInput> CreateInstance()
{
return new Bar();
}
}

Injecting multiple matching classes with structuremap

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));
}

Categories

Resources