Refactor factory without violating Open Close Principle - c#

I have two versions of a factory class designed based on the article
http://www.oodesign.com/factory-pattern.html
public abstract class Employee
{
public string Name { get; set; }
protected string Role { get; set; }
public abstract string GetRole();
}
public class Manager : Employee
{
public Manager()
{
Role = "MGR";
}
public override string GetRole()
{
return this.Role;
}
}
Version 1: Simple, Violates Open Close Principle
Need to change SimpleEmployeeFactory every time, when I add a new concrete class
public class SimpleEmployeeFactory
{
public static Employee GetEmployee(int typeId)
{
switch (typeId)
{
case 1:
return new Manager();
case 2:
return new TechnicalLead();
default:
return null; //if the id doesn't have any
}
}
}
Version 2:
Refactored Factory, still needs a Concrete Class creation, before we use factory call
public abstract class Employee
{
public string Name { get; set; }
protected string Role { get; set; }
public abstract string GetRole();
public abstract Employee createEmployee();
}
public class ChiefTechnologyOfficer : Employee
{
public ChiefTechnologyOfficer()
{
this.Role = "CTO";
}
static ChiefTechnologyOfficer()
{
RefactoredFactory.Instance.registerEmployee(5, new ChiefTechnologyOfficer());
}
public override string GetRole()
{
return this.Role;
}
public override Employee createEmployee()
{
return new ChiefTechnologyOfficer();
}
}
Factory
class RefactoredFactory
{
private static readonly RefactoredFactory instance = new RefactoredFactory();
static RefactoredFactory()
{
}
private RefactoredFactory()
{
}
public static RefactoredFactory Instance
{
get
{
return instance;
}
}
private Dictionary<int, Employee> registeredEmployees = new Dictionary<int, Employee>();
public void registerEmployee(int typeId, Employee employeeInst)
{
registeredEmployees.Add(typeId, employeeInst);
}
public Employee createEmployee(int typeId)
{
return ((Employee)registeredEmployees[typeId]).createEmployee();
}
}
Client
Employee emp = SimpleEmployeeFactory.GetEmployee(1);
Activator.CreateInstance(typeof(ChiefTechnologyOfficer)); //Avoid
Employee empFNoR = RefactoredFactory.Instance.createEmployee(5);
You can see Activator.CreateInstance(typeof(ChiefTechnologyOfficer)) call to make the concrete classes to register themselves with the Factory. Otherwise we cant retrieve the object
Is there a way to create a Factory class with out violating OCP principle & with out creating an object like the one I used in RefactoredFactory class?

It looks like the typeId suffers from Feature Envy. Instead, define a polymorphic type to capture the type; e.g. an interface:
public interface IEmployeeType
{
Employee Create()
}
Now you can define e.g. a ManagerType, and a TechnicalLeadType, etc. Example:
public class ManagerType : IEmployeeType
{
public Employee Create()
{
return new Manager();
}
}
This is essentially an Abstract Factory, and it has the advantage that you can always create a new implementation when you need to create a new sub-type.
If you're at the boundary of a system, and must translate a primitive value like an integer to a polymorphic value, you can use one of the Role Hint patterns - particularly Metadata, Role Interface, or (my favourite) Partial Type Name.
Client
Given an IEmployeeType instance employeeType, a client would simply go:
Employee emp = employeeType.Create();

Thala,
Instead of using static constructor,register method to populate dictionary of Types.
You can use config based solution like .net DbProviderFactory, to register all types.
<EmployeeFactories>
<add name="manger" type="Manager, EmployeeAssmbly" />
..
</EmployeeFactories>

Related

C# how to "register" class "plug-ins" into a service class? - As of today

6 Years have passed since this question was made and I was expecting to have an easy solution today.. but seems not.
NOTE: please read the other question to understand the concept:
After a few minutes I tried to implement an easy example and I've almost accomplished it. Meanwhile I still see some problems. And I was wondering if someone has ideas on how to make it better.
Using .NET 6 (code bellow).
Issue 1: I don't like the fact that the generics where we say, use TTarget as User, we also need to pass the T ID type.... why by passing User is not enought for the compiler to know the ID data type? Example: class UserService : IBaseDBOperation1<User, Guid> why not class UserService : IBaseDBOperation1<User> ?
Issue 2: I understand that now we are allowed to have interfaces with methods with code, but why do we still need to define the variable type exactly with both data types and using var is not enough? Well, we can use var, but then the methods are not visible.
instead of: IBaseDBOperation1<User, Guid> serviceU1 = new UserService(); ........ var serviceU2 = new UserService(); ...... this second variable will not see the other methods.
Final note: Everything would be so much easier if C# would allow us to extend a class with more than one other abstract class.... (as of today we are limited to 1).
Objective: Accomplish what was asked in the question made 6 years ago.... in other words.... avoid copy/paste, and somehow "inject/associate/register/define" more than one "operation class" into a service.... those "operation classes" will be reused a lot in multiple different services.... and I do want to have a "clean/pretty" way of setting this up, but at the same time, the consumer should not worry about "lower/deeper "lever inheritance generics.
Code
public abstract class BaseDBEntry<T> where T : struct
{
protected BaseDBEntry()
{
CreatedOn = DateTime.Now;
}
public T Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? DeletedOn { get; set; }
}
public class User : BaseDBEntry<Guid>
{
public User() { Id = Guid.NewGuid(); }
public string Name { get; set; }
}
public class Color : BaseDBEntry<long>
{
public Color() { Id = DateTime.Now.Ticks; }
public string RGB { get; set; }
}
Services
public interface IBaseDBOperation1<in TTarget, out T>
where TTarget : BaseDBEntry<T> where T : struct
{
public bool IsValid(TTarget model) { return true; }
T GiveMeId(TTarget model) { return model.Id; }
}
public interface IBaseDBOperation2<in TTarget, T>
where TTarget : BaseDBEntry<T> where T : struct
{
public bool IsValidToDoSomethingElse(TTarget model) { return false; }
}
public class UserService : IBaseDBOperation1<User, Guid>, IBaseDBOperation2<User, Guid> { }
public class ColorService : IBaseDBOperation1<Color, long>, IBaseDBOperation2<Color, long> { }
Consumer
public class Consumer
{
public void Run()
{
IBaseDBOperation1<User, Guid> serviceU1 = new UserService();
IBaseDBOperation2<User, Guid> serviceU2 = new UserService();
var u = new User { Name = "Carl" };
var resU1 = serviceU1.IsValid(u);
var resU2 = serviceU1.GiveMeId(u);
var resU3 = serviceU2.IsValidToDoSomethingElse(u);
var serviceU3 = new UserService();
//serviceU3.XXXXX() --> has no information about the methods we need
IBaseDBOperation2<Color, long> serviceC1 = new ColorService();
var c = new Color { RGB = "#FFFFFF" };
var resC1 = serviceC1.IsValidToDoSomethingElse(c);
var adasda = "";
}
}
var consumer = new Consumer();
consumer.Run();
I will start with small remark - please try to follow standard naming conventions, in this case this one:
Interface names start with a capital I.
As for the issues:
Issue 1: I don't like the fact that the generics where we say, use TTarget as User, we also need to pass the T ID type.
Not much has changed here for the last 6 years, interface BaseDBOperation1<TTarget, T>.. still requires 2 generic type parameters and you can still have an interface with one type parameter, i.e. interface BaseDBOperation1<TTarget> which will be ambiguous for the compiler (so adding interface BaseDBOperation1<TTarget> will become a breaking change, which is a concern if those classes are distributed as library).
Possibly something like this could be achieved with something like higher-kinded types or similar language feature but ATM it is not available in C#.
Related issues to track:
First-class generic method / First-class polymorphism / Rank-N types
Higher Kinded Polymorphism / Generics on Generics
"Opaque" parameters
Existential types for interfaces and abstract types
partial type inference
Issue 2: ... this second variable will not see the other methods.
This is by design (default interface methods draft spec):
Note that a class does not inherit members from its interfaces; that is not changed by this feature:
interface IA
{
void M() { WriteLine("IA.M"); }
}
class C : IA { } // OK
new C().M(); // error: class 'C' does not contain a member 'M'
In order to call any method declared and implemented in the interface, the variable must be the type of the interface
i.e. for var serviceU2 = new UserService(); you will need to cast to corresponding interface:
var resU1 = ((BaseDBOperation1<User, Guid>)serviceU2).IsValid(u);
Another reason for such behaviour can be similar to the so called brittle/fragile base class problem.
Personally I'm not a big fan of this feature both conceptually and due to some corner cases (for example this one).
As for an approach to implement such functionality and reducing code written manually (if you have A LOT of such repositories) - you can look at some compile time code generation with source generators but this is not definitely an easy option. At least for the first time.
Would the following work for you? Essentially making the User and the Color the holder of the service operations.
https://dotnetfiddle.net/zsjZfQ
using System;
var user = new User();
var color = new Color();
Console.WriteLine(user.DbOperation1.IsValid());
Console.WriteLine(user.DbOperation2.IsValidToDoSomethingElse());
Console.WriteLine(user.DbOperation3.ThisIsOnlyAvailableToSome());
Console.WriteLine(color.DbOperation1.IsValid());
Console.WriteLine(color.DbOperation2.IsValidToDoSomethingElse());
var userAsBaseDbEntry = (BaseDBEntry<Guid>)user;
Console.WriteLine(userAsBaseDbEntry.DbOperation1.IsValid());
Console.WriteLine(userAsBaseDbEntry.DbOperation2.IsValidToDoSomethingElse());
public abstract class BaseDBEntry<T> where T : struct
{
public abstract IDbOperation1<T> DbOperation1 { get; init; }
public abstract IDbOperation2<T> DbOperation2 { get; init; }
public T Id { get; init; }
public DateTime CreatedOn { get; init; } = DateTime.Now;
public DateTime? DeletedOn { get; init; }
}
public class User : BaseDBEntry<Guid>
{
public string Name { get; init; }
override public sealed IDbOperation1<Guid> DbOperation1 { get; init; }
override public sealed IDbOperation2<Guid> DbOperation2 { get; init; }
public IDbOperation3 DbOperation3 { get; }
public User()
{
DbOperation1 = new DbOperation1Impl<Guid>(this);
DbOperation2 = new DbOperation2Impl<Guid>(this);
DbOperation3 = new DbOperation3Impl(this);
Id = Guid.NewGuid();
}
}
public interface IDbOperation3
{
bool ThisIsOnlyAvailableToSome();
}
public class DbOperation3Impl : IDbOperation3
{
private readonly BaseDBEntry<Guid> _entry;
public DbOperation3Impl(BaseDBEntry<Guid> entry)
{
_entry = entry;
}
public bool ThisIsOnlyAvailableToSome() => !_entry.DbOperation1.IsValid();
}
public class Color : BaseDBEntry<long>
{
override public sealed IDbOperation1<long> DbOperation1 { get; init; }
override public sealed IDbOperation2<long> DbOperation2 { get; init; }
public string Rgb { get; init; }
public Color()
{
DbOperation1 = new DbOperation1Impl<long>(this);
DbOperation2 = new DbOperation2Impl<long>(this);
Id = DateTime.Now.Ticks;
}
}
public interface IDbOperation1<T> where T : struct
{
bool IsValid();
}
public interface IDbOperation2<T> where T : struct
{
bool IsValidToDoSomethingElse();
}
class DbOperation1Impl<T> : IDbOperation1<T> where T : struct
{
private readonly BaseDBEntry<T> _entry;
public DbOperation1Impl(BaseDBEntry<T> entry)
{
_entry = entry;
}
public bool IsValid() => _entry.CreatedOn < DateTime.Now;
}
class DbOperation2Impl<T> : IDbOperation2<T> where T : struct
{
private readonly BaseDBEntry<T> _entry;
public DbOperation2Impl(BaseDBEntry<T> entry)
{
_entry = entry;
}
public bool IsValidToDoSomethingElse() => _entry.DeletedOn != null;
}

Factory method and where to choose which factory is to be used

I have a project involving a webshop for different kinds of products. From what I understand, if you have multiple classes that inherit from one base class, the factory design pattern is the way to go. I only have trouble deciding where to put the logic for actually deciding which factory to use.
I have created classes and factory classes for the different kinds of products like so.
public class Product
{
public int ID { get; protected set; }
public string Name { get; set; }
public ProductType Type { get; private set; }
public Product(int id)
{
ID = id;
Populate();
}
public virtual void CompleteOrder()
{
//SendMailToSupplier();
}
private void Populate()
{
//database stuff including setting the type
}
}
public class DigitalProduct : Product
{
public DigitalAsset ProductAsset { get; private set; }
public DigitalProduct(int id, DigitalAsset asset) : base(id)
{
ProductAsset = asset;
}
public override void CompleteOrder()
{
base.CompleteOrder();
//SendAssetToUser();
}
}
public class PrintProduct : Product
{
public PrintInformation Information { get; private set; }
public PrintProduct(int id, PrintInformation information) : base(id)
{
Information = information;
}
public override void CompleteOrder()
{
base.CompleteOrder();
//PreparePrintingFlle();
}
}
public abstract class ProductFactory
{
public abstract Product CreateProduct(int id);
}
public class GenericProductFactory : ProductFactory
{
public override Product CreateProduct(int id)
{
return new Product(id);
}
}
public class DigitalProductFactory : ProductFactory
{
public override Product CreateProduct(int id)
{
DigitalAsset asset = GetDigitalAsset(id);
return new DigitalProduct(id, asset);
}
private DigitalAsset GetDigitalAsset(int id)
{
DigitalAsset asset = new DigitalAsset();
//IO stuff
return asset;
}
}
public class PrintProductProductFactory : ProductFactory
{
public override Product CreateProduct(int id)
{
PrintInformation information = GetPrintInformation(id);
return new PrintProduct(id,information);
}
private PrintInformation GetPrintInformation(int id)
{
PrintInformation information = new PrintInformation();
//database stuff
return information;
}
}
Now when an order is completed an event is triggered.
public void OrderCompleted(int orderId, List<int> productIds);
So here I have a list of int's from which I want to make product object so I can call the
CompleteOrder function on each of them. The problem is to know the type of the product I need to get the product type from the database which is filled in the populate function.
What I could do is create a function public ProductFactory GetFactory(int id) in the ProductFactory. But then the factory is can not be an abstract class.
Another option would be creating a function public static Product GetProduct(int id) in the product class. Which then first figures out which factory to use and the returns the created product.
But both of this options feel weird. Am I missing something? Or is one of these the actual way to go?
Cheers.
So skip the Populate function in the Product class. That is the duties of the factory to do. And I would go with one factory class to create all types of products. (The factory can if needed call other classes to help create the product)
Something like:
public class ProductFactory
{
public Product GetProductById(int id)
{
var dbProduct = FetchFromDb(id);
switch(dbProduct.Type)
{
case "Print"
return CreatePrintProduct(dbProduct);
case "Digital"
return CreateDigitalProduct(dbProduct);
}
}
private DigitalProduct CreateDigitalProduct(DbEntity dbProduct)
{
var product = new DigitalProduct(dbProduct.Id);
//Initialize the product
return product;
}
//You might also want a batch function to avoid calling the database for each product.
public IEnumerable<Product> GetProductByIds(IEnumerable<int> ids)
{
var dbProducts = FetchFromDb(ids);
...
}
}
Eh, just don't over think it. Design patterns should be tools you wield to create your code, if I read your question correctly, I think you are more in a state of the design pattern wielding you.
So unless the pattern helps you, do not over complicate your code with it.
That said, If you do choose to go for a pattern, your situation seems simple enough to go for Magnus's solution.
look at this example of factory method design pattern: http://jayeshtanna.azurewebsites.net/2018/11/25/factory-method-design-pattern/

Implementation of factory method pattern with dependencies

I am trying to better understand the use of the factory method pattern and adhering to SOLID principles and I am not sure if my implementation is correct for the following reasons:
The dependencies my IBankAccountAddOnService implementations need (instantiated in my factory) the larger my BankAccountAddOnFactory constructor is going to get. Shouldn't each IBankAccountAddOnService be responsible for its own dependencies via DI?
In the constructor params for each IBankAccountAddOnService implementation not only do they contain their dependencies but also the concrete type of IBankAccountAddOn specific to that service (e.g. CreditCardAddOn for CreditCardAddOnService). This feels wrong and is why I can't use DI to set them for each service. How could I get the BuildAddOn method to take in the relevant concrete IBankAccountAddOn instead?
Does the switch statement violate the Open Closed Principle or is it ok within a factory? If there were many more bank addons in future, the switch statement may become very large?
IBankAccountAddOn and it's implementations (there may be many of these)
public interface IBankAccountAddOn
{
int Id { get; }
}
public class CreditCardAddOn : IBankAccountAddOn
{
public int Id { get; }
public int CustomerId { get; set; }
public double Limit { get; set; }
public double BalanceTransfer { get; set; }
}
public class TravelInsuranceAddOn : IBankAccountAddOn
{
public int Id { get; }
public int CustomerId { get; set; }
public DateTime Start { get; set; }
public int? MonthsDuration { get; set; }
}
IBankAccountAddOnService that my factory creates dependent upon IBankAccountAddOn
Note - The IExternal... interfaces are from 3rd party libraries.
public interface IBankAccountAddOnResult
{
bool Success { get; set; }
List<string> Errors { get; set; }
}
public class BankAccountAddOnResult : IBankAccountAddOnResult
{
public bool Success { get; set; }
public List<string> Errors { get; set; }
}
public interface IBankAccountAddOnService
{
IBankAccountAddOnResult BuildAddOn();
}
public class CreditCardAddOnService : IBankAccountAddOnService
{
private readonly IExternalCreditCardService _creditCardService;
private readonly IRepository _repository;
private readonly CreditCardAddOn _creditCardAddOn;
public CreditCardAddOnService(IExternalCreditCardService creditCardService, IRepository repository, CreditCardAddOn creditCardAddOn)
{
_creditCardService = creditCardService;
_repository = repository;
_creditCardAddOn = creditCardAddOn;
}
public IBankAccountAddOnResult BuildAddOn()
{
var customerDetails = _repository.GetCustomer(_creditCardAddOn.CustomerId);
if (!customerDetails.CanApplyCreditCards)
{
return new BankAccountAddOnResult
{
Success = false,
Errors = new List<string>{
"Customer cannot apply for credit cards"
}
};
}
var result = _creditCardService.Apply(_creditCardAddOn);
return result;
}
}
public class TravelInsuranceAddOnService : IBankAccountAddOnService
{
private readonly IExternalTravelInsuranceService _travelInsuranceService;
private readonly TravelInsuranceAddOn _travelInsuranceAddOn;
public TravelInsuranceAddOnService(IExternalTravelInsuranceService travelInsuranceService, TravelInsuranceAddOn travelInsurance)
{
_travelInsuranceService = travelInsuranceService;
_travelInsuranceAddOn = travelInsurance;
}
public IBankAccountAddOnResult BuildAddOn()
{
var result = _travelInsuranceService.Apply(_travelInsuranceAddOn.CustomerId, _travelInsuranceAddOn.MonthsDuration, _travelInsuranceAddOn.Start);
return result;
}
}
Factory implementation
public interface IBankAccountAddOnFactory
{
IBankAccountAddOnService Create(IBankAccountAddOn addOn);
}
public class BankAccountAddOnFactory : IBankAccountAddOnFactory
{
private readonly IExternalCreditCardService _creditCardService;
private readonly IExternalTravelInsuranceService _travelInsuranceService;
private readonly IRepository _repository;
public BankAccountAddOnFactory(
IExternalCreditCardService creditCardService,
IExternalTravelInsuranceService travelInsuranceService,
IRepository repository
)
{
_creditCardService = creditCardService;
_travelInsuranceService = travelInsuranceService;
_repository = repository;
}
public IBankAccountAddOnService Create(IBankAccountAddOn addOn)
{
switch (addOn)
{
case CreditCardAddOn creditCard:
return new CreditCardAddOnService(_creditCardService, _repository, creditCard);
case TravelInsuranceAddOn travelInsurance:
return new TravelInsuranceAddOnService(_travelInsuranceService, travelInsurance);
//Many other addon cases
default:
throw new ArgumentOutOfRangeException();
}
}
}
Service that creates add ons for customers
public class BankAccountAddOnService
{
private IBankAccountAddOnFactory _bankAddOnFactory;
public BankAccountAddOnService(IBankAccountAddOnFactory bankAddOnFactory)
{
_bankAddOnFactory = bankAddOnFactory;
}
public IBankAccountAddOnResult Apply(IBankAccountAddOn addOn)
{
var applyService = _bankAddOnFactory.Create(addOn);
var response = applyService.BuildAddOn();
//Do something with response
return response;
}
}
The dependencies my IBankAccountAddOnService implementations need (instantiated in my factory) the larger my BankAccountAddOnFactory constructor is going to get. Shouldn't each IBankAccountAddOnService be responsible for its own dependencies via DI?
I don't understand "each [service] be responsible for its own dependencies via DI." The whole point of DI is that classes are not responsible for their own dependencies-- the code that instantiates the class is.
And yes it is normal to have a constructor with more and more arguments as dependencies are added. If you have trouble with this, see Constructor injection: How many dependencies is too many?.
In the constructor params for each IBankAccountAddOnService implementation not only do they contain their dependencies but also the concrete type of IBankAccountAddOn specific to that service (e.g. CreditCardAddOn for CreditCardAddOnService). This feels wrong and is why I can't use DI to set them for each service. How could I get the BuildAddOn method to take in the relevant concrete IBankAccountAddOn instead?
It's okay to inject a concrete type, obviously, but the class receiving the injection should not rely on it. Instead, define an interface for the things it relies on, and add that interface to the concrete type. It's OK if that interface contains all the concrete type's members.
Example:
public interface IBankAccountAddOnService
{
IBankAccountAddOnResult BuildAddOn();
}
public interface ICreditCardAddOnService : IBankAccountAddOnService
{
int CustomerId { get; }
}
public class CreditCardAddOnService : ICreditCardAddOnService
{
public CreditCardAddOnService(IExternalCreditCardService creditCardService, IRepository repository, ICreditCardAddOn creditCardAddOn)
{
//etc
Does the switch statement violate the Open Closed Principle or is it ok within a factory? If there were many more bank addons in future, the switch statement may become very large?
No, it does not violate OCP in and of itself.
If the list gets very large, you can implement as a map instead, e.g.
var map = new Dictionary<Type,Func<IBankAccountAddOnService>>
{
{ typeof(CreditCardAddOn), () => new CreditCardAddOnService(_creditCardService, _repository, creditCard) },
{ typeof(TravelInsuranceAddOn), () => new TravelInsuranceAddOnService(_travelInsuranceService, travelInsurance) }
}
With the map in place, you can do this:
public IBankAccountAddOnService Create(IBankAccountAddOn addOn)
{
return map[addOn.GetType()]();
}

Multiple Inheritance Substitute in C# - Specific Hypothetical Example With Logic in The Properties

Let’s say there are 2 classes that have the same prop, with logic in that prop as well.
public class Manager
{
private string _ssn { get; set; }
[RegularExpression(#"\d{9}")]
public string SSN
{
get
{
return _ssn;
}
set
{
if (!string.IsNullOrEmpty(value))
_ssn = someLogicalMethod (value);
}
}
}
And
public class Employee
{
private string _ssn { get; set; }
[RegularExpression(#"\d{9}")]
public string SSN
{
get
{
return _ssn;
}
set
{
if (!string.IsNullOrEmpty(value))
_ssn = someLogicalMethod(value);
}
}
}
Ideally, you’d make an abstract base class (BaseSSN) these would inherit from. That’s all well and good, but not ideal! The reason for this is because in C# you can only inherit from 1 super class. That means that if you have a case where Manager and Employee both have SSN, but Manager and a new class (CEO) have a ManagerOf property, then you have to then create a new class that implements the BaseSSN class but it would also be an abstract class (BaseManagerOf) that has the logic for Managerof inside of it. Then, Manager and CEO would inherit from the new class. However, now you would have to create still another class if someone was a manager but themselves did not have an SSN. You would need to pull out the Manager prop and put it in a super, to separate it from the SSN class.
Do you see where I’m going with this? It could create N number of variations depending on the amount of props each class has that are similar to other classes.
So what I would like to do is simply
Public class Manager : BaseSSN, BaseManagerOf, X
Where X is anything. You can do this with interfaces, but interfaces can’t contain logic.
I believe there is probably a smooth strategy that will solve this, but can’t figure it out for the life of me.
EDIT:
There seems to be a small amount of confusion regarding my question: this is a hypothetical question. I understand that managers are employees. The simple question is that i want one class to implement 2 abstracts and cannot do that in C#. However, is there a strategy that would allow this to work in any way?
public class Manager : BaseManager
{
}
public abstract class BaseManager : BaseSSN
{
private string _managerOf;
public int ManagerOf
{
get
{
return _managerOf;
}
set
{
if (!string.IsNullOrEmpty(value))
_managerOf = someLogicalMethod(value);
}
}
}
public abstract class BaseSSN
{
private string _ssn { get; set; }
[RegularExpression(#"\d{9}")]
public string SSN
{
get
{
return _ssn;
}
set
{
if (!string.IsNullOrEmpty(value))
_ssn = someLogicalMethod(value);
}
}
}
public class CEO : ManagerOf {}
Now it begins to fall apart with CEO. I don't want the CEO's SSN, only the person he manages. So I would have to pull the logic out of the ManagerOf class that inherits SSN, and put that in its own class. Then CEO wouldn't have the SSN prop. However, now I can't have both ManagerOf logic and SSN logic in my Manager class without creating yet another abstract that looks like the following class...
public class ManagerOfAndSSN: SSN
{
// repetitive manager logic here
}
One answer is to use interfaces and composition. Your "base" classes that implement the functionality (e.g. ManagerOf or SSN) implement the interface, and then you provide those as dependencies to classes that need them:
public interface ISsn
{
string Ssn { get; set; }
}
public interface IManagerOf
{
List<Employee> Manages { get; set; }
}
public class Ssn : ISsn { ... }
public class ManagerOf : IManagerOf { ... }
Now you can inject those classes in the classes that compose them together:
// here we are implementing the interfaces on the class
public class Employee : ISsn
{
private ISsn _ssn;
public Employee(ISsn ssn)
{
_ssn = ssn;
}
public string Ssn
{
get { return _ssn.Ssn; }
set { _ssn.Ssn = value }
}
}
public class Manager : ISsn, IManagerOf
{
private ISsn _ssn;
private IManagerOf _managerOf;
public Employee(ISsn ssn, IManagerOf managerOf)
{
_ssn = ssn;
_managerOf = managerOf;
}
public string Ssn
{
get { return _ssn.Ssn; }
set { _ssn.Ssn = value }
}
public List<Employee> Manages
{
get { return _managerOf.Manages; }
set { _managerOf.Manages = value; }
}
}
Or, an alternative implementation of the classes:
// here we're just going to expose each dependency as the interface
public class Employee : ISsn
{
private ISsn _ssn;
public Employee(ISsn ssn)
{
_ssn = ssn;
}
public ISsn Ssn => _ssn;
}
public class Manager2
{
private ISsn _ssn;
private IManagerOf _managerOf;
public Employee(ISsn ssn, IManagerOf managerOf)
{
_ssn = ssn;
_managerOf = managerOf;
}
public ISsn Ssn => _ssn;
public IManagerOf ManagerOf => _managerOf;
}
This is a fairly trivial implementation, and in this case I'd opt to simply implement the interfaces in each class supporting the functionality. If, however, you had more complex logic around the properties, the composition route makes more sense since you are sharing the implementation then. It's not as "elegant" as multiple inheritance seems at first, but see Why is Multiple Inheritance not allowed in Java or C#? for some discussion of why multiple inheritance is often thought to cause more trouble than it solves.

Implementing interface in different assemblies

I have an interface and class like this
public interface ICustomerEx
{
void Load(DataRow row);
}
public class Customer:ICustomerEx
{
public string Name{get;set;}
public string Address{get;set;}
void Load(DataRow row)
{
Name = (string)row["name"];
Address = (string)row["address"];
}
}
Now I'm building this as a class library and add to another project as a reference.
In that project there's a class called UiCustomer that implements from the same refereced interface ICustomerEx
In this class it has its own property and load that property from its load method.
public class UiCustomer:ICustomerEx
{
public string Telephone{get;set;}
void Load(DataRow row)
{
Telephone=(string)row["tele"];
}
}
Now is there any way to implement my first class's(that build as a class library) Load method to load Ui project's properties after loading it's own properties by using like Dependency Injection.
eg.
public class Customer:ICustomerEx
{
public string Name{get;set;}
public string Address{get;set;}
void Load(DataRow row)
{
Name = (string)row["name"];
Address = (string)row["address"];
//Call load methods in other places that Interface implemented
}
}
It depends what you want. Using separate classes as you have now, you'd need to dependency-inject a list of ICustomerEx objects into each Customer, but then you'd end up with a bunch of different objects each of which would have only a subset of the relevant properties. It sounds like inheritance + the template method pattern might be a better fit:
public class Customer:ICustomerEx
{
public string Name{get;set;}
public string Address{get;set;}
void Load(DataRow row)
{
this.Name = (string)row["name"];
this.Address = (string)row["address"];
this.DoMoreLoading(row);
}
// this method is defined as a no-op in the base class, but it provides an extension point
// for derived classes that want to load additional properties
protected virtual void DoMoreLoading(DataRow row) { }
}
// note that now UiCustomer extends Customer (and thus still implements ICustomerEx
public class UiCustomer : Customer
{
public string Telephone { get; set; }
protected override void DoMoreLoading(DataRow row)
{
this.Telephone = (string)row["tele"];
}
}
// usage
var uiCustomer = new UiCustomer();
uiCustomer.Load(row); // populates name, addr, and telephone
To support instantiating the customer on the library side, you'll need some way to make the library aware of the UiCustomer class.
One way to do this would be to register an ICustomerEx with an IOC container and then resolve the instance using dependency injection:
// in the UI code (this is code for the Autofac IOC container):
ContainerBuilder cb = ...
cb.RegisterType<UiCustomer>().As<ICustomerEx>();
cb.RegisterType<AServiceThatNeedsACustomer>();
// in the library code
public class AServiceThatNeedsACustomer {
private readonly ICustomerEx customer;
// the customer will get injected by the IOC container
public AServiceThatNeedsACustomer(ICustomerEx customer) {
this.customer = customer;
}
}
Alternatively, you could use a factory pattern:
// in the library:
public static class CustomerFactory {
private static volatile Func<ICustomerEx> instance = () => new Customer();
public static Func<ICustomerEx> Instance { get { return instance; } set { instance = value; } }
}
// then to get a customer
var cust = CustomerFactor.Instance();
cust.Load(row);
// in the UI code:
CustomerFactory.Instance = () => new UiCustomer();
You can call the other implementations like this
In the assembly that contains the interface ICustomerEx you can add a registry-class that stores instances of ICustomerEx like this
(Note this is pseudocode to show how it could go.)
public class CustomerRegistry : ICustomerEx {
// singelton
public static final CustomerRegistry theRegistry = new CustomerRegistry();
private ArrayList<ICustomerEx> customers = new ArrayList<ICustomerEx>();
public void RegisterCustomer(ICustomerEx customer) {
customers.add(customer);
}
public void Load(DataRow row)
{
foreach(ICustomerEx customer in customers) {
customer.Load(row);
}
}
}
every implementation of ICustomerEx needs a call to the registry
CustomerRegistry.theRegistry.RegisterCustomer(new UiCustomer());
in your main customer class you use the registry to call the other loads
public class Customer:ICustomerEx
{
void Load(DataRow row)
{
CustomerRegistry.theRegistry.Load(row);
}
}

Categories