Я пытаюсь вернуть реализацию универсального абстрактного класса с использованием фабрики, чтобы вызывающей стороне не нужно было знать, что вернул конкретный тип. Но не удалось.
public class Car:IMoveable { }
public interface IMoveable { }
public abstract class Service<TEntity>
{
public abstract void PerformService(TEntity t);
}
public class VehicleService : Service<IMoveable>
{
public override void PerformService(IMoveable t) { }
}
public class DefaultService : Service<object>
{
public override void PerformService(object t){ }
}
public static class ServiceFactory
{
public static Service<TEntity> CreateService<TEntity>(TEntity entity) where TEntity : class
{
if (typeof(IMoveable).IsAssignableFrom(typeof(TEntity)))
{
// run time error here as returns null
return new VehicleService() as Service<TEntity>;
//compiler error
return (Service<TEntity>) new VehicleService();
}
else
{
return new DefaultService() as Service<TEntity>;
}
}
}
static void Main(string[] args)
{
var car = new Car();
var service = ServiceFactory.CreateService(car);
}
Проблема в том, что служба после createService всегда имеет значение null.
Я подозреваю, что проблема в том, что TEntity передается как Car, тогда как VehicleService реализуется как IMovebale. Но никак не могу понять, как это сделать, и возможно ли это вообще?
Заранее спасибо.
Вам нужно пометить TEntity
общий тип Service
как контравариантный с помощью ключевого слова in
и использовать базовый интерфейс вместо базового абстрактного класса, тогда будет работать приведение к универсальному базовому типу:
public interface Service<in TEntity>
{
void PerformService(TEntity t);
}
В вашем примере TEntity - это Car. Итак, вы пытаетесь преобразовать объект типа Service<IMoveable> в тип Service<Car> ( Service<TEntity> ), но это невозможно, поскольку они не являются контравариантными. Вы можете пометить параметр типа ключевым словом in, как описано здесь: docs.microsoft.com/en-us/dotnet/standard/generics/…