如何根据合同层次结构实例化与服务 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
被注入到类型为 IServiceBase
、IService
或 IOtherService
的组件中,容器将能够解析 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 属性 的键实例化=] 并且它的接口类型继承自父客户端中定义的 属性 类型。
我想根据合同层次实例化与服务的关联 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
被注入到类型为 IServiceBase
、IService
或 IOtherService
的组件中,容器将能够解析 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 属性 的键实例化=] 并且它的接口类型继承自父客户端中定义的 属性 类型。