如何根据合同层次结构实例化与服务 class 的关联?

How to instantiate an association to a service class based on the contract hierarchy?

我想根据合同层次实例化与服务的关联 class。考虑以下代码:

public interface IServiceBase
{
    void DoSomething();
}

public interface IService : IServiceBase
{
    void DoSomeOtherthing();
}

public interface IOtherService : IServiceBase
{
    void DoAnotherthing();
}
public class ServiceBase : IServiceBase
{
    public virtual void DoSomething()
    {
        Console.WriteLine("Base service implementation");
    }
}
public class Service : ServiceBase, IService
{
    public void DoSomeOtherthing()
    {
        Console.WriteLine("New service implementation");
    }

    public override void DoSomething()
    {
        base.DoSomething();
        Console.WriteLine("Child service implementation");
    }
}
public class OtherService : ServiceBase, IOtherService
    {
        public void DoAnotherthing()
        {
            Console.WriteLine("Another child service implementation");
        }
    }
public abstract class ClientBase
{
    public IServiceBase Service { get; set; }
}

public class Client : ClientBase
{
    public IService Service { get; set; }
}

public class OtherClient : ClientBase
{
    public IOtherService Service { get; set; }
}

如果一个 IoC 容器尝试注入 ClientBase 的 Service 属性,它会发现注册为 IServiceBase 的两种类型:IService 和 IOtherService。 IoC 如何决定使用哪种类型适合实例化?这个决定取决于具体的客户端class:他们知道他们实际依赖于哪个继承接口的客户端或其他客户端:IService或IOtherService对应于Service或OtherService类型。

通常IoC/DI容器配置一个具体的服务接口。它们不会自动处理 IService 的注入,即使您已经在最后一个接口实现 IService 时配置了 IOtherService。即只能注入IOtherService.

的直接实现

例如,在 Castle Windsor 中,您一次注册多个服务的实现如下:

container.Register
(
     // OtherService implements these interfaces, right?
     Component.For<IServiceBase, IService, IOtherService>()
              .ImplementedBy<OtherService>()
);

也就是说,一旦 OtherService 被注入到类型为 IServiceBaseIServiceIOtherService 的组件中,容器将能够解析 OtherService.

最后我找到了一个解决方案,它将组合逻辑封装在 Resolver(Composer) 中 class;附有一些关于 属性 服务定义的合同。 我们定义了 Lazy 属性,其中 T 是服务接口的类型。当我修复以下代码时:

public interface IServiceBase
{
    void DoSomething();
}

public interface IService : IServiceBase
{
    void DoSomeOtherthing();
}

public interface IOtherService : IServiceBase
{
    void DoAnotherthing();
}
public class ServiceBase : IServiceBase
{
    public virtual void DoSomething()
    {
        Console.WriteLine("Base service implementation");
    }
}
public class Service : ServiceBase, IService
{
    public void DoSomeOtherthing()
    {
        Console.WriteLine("New service implementation");
    }

    public override void DoSomething()
    {
        base.DoSomething();
        Console.WriteLine("Child service implementation");
    }
}
public class OtherService : ServiceBase, IOtherService
    {
        public void DoAnotherthing()
        {
            Console.WriteLine("Another child service implementation");
        }
    }
public abstract class ClientBase
{
    private IServiceResolver _serviceResolver;
    public ClientBase()
    {
        _serviceResolver = new ServiceResolver();
        _serviceResolver.Resolve(this);
    }
    [Resolve(isParentContract:true)]
    public Lazy<IServiceBase> Service { get; set; }
}

public class Client : ClientBase
{
    [Resolve]
    public Lazy<IService> Service { get; }
}

public class OtherClient : ClientBase
{
    [Resolve]
    public Lazy<IOtherService> Service { get; }
}

ServiceResolver 的职责是找到所有由 Resolve 属性标记的 Lazy 属性,并创建真实合同的 Lazy 实例,该实例可通过将合同与父服务合同相匹配来推断。这样,由 ResolveAttribute 标记为 isParentContract:true 的 属性 将由继承的客户端 [=17] 中定义的类型 a 属性 的键实例化=] 并且它的接口类型继承自父客户端中定义的 属性 类型。