【问题标题】:How to create instance from an interface?如何从接口创建实例?
【发布时间】:2017-12-14 09:13:30
【问题描述】:

我有这些接口:

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

那么我怎样才能正确地从接口实例化一个类呢?

【问题讨论】:

  • 您不会从接口创建类实例。您创建一个类实例来满足接口。但是您仍然需要显式创建类实例(或使用某种 IoC 容器注册该类 - 但不要过早地这样做)。看起来很像你过度工程。
  • 看来你要做的是重新发明依赖注入。查一下,很可能你不需要自己构建任何东西。
  • 或者你正在重新发明像 moq 这样的模拟框架。
  • 如果你只是改变'var customerService = GetService();'到 'var customerService = GetService();'?
  • @Mirt 虽然这行得通,但我认为这不是 OP 的目的:)

标签: c#


【解决方案1】:

你不能。您将需要一个依赖注入容器,该容器知道您希望为每个 ISomething 创建一个 ConcreteSomething。类和接口之间的这种联系并不是神奇地建立起来的,想象一下你有两个类实现了ISomething

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

【讨论】:

    【解决方案2】:

    我想在这个答案的开头说:我真的建议为此使用适当的 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;
        }
    }
    

    【讨论】:

      【解决方案3】:

      您不能实例化接口的实例。您只能实例化实现接口的具体类型(类或结构)。

      【讨论】:

        【解决方案4】:

        你不能。但是你可以通过使用具体类间接获得相同的结果。

        CustomerService  c = new CustomerService();
        ICustomerService i = ((ICustomerService)Activator.CreateInstance(c.GetType()));
        

        【讨论】:

          猜你喜欢
          • 2011-10-30
          • 1970-01-01
          • 1970-01-01
          • 2016-08-13
          • 1970-01-01
          • 1970-01-01
          • 2020-05-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多