我有这些接口:
public interface _IService<T>
{
T Get(int id);
Task<T> SaveAsync(T entity);
Task<bool> DeleteAsync(int id);
}
public interface ICustomerService :
IService<Customer>
{
IEnumerable<Customer> GetMany(IEnumerable<int> ids);
}
我还有一个抽象类和一个具体的类:
public abstract class Service : IDisposable
{
protected readonly IUnitOfWork unitOfWork;
protected Service(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void Dispose()
{
if (unitOfWork != null)
{
unitOfWork.Dispose();
}
}
}
public class CustomerService : Service, ICustomerService
{
public CustomerService(IUnitOfWork unitOfWork)
: base(unitOfWork)
{ }
//Implementation here...
}
一切都按预期工作。
现在我想添加通用工厂模式来实例化各种服务。所以我试着这样做:
public TService GetService<TService>()
{
object[] args = new object[] { (unitOfWork) };
return (TService)Activator.CreateInstance(typeof(TService), args);
}
使用如下:
var customerService = GetService<ICustomerService>();
但是,抛出以下异常:
未找到“ICustomerService”类型的构造函数。
那么如何从界面正确实例化一个类?
答案 0 :(得分:7)
你做不到。您将需要一个依赖注入容器,该容器知道您希望创建ISomething
的每个ConcreteSomething
。类和接口之间的这种连接并没有神奇地建立,只是想象你有两个实现ISomething
的类。
您可以自己构建该容器,使用接口类型的Dictionary到类类型,然后执行return (TService)Activator.CreateInstance(this.TypeMappings[typeof(TService)], args);
,或者您可以使用现有的依赖注入容器之一。但是你需要这种映射。
答案 1 :(得分:1)
我想在这个答案的前言中说:我真的建议使用适当的DI容器,例如Unity,Ninject或Autofac。看起来你可能正试图重新发明轮子,并试图创建服务定位器反模式,这两者都可能是坏的。
无论如何,要回答你的问题:你必须创建一个具体实现的实例。
interface
(ICustomerService
)只是一个合同,任何实现它(具体实现 - 在你的情况下CustomerService
)将提供该接口定义的功能。
您需要具体类的实例:
private readonly Dictionary<Type, Type> _concreteImplementations = new Dictionary<Type, Type>();
public Factory()
{
_concreteImplementations.Add(typeof(ICustomerService), typeof(CustomerService));
}
public TService GetService<TService>()
{
Type toInstantiate;
if (_concreteImplementations.TryGetValue(typeof(TService), out toInstantiate))
{
object[] args = new object[] { (unitOfWork) };
return (TService)(object)Activator.CreateInstance(toInstantiate, args);
}
else
{
return null;
}
}
答案 2 :(得分:0)
您无法实例化接口的实例。您只能实例化实现接口的具体类型(类或结构)。
答案 3 :(得分:0)
你做不到。但是你可以通过使用具体的类来间接获得相同的结果。
CustomerService c = new CustomerService();
ICustomerService i = ((ICustomerService)Activator.CreateInstance(c.GetType()));