Dependency injection with .NET Core and abstract (base) class - c#

I have 1 abstract class that is used by 2 other classes inheriting from it:
public abstract class FiltererBase
{
ColorsOrderer colorsOrderer;
public FiltererBase(ColorsOrderer colorsOrderer)
{
this.colorsOrderer = colorsOrderer;
}
protected string OrderColors(string colors)
{
return string.Join("", colors.ToCharArray().OrderBy(i => colorsOrderer.Order[i]));
}
}
public class Filterer1 : FiltererBase
{
public Filterer1(ColorsOrderer colorsOrderer)
: base(colorsOrderer) { }
}
public class Filterer2 : FiltererBase
{
public Filterer2(ColorsOrderer colorsOrderer)
: base(colorsOrderer) { }
}
As you can see, I am using dependency injection (DI) and passing the class instantiated from the child constructor to the parent constructor.
Is it really the best way to do DI with abstract (base) classes? Isn't the .NET Core framework providing a more automatic way to do that?

Unfortunately, it's not possible to inject parameters into a parent constructor.
You could use a composition approach instead of inheritance.
Refactoring your code to a composition approach, it would appear like this:
public class ColorFilter
{
ColorsOrderer colorsOrderer;
public ColorFilter(ColorsOrderer colorsOrderer)
{
this.colorsOrderer = colorsOrderer;
}
public string OrderColors(string colors)
{
return string.Join("", colors.ToCharArray().OrderBy(i => colorsOrderer.Order[i]));
}
}
public class Filterer1
{
ColorFilter colorFilter;
public Filterer1(ColorFilter colorFilter)
{
this.colorFilter = colorFilter;
}
public string OrderColors(string colors)
{
return this.colorFilter(colors);
}
}
public class Filterer2
{
ColorFilter colorFilter;
public Filterer2(ColorFilter colorFilter)
{
this.colorFilter = colorFilter;
}
public string OrderColors(string colors)
{
return this.colorFilter(colors);
}
}

Related

DI - register all implementation of derived class by generic interface

I have the following:
public interface IModelProcessor<S>
where S : MyAbstractClass
{
void ProcessModel(S myAbstractClass);
}
public abstract class ModelProcessor<S> : IModelProcessor<S>
where S : MyAbstractClass
{
public void ProcessModel(S myAbstractClass)
{
// Implementation here.
}
}
// ConcreteOne derives from MyAbstractClass.
public class ConcreteOneProcessor : ModelProcessor<ConcreteOne>
{
}
// ConcreteTwo derives from MyAbstractClass.
public class ConcreteTwoProcessor : ModelProcessor<ConcreteTwo>
{
}
// ConcreteThree derives from MyAbstractClass.
public class ConcreteThreeProcessor : ModelProcessor<ConcreteThree>
{
}
public class ModelProcessorFactory : IModelProcessorFactory
{
private readonly IEnumerable<IModelProcessor<MyAbstractClass>> _modelProcessors;
public ModelProcessorFactory(
IEnumerable<IModelProcessor<MyAbstractClass>> modelProcessors)
{
_modelProcessors = modelProcessors; // Always null.
}
}
I want to be able to register all implementations of IModelProcessor so thay are injected into the ModelProcessorFactory above, but the collection is always null at runtime.
I have tried:
builder.Services.AddScoped<IModelProcessor<ConcreteOne>, ConcreteOneProcessor>();
builder.Services.AddScoped<IModelProcessor<ConcreteTwo>, ConcreteTwoProcessor>();
builder.Services.AddScoped<IModelProcessor<ConcreteThree>, ConcreteThreeProcessor>();
but this doesn't seem to work. Can anyone point out what I'm doing wrong here?
Thanks.
You can register it by using the below extension method:
public static class DependencyExtensions
{
public static IServiceCollection AddGenericInterface(this IServiceCollection services,Type interfaceType, Assembly assembly)
{
foreach (var exportedType in assembly.GetExportedTypes())
{
if (exportedType.IsClass && !exportedType.IsAbstract )
{
var interfaces = exportedType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == interfaceType);
// If you need to support multiple interface for the same class
foreach (var typeDefinition in interfaces.ToList())
{
services.AddScoped(typeDefinition, exportedType);
}
}
}
return services;
}
}
And then add it to you services like the below:
Services.AddEndpointsApiExplorer();

Is it better practice to retain an extra reference to a subclass or cast to a subclass to call methods specific to that subclass?

I have a system where an object can take a generic configuration object (think flyweight pattern). I also have a subclass which takes a subclassed configuration object.
In order to access properties that are specific to the subclass configuration object, is it better to maintain a second reference to the subclass or cast to the subclass?
e.g.
class Base {
public BaseConf Conf;
public Base(BaseConf C) {
Conf = C;
}
}
class Derived : Base {
public DerivedConf DerConf; //Create an extra reference, no casting
public Derived(DerivedConf DC) : base(DC) {
DerConf = DC;
}
public void PrintName() {
Console.WriteLine(DerConf.Name);
}
}
class BaseConf {
public BaseConf() {}
}
class DerivedConf : BaseConf {
public string Name;
public DerivedConf(string n) : base() {
Name = n;
}
}
vs.
class Base {
public BaseConf Conf;
public Base(BaseConf C) {
Conf = C;
}
}
class Derived : Base {
public Derived(DerivedConf DC) : base(DC) {}
public void PrintName() {
DerivedConf DerConf = Conf as DerivedConf; //Cast, no extra reference
Console.WriteLine(DerConf.Name);
}
}
class BaseConf {
public BaseConf() {}
}
class DerivedConf : BaseConf {
public string Name;
public DerivedConf(string n) : base() {
Name = n;
}
}
Both have an identical output
I wouldn't want to do either of those and you can get around both by making the Base take a generic, like so:
class Base<T> where T : BaseConf
{
public T Conf;
public Base(T C)
{
Conf = C;
}
}
class Derived : Base<DerivedConf>
{
public Derived(DerivedConf DC) : base(DC)
{
}
public void PrintName()
{
Console.WriteLine(Conf.Name);
}
}
static void Main(string[] args)
{
var derived = new Derived(new DerivedConf("Foo"));
derived.PrintName(); // Foo
}

Unity - Resolve implementation of generic interface based on model type

I'm new to Unity and am running into issues when it comes to classes that implement generic interfaces.
Suppose I have one controller and one service class, with the intention that they call the business layer based on an type identifier passed into the controller. Here's my layout:
Models:
public interface IModel
{
string Name { get; }
}
public class MyOrder : IModel
{
public string Name { get { return "Order"; } }
}
public class MyInvoice : IModel
{
public string Name { get { return "Invoice"; } }
}
Business Logic:
public interface ILogic
{
string GetModelName(IModel myModel);
}
public class MyOrderLogic : ILogic
{
public string GetModelName(IModel myModel)
{
return "MyOrderLogic : " + myModel.Name;
}
}
public class MyInvoiceLogic : ILogic
{
public string GetModelName(IModel myModel)
{
return "MyInvoiceLogic : " + myModel.Name;
}
}
public class LogicFactory
{
Func<IModel, ILogic> logicResolver;
public LogicFactory(Func<IModel, ILogic> resolver)
{
logicResolver = resolver;
}
public ILogic GetLogicForModel(IModel model)
{
return logicResolver(model);
}
}
Service:
public class MySingleService
{
private LogicFactory factory;
public MySingleService(LogicFactory f)
{
this.factory = f;
}
public IModel GetModel(int typeId, int objectId)
{
IModel model;
// This would really call Entity Framework context
switch (typeId)
{
case 1:
model = new MyOrder();
break;
default:
model = new MyInvoice();
break;
}
return model;
}
public void DoSomething(IModel model)
{
var logic = factory.GetLogicForModel(model);
var name = logic.GetModelName(model);
Console.WriteLine(name);
}
}
Controller:
public class MyController
{
MySingleService service;
public MyController(MySingleService s)
{
this.service = s;
}
public void DoAnAction(int typeId, int objectId)
{
var model = service.GetModel(typeId, objectId);
service.DoSomething(model);
}
}
This all works pretty well when I configure my Unity container like so
var container = new UnityContainer();
container.RegisterType<ILogic, MyOrderLogic>("MyOrder");
container.RegisterType<ILogic, MyInvoiceLogic>("MyInvoice");
Func<IModel, ILogic> resolver = (myModel) => container.Resolve<ILogic>(myModel.GetType().Name);
var logicFactory = new LogicFactory(resolver);
container.RegisterInstance<LogicFactory>(logicFactory);
var controller = container.Resolve<MyController>();
My issue is that I want to restrict the Business Logic classes so that they can only work on the proper model (i.e. I want MyOrderLogic to only accept MyOrder)
I wanted to have the business layer make use of generics, like so:
// Business Logic
public interface ILogic<T> where T : IModel
{
string GetModelName(T myModel);
}
public class MyOrderLogic : ILogic<MyOrder>
{
public string GetModelName(MyOrder myModel)
{
return "MyOrderLogic : " + myModel.Name;
}
}
public class MyInvoiceLogic : ILogic<MyInvoice>
{
public string GetModelName(MyInvoice myModel)
{
return "MyInvoiceLogic : " + myModel.Name;
}
}
This caused all kinds of problems between the Service and the Controller. I'm not sure how to properly resolve the *Logic classes based on a type identifier. I tried to do something similar to ILogic<IModel> logic = new MyOrderLogic(), but that obviously didn't work.
Is what I'm looking for possible? Is there something I can add to just the LogicFactory or something?
I want to avoid having individual controller and service objects as they would just have duplicate code.

Appropriate design pattern for the payment modules c#

As i am learning through design pattern concept and also wanted to implement the payment modules in my project using the proper design pattern. So for that I have created some sample code.
Currently I have two concrete implementation for the payment PayPal and Credit Card. But the concrete implementation will be added further on the project.
Payment Service
public interface IPaymentService
{
void MakePayment<T>(T type) where T : class;
}
Credit Card and Pay Pal Service
public class CreditCardPayment : IPaymentService
{
public void MakePayment<T>(T type) where T : class
{
var creditCardModel = (CreditCardModel)(object)type;
//Implementation CreditCardPayment
}
}
class PayPalPayment : IPaymentService
{
public void MakePayment<T>(T type) where T : class
{
var payPalModel = (PayPalModel)(object)type;
//Further Implementation will goes here
}
}
Client Code Implementation
var obj = GetPaymentOption(payType);
obj.MakePayment<PayPalModel>(payPalModel);
Get Payment Option
private static IPaymentService GetPaymentOption(PaymentType paymentType)
{
IPaymentService paymentService = null;
switch (paymentType)
{
case PaymentType.PayPalPayment:
paymentService = new PayPalPayment();
break;
case PaymentType.CreditCardPayment:
paymentService = new CreditCardPayment();
break;
default:
break;
}
return paymentService;
}
I thought of implementing this modules using strategy design pattern, and I got deviated from Strategy and ended up doing this way.
Is this a proper way for creating the payment modules. Is there a more better approach of solving this scenario. Is this a design pattern?
Edited:
Client Code:
static void Main(string[] args)
{
PaymentStrategy paymentStrategy = null;
paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)1));
paymentStrategy.Pay<PayPalModel>(new PayPalModel() { UserName = "", Password = "" });
paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)2));
paymentStrategy.Pay<CreditCardModel>(
new CreditCardModel()
{
CardHolderName = "Aakash"
});
Console.ReadLine();
}
Strategy:
public class PaymentStrategy
{
private readonly IPaymentService paymentService;
public PaymentStrategy(IPaymentService paymentService)
{
this.paymentService = paymentService;
}
public void Pay<T>(T type) where T : class
{
paymentService.MakePayment(type);
}
}
Does this update inlines with the Strategy Pattern?
One major drawback of using an abstract factory for this is the fact that it contains a switch case statement. That inherently means if you want to add a payment service, you have to update the code in the factory class. This is a violation of the Open-Closed Principal which states that entities should be open for extension but closed for modification.
Note that using an Enum to switch between payment providers is also problematic for the same reason. This means that the list of services would have to change every time a payment service is added or removed. Even worse, a payment service can be removed from the strategy, but still be an Enum symbol for it even though it isn't valid.
On the other hand, using a strategy pattern doesn't require a switch case statement. As a result, there are no changes to existing classes when you add or remove a payment service. This, and the fact that the number of payment options will likely be capped at a small double-digit number makes the strategy pattern a better fit for this scenario.
Interfaces
// Empty interface just to ensure that we get a compile
// error if we pass a model that does not belong to our
// payment system.
public interface IPaymentModel { }
public interface IPaymentService
{
void MakePayment<T>(T model) where T : IPaymentModel;
bool AppliesTo(Type provider);
}
public interface IPaymentStrategy
{
void MakePayment<T>(T model) where T : IPaymentModel;
}
Models
public class CreditCardModel : IPaymentModel
{
public string CardHolderName { get; set; }
public string CardNumber { get; set; }
public int ExpirtationMonth { get; set; }
public int ExpirationYear { get; set; }
}
public class PayPalModel : IPaymentModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
Payment Service Abstraction
Here is an abstract class that is used to hide the ugly details of casting to the concrete model type from the IPaymentService implementations.
public abstract class PaymentService<TModel> : IPaymentService
where TModel : IPaymentModel
{
public virtual bool AppliesTo(Type provider)
{
return typeof(TModel).Equals(provider);
}
public void MakePayment<T>(T model) where T : IPaymentModel
{
MakePayment((TModel)(object)model);
}
protected abstract void MakePayment(TModel model);
}
Payment Service Implementations
public class CreditCardPayment : PaymentService<CreditCardModel>
{
protected override void MakePayment(CreditCardModel model)
{
//Implementation CreditCardPayment
}
}
public class PayPalPayment : PaymentService<PayPalModel>
{
protected override void MakePayment(PayPalModel model)
{
//Implementation PayPalPayment
}
}
Payment Strategy
Here is the class that ties it all together. Its main purpose is to provide the selection functionality of the payment service based on the type of model passed. But unlike other examples here, it loosely couples the IPaymentService implementations so they are not directly referenced here. This means without changing the design, payment providers can be added or removed.
public class PaymentStrategy : IPaymentStrategy
{
private readonly IEnumerable<IPaymentService> paymentServices;
public PaymentStrategy(IEnumerable<IPaymentService> paymentServices)
{
this.paymentServices = paymentServices ?? throw new ArgumentNullException(nameof(paymentServices));
}
public void MakePayment<T>(T model) where T : IPaymentModel
{
GetPaymentService(model).MakePayment(model);
}
private IPaymentService GetPaymentService<T>(T model) where T : IPaymentModel
{
var result = paymentServices.FirstOrDefault(p => p.AppliesTo(model.GetType()));
if (result == null)
{
throw new InvalidOperationException(
$"Payment service for {model.GetType().ToString()} not registered.");
}
return result;
}
}
Usage
// I am showing this in code, but you would normally
// do this with your DI container in your composition
// root, and the instance would be created by injecting
// it somewhere.
var paymentStrategy = new PaymentStrategy(
new IPaymentService[]
{
new CreditCardPayment(), // <-- inject any dependencies here
new PayPalPayment() // <-- inject any dependencies here
});
// Then once it is injected, you simply do this...
var cc = new CreditCardModel() { CardHolderName = "Bob" /* Set other properties... */ };
paymentStrategy.MakePayment(cc);
// Or this...
var pp = new PayPalModel() { UserName = "Bob" /* Set other properties... */ };
paymentStrategy.MakePayment(pp);
Additional References:
Dependency Injection Unity - Conditional Resolving
Factory method with DI and IoC
This is one approach you could take. There's not a lot to go on from your source, and I'd really reconsider having MakePayment a void instead of something like an IPayResult.
public interface IPayModel { } // Worth investigating into common shared methods and properties for this
public interface IPaymentService
{
void MakePayment(IPayModel payModel);
}
public interface IPaymentService<T> : IPaymentService where T : IPayModel
{
void MakePayment(T payModel); // Void here? Is the status of the payment saved on the concrete pay model? Why not an IPayResult?
}
public class CreditCardModel : IPayModel
{
public string CardHolderName { get; set; }
}
public class PayPalModel : IPayModel
{
public string UserName { get; set; }
public string Password { get; set; }
}
public class CreditCardPayment : IPaymentService<CreditCardModel>
{
public void MakePayment(CreditCardModel payModel)
{
//Implmentation CreditCardPayment
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as CreditCardModel);
}
}
public class PayPalPayment : IPaymentService<PayPalModel>
{
public void MakePayment(PayPalModel payModel)
{
//Implmentation PayPalPayment
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as PayPalModel);
}
}
public enum PaymentType
{
PayPalPayment = 1,
CreditCardPayment = 2
}
So following your implementation approach, it could look something like:
static class Program
{
static void Main(object[] args)
{
IPaymentService paymentStrategy = null;
paymentStrategy = GetPaymentOption((PaymentType)1);
paymentStrategy.MakePayment(new PayPalModel { UserName = "", Password = "" });
paymentStrategy = GetPaymentOption((PaymentType)2);
paymentStrategy.MakePayment(new CreditCardModel { CardHolderName = "Aakash" });
Console.ReadLine();
}
private static IPaymentService GetPaymentOption(PaymentType paymentType)
{
switch (paymentType)
{
case PaymentType.PayPalPayment:
return new PayPalPayment();
case PaymentType.CreditCardPayment:
return new CreditCardPayment();
default:
throw new NotSupportedException($"Payment Type '{paymentType.ToString()}' Not Supported");
}
}
}
I also think for a strategy/factory pattern approach, manually creating an IPayModel type doesn't make much sense. Therefore you could expand the IPaymentService as an IPayModel factory:
public interface IPaymentService
{
IPayModel CreatePayModel();
void MakePayment(IPayModel payModel);
}
public interface IPaymentService<T> : IPaymentService where T : IPayModel
{
new T CreatePayModel();
void MakePayment(T payModel);
}
public class CreditCardPayment : IPaymentService<CreditCardModel>
{
public CreditCardModel CreatePayModel()
{
return new CreditCardModel();
}
public void MakePayment(CreditCardModel payModel)
{
//Implmentation CreditCardPayment
}
IPayModel IPaymentService.CreatePayModel()
{
return CreatePayModel();
}
void IPaymentService.MakePayment(IPayModel payModel)
{
MakePayment(payModel as CreditCardModel);
}
}
Usage would then be:
IPaymentService paymentStrategy = null;
paymentStrategy = GetPaymentOption((PaymentType)1);
var payModel = (PayPalModel)paymentStrategy.CreatePayModel();
payModel.UserName = "";
payModel.Password = "";
paymentStrategy.MakePayment(payModel);
Your code is basically using the factory pattern. This is a good way to handle more than one method of payment
http://www.dotnettricks.com/learn/designpatterns/factory-method-design-pattern-dotnet

Inject a string property in a class using Ninject

One of my interfaces has a string property that will depend on where the interface is being used. I want to avoid hardcoding the property every time the object is created. I can set the property in constructor, but the object is injected using a factory.
The interface as follows:
public interface IObjectStore
{
string StorageTableName { get; set;}
void UpdateObjectStore(string key, string value);
string ReadObjectStore(string key);
}
Which is used in a service
public class CategoryService<T> : ICategoryService<T> where T : Company
{
private readonly IObjectStore objectStore;
public CategoryService(IObjectStore objStore)
{
this.objectStore = objStore;
objectStore.StorageTableName = "CategoryTable"; // I want to avoid this hard coding
}
...
}
The service is created using service factory (Ninject.Extensions.Factory)
public interface IServiceFactory
{
ICategoryService<T> CreateCategoryService<T>() where T : class;
}
Which is then injected using Ninject at the controller level. Here are my bindings
bool storeInNoSql = true;
kernel.Bind<IServiceFactory>().ToFactory().InSingletonScope();
kernel.Bind<ICategoryService<Article>>().To<CategoryService<Article>>();
kernel.Bind<IObjectStore>().ToMethod(ctx => storeInNoSql ? ctx.Kernel.Get<ObjectStore>() : null);
So the question is: how do i tell Ninject to set the property StorageTableName to "CategoryTable" everytime the object is injected into CategoryService and to "ArticleTable" everytime it is inserted into ArticleService?
I think this is what you are looking for.
It's just a very small sample project I just did, but this should solve your problem.
public class Ninject_34091099
{
public static void Run()
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IInterface<Generic1>>()
.To<Class<Generic1>>()
.WithConstructorArgument("name", "STRING ONE");
kernel.Bind<IInterface<Generic2>>()
.To<Class<Generic2>>()
.WithConstructorArgument("name", "The other string");
kernel.Bind<IServiceFactory>().ToFactory().InSingletonScope();
var factory = kernel.Get<IServiceFactory>();
var c1 = factory.CreateInterface<Generic1>();
var c2 = factory.CreateInterface<Generic2>();
Console.WriteLine(c1.Name);
Console.WriteLine(c2.Name);
}
Console.WriteLine("Done");
Console.ReadLine();
}
}
public interface IInterface<T> where T : class
{
string Name { get; set; }
}
public class Generic1
{
}
public class Generic2
{
}
public class Class<T> : IInterface<T> where T : class
{
public string Name { get; set; }
public Class(string name)
{
Name = name;
}
}
public interface IServiceFactory
{
IInterface<T> CreateInterface<T>() where T : class;
}
Sorry that the names mean nothing :D
Hope it helps

Categories

Resources