I have an abstract base model class which contains some shared properties. On top of that I have a number of minor interfaces, which defines what processes a model will be available for.
Here is an example of the base class, an interface and a derived class:
public abstract class ModelBase
{
public ModelBase(string name)
{
Name = name;
}
public int Id { get; private set; }
public int Name { get; private set; }
}
public interface ISupportProcessA
{
public decimal Amount { get; }
}
public class ModelDerived : ModelBase
{
public ModelDerived(string name) : base(name) { }
public decimal Amount { get; private set; }
}
To perform some work with the base model I also have an abstract base processor class, with some shared functionaliy and some derived processor classes, one for each process. It could look like this:
public abstract class ProcessorBase
{
private readonly ModelBase model;
public ProcessorBase(ModelBase model)
{
this.model = model;
}
// ...some shared methods
}
public class ProcessorA : ProcessorBase
{
private readonly ISupportProcessA model;
public ProcessorA(ISupportProcessA model) : base(model)
{
this.model = model;
}
// ...some specific methods
}
Now here lies the problem. Because ISupportProcessA
is not (to the compilers knowledge) related to ModelBase
and can therefore not be given as input in base()
. That makes sense.
So what I tried to do was to create an interface IModelBase
which I use instead of ModelBase
. However, this gives some issues once I connect to Entity Framework, which doesn't work well with interfaces (or maybe it's just me?).
So here is my question:
Is there anyway to request a class which both derives from ModelBase
but also implements ISupportProcessA
?
You can get some of the way there with generics:
public class ProcessorA<TModel> : ProcessorBase where TModel : ModelBase, ISupportProcessA
{
private readonly ISupportProcessA model;
public ProcessorA(TModel model) : base(model)
{
this.model = model;
}
// ...some specific methods
}
This is a bit ugly however, as you need to create a new ProcessorA<ModelDerived>
, rather than just a ProcessorA
.
You can add more boilerplate to make things a bit nicer:
public abstract class ProcessorBase
{
protected abstract ModelBase ModelForBase { get; }
// ...some shared methods
}
public abstract class ProcessorA : ProcessorBase
{
public static ProcessorA Create<TModel>(TModel model) where TModel : ModelBase, ISupportProcessA
{
return new ProcessorA<TModel>(model);
}
// Abstract specific methods
public abstract void SomeSpecificMethod();
}
public class ProcessorA<TModel> : ProcessorA where TModel : ModelBase, ISupportProcessA
{
protected override ModelBase ModelForBase => model;
private readonly TModel model;
public ProcessorA(TModel model)
{
this.model = model;
}
// Specific method overrides
public override void SomeSpecificMethod()
{
}
}
This means you can do ProcessorA processor = ProcessorA.Create(new Model())
, but at the cost of a lot more boilerplate.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.