如何从界面创建实例?

时间:2017-12-14 09:13:31

标签: c#

我有这些接口:

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”类型的构造函数。

那么如何从界面正确实例化一个类?

4 个答案:

答案 0 :(得分:7)

你做不到。您将需要一个依赖注入容器,该容器知道您希望创建ISomething的每个ConcreteSomething。类和接口之间的这种连接并没有神奇地建立,只是想象你有两个实现ISomething的类。

您可以自己构建该容器,使用接口类型的Dictionary到类类型,然后执行return (TService)Activator.CreateInstance(this.TypeMappings[typeof(TService)], args);,或者您可以使用现有的依赖注入容器之一。但是你需要这种映射。

答案 1 :(得分:1)

我想在这个答案的前言中说:我真的建议使用适当的DI容器,例如Unity,Ninject或Autofac。看起来你可能正试图重新发明轮子,并试图创建服务定位器反模式,这两者都可能是坏的。

无论如何,要回答你的问题:你必须创建一个具体实现的实例。

interfaceICustomerService)只是一个合同,任何实现它(具体实现 - 在你的情况下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()));