Reputation: 34189
I have a base service class with virtual method that sets the properties of an object and returns that object.
Then i have one more service which derived from the base service and also overrides the base method. In overriden method, the derived service executes base.DowWork()
to set common properties, and then also sets additional properties.
So based on articles here and here I was able to do this using generics.
public interface IResult
{
}
public class BaseResult : IResult
{
public string CommonProperties { get; set; }
}
public class AdditionalResult : BaseResult
{
public string AdditionalProperties { get; set; }
}
public interface IService<T> where T : IResult
{
T DoWork();
}
public class BaseService<T> : IService<T> where T : BaseResult, new()
{
public virtual T DoWork()
{
var t = new T();
t.CommonProperties = "Some Value";
return t;
}
}
public class AdditionalService : BaseService<AdditionalResult>
{
public override AdditionalResult DoWork()
{
var addtionalResult = base.DoWork();
addtionalResult.CommonProperties = "Override value that was set by BaseService";
addtionalResult.AdditionalProperties = "Set additional properties";
return addtionalResult;
}
}
So far so good
Now i want to create a Factory method that will return the instance of a service based on some type. The application will use the factory to get service instance and call DoWork() like below
class Program
{
static void Main()
{
var factory = new MyFactory();
var service = factory.GetService(0);
var iresult = service.DoWork();
// do something here with IResult
}
}
below is the factory method
public class MyFactory
{
public IService<IResult> GetService(int someType)
{
if (someType == 0)
{
return (IService<IResult>)new BaseService<BaseResult>();
}
if (someType == 1)
{
return (IService<IResult>)new AdditionalService();
}
// note I may have more types and services here. But for simplicity i am using only 2
throw new NotSupportedException();
}
}
However i am not able to figure out what should be the signature of this factory method? Based on suggestions here I'm casting service instance but while executing the application I am getting runtime exception
Unable to cast object of type 'BaseService 1[BaseResult]' to type 'IService 1[IResult]'
if i don't cast the service instance in the Factory then i get compile time error
Cannot implicitly convert type 'BaseService' to 'IService'. An explicit conversion exists (are you missing a cast?)
Upvotes: 2
Views: 1544
Reputation: 62318
See SO question Understanding Covariant and Contravariant interfaces in C#.
You want to use covariance (out
keyword). If you add it to your IService
interface generic type it works as expected.
public interface IService<out T> where T : IResult
I know SO prefers not to post links but I can't possibly write anything more or better than already answered in that question.
Upvotes: 4