from my title it might be a little hard to understand what I'm trying to achieve, so I'll go a little further into detail.
I have the following interface:
public interface IModelBuilder<T>
where T : IStandardTemplateTemplate
{
M Build<M>(T pTemplate, params object[] pParams) where M : BaseModel;
}
Now I want to implement the interface in my actual builder. The builder I use to map different object types. So this looks as follows:
public class BusinessModelBuilder : IModelBuilder<IBusinessTemplate>
{
public virtual M Build<M>(IBusinessTemplate pTemplate, params object[] pParams) where M : BussinessModel
{
var businessModel = Activator.CreateInstance<M>();
// map data
return businessModel;
}
}
Now the problem is the following. I can't get the constraint to work. Since I defined the constraint on the interface it won't let me use a different constraint on my actual method, even though my BusinessModel inherits from BaseModel. It keeps telling me my constraint M must match the constraint from the interface. I tried several different approaches, but none seem to work.
Does anyone know if or how this can be achieved? I just want to tell my constraint in the interface that inherited models are allowed.
Here's a short but complete example of your problem:
public class Parent { }
public class Child { }
public interface Interface
{
void Foo<T>() where T : Parent;
}
public class Implementation : Interface
{
public void Foo<T>() where T : Child
{
}
}
This won't compile, for the same reason that yours won't. The implementation of the interface method must have the exact same constraint on the generic argument, it can't have a more restrictive constraint.
Your Build
method can only constrain the type to BaseModel
, not BussinessModel
.
If you alter your IModelBuilder
interface to add an additional class level generic argument, and then use that as the constraint, then you can get the desired functionality:
public interface IModelBuilder<T, Model>
where T : IStandardTemplateTemplate
where Model : BaseModel
{
M Build<M>(T pTemplate, params object[] pParams) where M : Model;
}
public class BusinessModelBuilder : IModelBuilder<IBusinessTemplate, BussinessModel>
{
public virtual M Build<M>(IBusinessTemplate pTemplate, params object[] pParams)
where M : BussinessModel
{
var businessModel = Activator.CreateInstance<M>();
// map data
return businessModel;
}
}
This solution is based in part on Reed's answer but which takes it a step further.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With