在具有 WCF 服务的 C# 服务器中使用穷人的 DI

Using Poor man's DI in C# server with WCF services

我正在用 C# 和 WCF 构建服务器。我有我的 ServiceContract 以及客户端应用程序使用的方法。但是整个逻辑在不同的 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 显示了如何执行此操作的示例。

您可以自定义该答案中的代码以添加更多依赖项。