Extract Reusable Code into Abstract Base Class with Generic Parameters - c#

I am trying to achieve a design in c# like below.
void Main()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped(typeof(RedisRepository<>));
serviceCollection.AddScoped(typeof(CommitterBase<IDto>), typeof(ACommitter));
serviceCollection.AddScoped(typeof(CommitterBase<IDto>), typeof(BCommitter));
serviceCollection.AddScoped<Client>();
var services = serviceCollection.BuildServiceProvider();
var client = services.GetRequiredService<Client>();
client.Dump();
}
public class RedisRepository<T> where T: IDto
{
public void Add(T dto)
{
Console.WriteLine("Added data");
}
}
public interface IDto
{
}
public class ADto: IDto
{
}
public class BDto : IDto
{
}
and :
public abstract class CommitterBase<T> where T: IDto
{
public CommitterBase(RedisRepository<T> repo)
{ }
public void Commit()
{
var dto = GenerateDto();
//do something with dto here
}
protected abstract T GenerateDto();
}
and its implementations:
public class ACommitter : CommitterBase<ADto>
{
public ACommitter(RedisRepository<ADto> repo): base(repo)
{ }
protected override ADto GenerateDto()
{
return new ADto();
}
}
public class BCommitter : CommitterBase<BDto>
{
public BCommitter(RedisRepository<BDto> repo) : base(repo)
{
}
protected override BDto GenerateDto()
{
return new BDto();
}
}
public class Client
{
public Client(IEnumerable<CommitterBase<IDto>> committers)
{ }
}
error that I get
Implementation type 'BCommitter' can't be converted to
service type 'UserQuery+CommitterBase`1[IDto]'
I understand from this stackoverflow post that this error is expected. Just wondering how to achieve similar effect without encountering the error. My aim is to extract reusable code into an Abstract Base Class and let the implementations do bare minimum.
Thanks in advance!

Interface cannot be instantiated and IDto is interface. So you can register specific implementation to your interface.
I little bit refactored code to use generic parameters.
This is yor base abstract class:
public abstract class CommitterBase<T> where T : IDto
{
public CommitterBase(RedisRepository<T> repo)
{ }
public void Commit()
{
var dto = GenerateDto();
//do something with dto here
}
protected abstract T GenerateDto();
}
And its concrete implementations such as ACommitter:
public class ACommitter<T> : CommitterBase<T> where T : IDto, new()
{
public ACommitter(RedisRepository<T> repo) : base(repo)
{ }
protected override T GenerateDto()
{
return new T();
}
}
and BCommitter:
public class BCommitter<T> : CommitterBase<T> where T: IDto, new()
{
public T FooBar { get; set; }
public BCommitter(RedisRepository<T> repo) : base(repo)
{
}
protected override T GenerateDto()
{
return new T();
}
}
and RedisRepository:
public class RedisRepository<T> where T : IDto
{
public void Add(T dto)
{
Console.WriteLine("Added data");
}
}
and Client class:
public class Client<T> where T : IDto, new()
{
public CommitterBase<T> CommitterBaseProperty { get; set; }
public Client(CommitterBase<T> committer) // if you want all instances of committers,
// then you need to create a factory
// and inject it through DI
{
CommitterBaseProperty = committer;
}
}
And you can call it like this:
static void Main(string[] args)
{
ServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<RedisRepository<ADto>>();
serviceCollection.AddScoped<RedisRepository<BDto>>();
serviceCollection.AddScoped<CommitterBase<ADto>, ACommitter<ADto>>();
serviceCollection.AddScoped<CommitterBase<BDto>, BCommitter<BDto>>();
serviceCollection.AddScoped<Client<ADto>>();
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
CommitterBase<ADto> committerBase = serviceProvider.GetRequiredService<CommitterBase<ADto>>();
CommitterBase<BDto> committerBase_B =
serviceProvider.GetRequiredService<CommitterBase<BDto>>();
committerBase.Commit();
Client<ADto> client = serviceProvider.GetRequiredService<Client<ADto>>();
}

Related

How to use dependency injection for generic interfaces?

How to use dependency injection for generic interfaces? I want the IDrawView interface to be created in DrawPresenter, and it controls the view.
I do not know what to use, Ninject or something else. I am using WinForms.
Which is better to choose?
class Program
{
static void Main(string[] args)
{
IDrawPresenter prisenter = new DrawPresenter(new DrawWindow());
prisenter.Show();
Console.ReadLine();
}
}
public interface IView
{
void Show();
}
public interface IDrawView : IView
{
object GetGridDraw { get; }
}
public interface IPrisenter<TView> where TView : IView
{
void Show();
}
public interface IDrawPresenter : IPrisenter<IDrawView>
{
object SelectedDraws { get; }
}
public class DrawWindow : IDrawView
{
public object GetGridDraw => 1;
public void Show()
{
Console.WriteLine("Show Window");
}
}
public abstract class BasePresenter<TView> : IPrisenter<TView>
where TView : IView
{
protected BasePresenter(TView view)
{
View = view;
}
protected TView View { get; private set; }
public void Show()
{
View.Show();
}
}
public class DrawPresenter : BasePresenter<IDrawView>, IDrawPresenter
{
public DrawPresenter(IDrawView view): base(view)
{
}
public object SelectedDraws => View.GetGridDraw;
}
Can DI implement this?
IDrawPresenter prisenter = new DrawPresenter();
public DrawPresenter()
{
}
What I need to do for Presenter to manage the form.
Here is what I want to get. But this does not work ...
public class NinjectProgram
{
//Gets the inject kernal for the program.
public static IKernel Kernel { get; protected set; }
}
public class DependencyModule : NinjectModule
{
public override void Load()
{
Bind<IDrawView>().To<DrawWindow>();
}
}
static void Main(string[] args)
{
StandardKernel Kernel = new StandardKernel();
Kernel.Load(new DependencyModule());
IDrawPresenter prisenter = new DrawPresenter();
prisenter.Show();
Console.ReadLine();
}
public abstract class BasePresenter<TView> : IPrisenter<TView>
where TView : IView
{
protected BasePresenter()
{
View = NinjectProgram.Kernel.Get<TView>();
}
protected TView View { get; private set; }
public void Show()
{
View.Show();
}
}
Thank you all, that’s what I wanted to do. Perhaps this will help someone in the future.
static void Main(string[] args)
{
CompositionRoot.Wire(new DependencyModule());
IDrawPresenter prisenter = new DrawPresenter();//kernel.Get<IDrawPresenter>();
prisenter.Show();
Console.ReadLine();
}
public class CompositionRoot
{
private static IKernel _ninjectKernel;
public static void Wire(INinjectModule module)
{
_ninjectKernel = new StandardKernel(module);
}
public static T Resolve<T>()
{
return _ninjectKernel.Get<T>();
}
}
public class DependencyModule : NinjectModule
{
public override void Load()
{
Bind<IDrawView>().To<DrawWindow>();
}
}
public abstract class BasePresenter<TView> : IPrisenter<TView>
where TView : IView
{
protected BasePresenter()
{
View = CompositionRoot.Resolve<TView>();//NinjectProgram.Kernel.Get<TView>();
}
protected TView View { get; private set; }
}
Also include the presenter in the container and resolve it.
public class DependencyModule : NinjectModule {
public override void Load() {
Bind<IDrawView>().To<DrawWindow>();
Bind<IDrawPresenter>().To<DrawPresenter>();
}
}
All its dependencies, if registered, will also be resolved and injected into the presenter
static void Main(string[] args) {
var kernel = new StandardKernel();
kernel.Load(new DependencyModule());
IDrawPresenter presenter= kernel.Get<IDrawPresenter>();
presenter.Show();
Console.ReadLine();
}
The above is based on
public abstract class BasePresenter<TView> : IPrisenter<TView> where TView : IView {
protected BasePresenter(TView view) {
View = view;
}
protected TView View { get; private set; }
public void Show() {
View.Show();
}
}
public class DrawPresenter : BasePresenter<IDrawView>, IDrawPresenter {
public DrawPresenter(IDrawView view): base(view) {
}
public object SelectedDraws => View.GetGridDraw;
}

Inject different implementations that have same interface in multiple constructor parameters

My goal is to create an object that contains different implementations of an interface and at runtime select the implementation to use. I'm using the Dependency injection in ASP.NET Core.
Code:
public interface IStateRepository : IDbReadRepository<IState> { }
public interface IDbReadRepository<T> : IBaseRepository
{
IReadOnlyList<T> GetAll();
}
public interface IBaseRepository
{
IUserContext UserContext { get; set; }
}
namespace MvcOpinionatedTemplate.Repositories.Dapper
{
public class StateRepository : BaseDbRepository, IStateRepository
{
public StateRepository(IUserContext userContext, IDbConnection dbConnection) : base(userContext, dbConnection) { }
public IReadOnlyList<IState> GetAll()
{
return _dbConnection.Query<State>("SELECT * FROM State").ToList();
}
}
}
namespace Template.Repositories.Local
{
public class StateRepository : BaseRepository, IStateRepository
{
public StateRepository(IUserContext userContext) : base(userContext) { }
public IReadOnlyList<IState> GetAll()
{
var filePath = Path.Combine(AppContext.BaseDirectory, #"Local\json\states.json");
return JsonConvert.DeserializeObject<List<State>>(File.ReadAllText(filePath));
}
}
namespace MvcOpinionatedTemplate.Repositories.Collections
{
public class StateRepositories
{
public IStateRepository Local { get; }
public IStateRepository SqlServer { get; }
public StateRepositories(IStateRepository local, IStateRepository sqlServer)
{
Local = local;
SqlServer = sqlServer;
}
}
}
What I'd like to do is set in the Startup.ConfigureServices():
services.AddTransient<StateRepositories, XXXXX>
I tried this:
services.AddTransient<StateRepositories>(s => new StateRepositories(new Repositories.Local.StateRepository(--UserContext--), new Repositories.Dapper.StateRepository(-UserContext--)));
The problem is how to have DI populate UserContext. I have it defined Startup.ConfigureServices():
services.AddScoped<IUserContext, UserContext>();
How do have DI populate UserContext for the StateRepositories implementations? Or is there a better approach to achieve my goal?
You can register your IStateRepository separately and then inject IEnumerable<IStateRepository> which injects all implementations of IStateRepository.
public interface IStateRepository
{
}
public class LocalRepository : IStateRepository
{
}
public class DapperRepository : IStateRepository
{
}
services.AddTransient<IStateRepository, LocalRepository>()
.AddTransient<IStateRepository, DapperRepository>()
.AddTransient<StateRepositories>();
public class StateRepositories
{
public IStateRepository Local { get; }
public IStateRepository SqlServer { get; }
public StateRepositories(IEnumerable<IStateRepository> repositories)
{
Local = repositories.OfType<LocalRepository>().FirstOrDefault();
SqlServer = repositories.OfType<DapperRepository>().FirstOrDefault();
}
}

Contravariant or invariant interfaces in the same List in C#

I am stuck with a problem about interface covariance and contravariance. I have two generic interfaces:
public interface IConfigConsumer<T> where T : IConfiguration
{
void Load(T configuration);
}
public interface IConfigProvider<out T> where T : IConfiguration
{
T Configuration { get; }
}
IConfiguration is just an empty interface (marker). There is a third interface:
public interface IConfigurable<T> : IConfigConsumer<T>, IConfigProvider<T>
where T : IConfiguration
{
void Reset();
}
I would like to have a list with all the IConfigurable implementations (regardless of the concrete type of T).
Since IConfigProvider is covariant I can have a list of IConfigProviders, but IConfigConsumer is invariant so I can't have a List like this:
var consumers = new List<IConfigConsumer<IConfiguration>>();
The best would be to have a list of IConfigurable<IConfiguration> since I will need the functionalities defined in both interfaces.
I just can't find a way to do this.
A workaround could be to just get rid of the type parameter in the IConfigConsumer interface and define the Load method as follows:
void Load(IConfiguration configuration)
But that would "hurt" the type safety a little bit since I could Load a type ConfigA into a ConfigConsumer that expects ConfigB and it would throw an exception only in runtime when I would try and cast it to ConfigB in the Load method.
Here is my complete sample code:
public interface IConfiguration
{
}
public interface IConfigurable<T> : IConfigConsumer<T>, IConfigProvider<T>
where T : IConfiguration
{
void Reset();
}
public interface IConfigConsumer<T> where T : IConfiguration
{
void Load(T configuration);
}
public interface IConfigProvider<out T> where T : IConfiguration
{
T Configuration { get; }
}
public abstract class ConfigBase : IConfiguration { }
public class TimeSynchronizationConfig : ConfigBase, ICloneable
{
public static string[] DefaultNtpServers = new string[] { "0.pool.ntp.org", "time1.google.com" };
public string NTPServer1 { get; set; } = DefaultNtpServers[0];
public string NTPServer2 { get; set; } = DefaultNtpServers[1];
public object Clone()
{
return new TimeSynchronizationConfig
{
NTPServer1 = NTPServer1,
NTPServer2 = NTPServer2
};
}
}
public class DataPruningConfig : ConfigBase, ICloneable
{
public const int DefaultPruningThresholdHours = 72;
public int PruningThresholdHours { get; set; }
public DataPruningConfig()
{
PruningThresholdHours = DefaultPruningThresholdHours;
}
public DataPruningConfig(int pruningThresholdHours)
{
PruningThresholdHours = pruningThresholdHours;
}
public object Clone()
{
return new DataPruningConfig(PruningThresholdHours);
}
}
public class A : IConfigurable<TimeSynchronizationConfig>
{
public TimeSynchronizationConfig Configuration => new TimeSynchronizationConfig();
public void Load(TimeSynchronizationConfig configuration)
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
}
public class B : IConfigurable<DataPruningConfig>
{
public DataPruningConfig Configuration => new DataPruningConfig();
public void Load(DataPruningConfig configuration)
{
throw new NotImplementedException();
}
public void Reset()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
var configurables = new List<IConfigurable<IConfiguration>>();
var a = new A();
var b = new B();
configurables.Add(a);
configurables.Add(b);
ProcessConfigurables(configurables);
}
static void ProcessConfigurables(IEnumerable<IConfigurable<IConfiguration>> configurables)
{
foreach (var c in configurables)
{
}
}
}
I started to doubt what I want is even possible. Do you have any idea?
Thank you in advance for all your help!

c# Factory for concrete implementation of generic base class

I have a Base class which is generic.
I have a concrete class which implements the base class.
How would I create a factory class/method for delivering different types of concrete classes?
Here an example:
public class ReceiverBase<T>
where T : IInterpreter
{ ... }
public class SpecialReceiver : ReceiverBase<OwnInterpreter> { ... }
public class ReceiverFactory<T>
where T : ReceiverBase<IInterpreter>, new()
public T Create(string type) {
switch(type) {
default:
return new SpecialReceiver();
}
}
}
The problem is that ReceiverBase seems not to be possible because the compiler only wants classes as Constraints, not interfaces.
And the second problem is that I cannot convert SpecialReceiver to T.
So is there a way to get this working?
=== EDIT: Added example according to first answer ===
public interface IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
public void Dispose()
{
throw new NotImplementedException();
}
public void DoSomething() { }
}
public abstract class ReceiverBase<T>
where T : IInterpreter
{
public T MyReceiver { get; set; }
internal abstract void Start();
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter, new()
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
MyReceiver = new T();
}
}
public class ReceiverFactory<T>
where T : IInterpreter, new()
{
public static ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The Problem is: MyReceiver.DoSomething(); will not work.
Additionally I would have to call the factory like this: ReceiverFactory<OwnInterpreter>.Create(""); I'd like to have it that way: ReceiverFactory.Create("SpecialReceiver");
You can use generic method in your factory:
class Program
{
static void Main(string[] args)
{
var own = ReceiverFactory.Create<OwnInterpreter>();
var other = ReceiverFactory.Create<OtherInterpreter>();
own.Start();
other.Start();
Console.ReadLine();
}
}
interface IInterpreter
{
void DoSomething();
}
class OwnInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Own"); }
}
class OtherInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Other"); }
}
abstract class ReceiverBase<T> where T: IInterpreter, new()
{
public T Interpreter { get; set; }
public ReceiverBase()
{
Interpreter = new T();
}
public void Start()
{
Interpreter.DoSomething();
}
}
class SpecialReceiver : ReceiverBase<OwnInterpreter> { }
class OtherReceiver : ReceiverBase<OtherInterpreter> { }
static class ReceiverFactory
{
private static Dictionary<string, object> factories = new Dictionary<string, object>();
static ReceiverFactory()
{
RegisterFactory(() => new SpecialReceiver());
RegisterFactory(() => new OtherReceiver());
}
public static void RegisterFactory<T>(Func<ReceiverBase<T>> factory) where T : IInterpreter, new()
{
factories.Add(typeof(T).FullName, factory);
}
public static ReceiverBase<T> Create<T>() where T : IInterpreter, new()
{
var type = typeof(T);
return ((Func<ReceiverBase<T>>)factories[type.FullName]).Invoke();
}
}
In fact, you do not need "new()" constraint here, since you use factories.
I suggest you to change your code to:
public class ReceiverBase<T> where T : IInterpreter
{
}
public interface IInterpreter
{
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
}
public class ReceiverFactory<T> where T : IInterpreter, new()
{
public ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The reason why you cannot just return T in your case is, that there is no implicit conversion between SpecialReceiver and ReceiverBase<IInterpreter>.
I was able to find a solution which suits my needs.
I've added another interface IReciver which defines the properties and members I really need. The factory method returns IReceiver so I can omit all binding issues whith generics. Sometimes it is just that easy. :)
public interface IInterpreter { }
public interface IReceiver
{
bool Enabled { get; set; }
}
public class OwnInterpreter : IInterpreter
{
public void DoSomething() { }
}
public abstract class ReceiverBase<T> : IReceiver
where T : IInterpreter, new()
{
public T MyReceiver { get; set; }
internal abstract void Start();
private bool _isEnabled;
public bool Enabled { get { return _isEnabled; } set { _isEnabled = value; OnEnable(value); } }
internal abstract void OnEnable(bool isEnabled);
protected ReceiverBase()
{
MyReceiver = new T();
}
}
public class SpecialReceiver : ReceiverBase<OwnInterpreter>
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
// just for testing puropses
MyReceiver = new OwnInterpreter();
}
internal override void OnEnable(bool isEnabled)
{
MyReceiver = isEnabled ? new OwnInterpreter() : null;
}
}
public class ReceiverFactory
{
public static IReceiver Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver();
}
}
}
public class Program
{
[STAThread]
public static void Main()
{
ReceiverFactory.Create("");
}
}

using generic method in abstract class with child class result

I'm working to DRY some code up and I'm running into the following situation. I've reworked the code to provide a better example of the scenario.
namespace SourceCode
{
public interface IFactory
{
public baseClass GenerateClass();
public bool IsUsable();
}
public abstract baseClass
{
...
}
public AClass:baseClass
{
...
}
public class FactoryA:IFactory
{
public baseClass GenerateClass()
{
return new AClass();
}
public bool IsUsable(){
{
return true if some condition;
}
}
public BClass:baseClass
{
...
}
public class FactoryB:IFactory
{
public baseClass GenerateClass()
{
return new BClass();
}
public bool IsUsable(){
{
return true if some condition;
}
}
public static class FactoryProvider
{
List<IFactory> factories
static FactoryProvider()
{
factories.Add(new FactoryA());
factories.Add(new FactoryB());
}
static List<baseClass> GetClasses()
{
return (from f in factories where f.IsUsable() select f).ToList();
}
}
}
namespace SourceCode.Tests
{
public class baseTests
{
public T GenericMethod<T>(){...}
}
public class ClassATests:baseTests
{
public void Test1()
{
... generic used in a method provided by the base class
}
}
public class ClassBTests:baseTests
{
public void Test1()
{
... generic used in a method provided by the base class
}
}
}
So the problem in my tests is that there are tests that will have to happen for every child class.
UPDATE=======================
I was able to solve my issue by doing the following.
namespace SourceCode.Tests
{
public class baseTests<I> where I: baseClass
{
public void Test1()
{
var result = GenericMethod<I>();
// The generic method will use ClassA for ClassATests
// and ClassB for ClassBTests
}
public T GenericMethod<T>(){...}
}
public class ClassATests:baseTests<ClassA>
{
}
public class ClassBTests:baseTests<ClassB>
{
}
}
Making your current A class generic could solve problems:
abstract class A
{
// protected members...
protected abstract A InternalGetData(List<A> src);
public void SharedMethodHappensAlways()
{
List<A> src = new List<A>();
var childResult = InternalGetData(src);
}
}
abstract class A<T> : A
where T: A
{
public T GetData(List<A> src)
{
return src.OfType<T>().FirstOrDefault();
}
protected override A InternalGetData(List<A> src)
{
return GetData(src);
}
}
class B : A<B>
{
}
class C : A<C>
{
}
Sample usage:
List<A> src = new List<A>() { new B(), new C() };
B b = new B();
b.SharedMethodHappensAlways();
B firstB = b.GetData(src); // returns first instance of B
C firstC = new C().GetData(src);

Categories