在具有 WCF 服务的 C# 服务器中使用穷人的 DI
Using Poor man's DI in C# server with WCF services
我正在用 C# 和 WCF 构建服务器。我有我的 Service 和 Contract 以及客户端应用程序使用的方法。但是整个逻辑在不同的 class 中分离:BusinessLogic。我将在 BussinessLogic 中注入我需要的所有内容,例如 repositories/database 提供程序或存储在内存中的其他数据。我使用 穷人的依赖 来构建我的 BussinessLogic(这是我的组合根)。这是一个控制台应用程序,所以 BussinessLogic 在 Main(string[] args)
方法中是 creaed/resolved。
我的问题是 WCF 服务是使用无参数构造函数创建的,独立于服务器的其余部分。每次在客户端使用时都会创建它们。
这是我的服务器的样子:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(ServiceLayer), new Uri("net.tcp://localhost:8005"));
host.Open();
Console.WriteLine("Running... Press key to stop");
Console.ReadKey();
}
我的服务:
[ServiceContract]
public interface IServiceContract
{
[OperationContract]
...
}
public class ServiceLayer : IServiceContract
{
IBusinessLogic _businessLogic;
public ServiceLayer(IBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
// Here, I would like to use IBusinessLogic
...
}
我找到了如何使用 IoC here 来做到这一点(我没有测试它),但我正在寻找一个最好的解决方案 穷人的依赖性,没有任何容器或工具,只有 C# 和 .NET。如果没有任何解决方案与 IoC 一样好或接近 IoC,请发表评论。
如果您围绕 commands and queries, it becomes very easy to create your WCF service as a thin maintenance free layer with just one service class 构建应用程序模型。
当您只有一个服务 class 时,您可以将此服务 class 本身用作 Composition Root or Humble Object,这意味着您不需要向服务 [=注入任何依赖项] =19=]。这样一来,您就不必在依赖项注入方面对 WCF 管道进行任何集成!
当您应用这些模式时,您可以将您的服务缩减为以下代码:
[ServiceKnownType(nameof(GetKnownTypes)]
public class CommandService
{
[OperationContract, FaultContract(typeof(ValidationError))]
public void Execute(dynamic command) {
CreateCommandHandler(command.GetType()).Handle(command);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider cap) {
yield return typeof(ShipOrder);
yield return typeof(CancelOrder);
yield return typeof(ConfirmOrder);
}
// Singletons
private static IUserContext userContext = new WcfUserContext();
private static dynamic CreateCommandHandler(Type commandType)
{
var context = new DbContext();
if (commandType == typeof(ShipOrder))
return Decorate(new ShipOrderHandler(context));
if (commandType == typeof(CancelOrder))
return Decorate(new CancelOrderHandler(context));
if (commandType == typeof(ConfirmOrder))
return Decorate(new ConfirmOrderHandler(context, userContext));
throw new ArgumentException("Unknown: " + commandType.FullName);
}
private static ICommandHandler<T> Decorate<T>(ICommandHandler<T> handler) {
return new WcfExceptionTranslatorCommandHandlerDecorator(
new LoggingCommandHandlerDecorator(
new Logger(),
new AuditTrailingCommandHandlerDecorator(
new PermissionCheckerCommandHandlerDecorator(
new ValidationCommandHandlerDecorator(
new TransactionCommandHandlerDecorator(
handler))))));
}
}
穷人的 DI 现在称为 Pure DI。
您可以使用纯 DI 编写 WCF 应用程序。您需要在 Composition Root.
中执行此操作
在 WCF 应用程序中,复合根是一个自定义的 ServiceHostFactory。
This answer 显示了如何执行此操作的示例。
您可以自定义该答案中的代码以添加更多依赖项。
我正在用 C# 和 WCF 构建服务器。我有我的 Service 和 Contract 以及客户端应用程序使用的方法。但是整个逻辑在不同的 class 中分离:BusinessLogic。我将在 BussinessLogic 中注入我需要的所有内容,例如 repositories/database 提供程序或存储在内存中的其他数据。我使用 穷人的依赖 来构建我的 BussinessLogic(这是我的组合根)。这是一个控制台应用程序,所以 BussinessLogic 在 Main(string[] args)
方法中是 creaed/resolved。
我的问题是 WCF 服务是使用无参数构造函数创建的,独立于服务器的其余部分。每次在客户端使用时都会创建它们。
这是我的服务器的样子:
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(ServiceLayer), new Uri("net.tcp://localhost:8005"));
host.Open();
Console.WriteLine("Running... Press key to stop");
Console.ReadKey();
}
我的服务:
[ServiceContract]
public interface IServiceContract
{
[OperationContract]
...
}
public class ServiceLayer : IServiceContract
{
IBusinessLogic _businessLogic;
public ServiceLayer(IBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
// Here, I would like to use IBusinessLogic
...
}
我找到了如何使用 IoC here 来做到这一点(我没有测试它),但我正在寻找一个最好的解决方案 穷人的依赖性,没有任何容器或工具,只有 C# 和 .NET。如果没有任何解决方案与 IoC 一样好或接近 IoC,请发表评论。
如果您围绕 commands and queries, it becomes very easy to create your WCF service as a thin maintenance free layer with just one service class 构建应用程序模型。
当您只有一个服务 class 时,您可以将此服务 class 本身用作 Composition Root or Humble Object,这意味着您不需要向服务 [=注入任何依赖项] =19=]。这样一来,您就不必在依赖项注入方面对 WCF 管道进行任何集成!
当您应用这些模式时,您可以将您的服务缩减为以下代码:
[ServiceKnownType(nameof(GetKnownTypes)]
public class CommandService
{
[OperationContract, FaultContract(typeof(ValidationError))]
public void Execute(dynamic command) {
CreateCommandHandler(command.GetType()).Handle(command);
}
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider cap) {
yield return typeof(ShipOrder);
yield return typeof(CancelOrder);
yield return typeof(ConfirmOrder);
}
// Singletons
private static IUserContext userContext = new WcfUserContext();
private static dynamic CreateCommandHandler(Type commandType)
{
var context = new DbContext();
if (commandType == typeof(ShipOrder))
return Decorate(new ShipOrderHandler(context));
if (commandType == typeof(CancelOrder))
return Decorate(new CancelOrderHandler(context));
if (commandType == typeof(ConfirmOrder))
return Decorate(new ConfirmOrderHandler(context, userContext));
throw new ArgumentException("Unknown: " + commandType.FullName);
}
private static ICommandHandler<T> Decorate<T>(ICommandHandler<T> handler) {
return new WcfExceptionTranslatorCommandHandlerDecorator(
new LoggingCommandHandlerDecorator(
new Logger(),
new AuditTrailingCommandHandlerDecorator(
new PermissionCheckerCommandHandlerDecorator(
new ValidationCommandHandlerDecorator(
new TransactionCommandHandlerDecorator(
handler))))));
}
}
穷人的 DI 现在称为 Pure DI。
您可以使用纯 DI 编写 WCF 应用程序。您需要在 Composition Root.
中执行此操作在 WCF 应用程序中,复合根是一个自定义的 ServiceHostFactory。
This answer 显示了如何执行此操作的示例。
您可以自定义该答案中的代码以添加更多依赖项。