在带有 WCF 服务的 C# 服务器中使用穷人的 DI [重复]
Posted
技术标签:
【中文标题】在带有 WCF 服务的 C# 服务器中使用穷人的 DI [重复]【英文标题】:Using Poor man's DI in C# server with WCF services [duplicate] 【发布时间】:2016-03-05 19:52:14 【问题描述】:我正在用 C# 和 WCF 构建服务器。我有我的 Service 和 Contract 以及客户端应用程序使用的方法。但是整个逻辑被分离在不同的类中:BusinessLogic。我将在 BussinessLogic 中注入我需要的所有内容,例如存储库/数据库提供程序或存储在内存中的其他数据。我使用 穷人的依赖 来构建我的 BussinessLogic(这是我的作文根)。它是一个控制台应用程序,因此在 Main(string[] args)
方法中创建/解析了 BussinessLogic。
我的问题是 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 一样好的或接近它的解决方案,请发表评论。
【问题讨论】:
【参考方案1】:如果您围绕commands 和queries 为您的应用程序建模,那么将您的WCF 服务创建为thin maintenance free layer with just one service class 将变得非常容易。
当您只有一个服务类时,您可以将此服务类本身用作Composition Root 或Humble Object,这意味着您不需要将任何依赖项注入服务类。当涉及到依赖注入时,这完全可以防止您在 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))))));
【讨论】:
感谢@Steven,我将不得不阅读您的几篇文章才能完全理解您的答案,这有点......不完全清楚。但据我现在所见,您拥有CommandService
而没有实现其接口(合同),这有点奇怪。第二件事,我现在正在查看solidservices
项目,这个 Bootstrapper 静态类看起来有点像 Service Locator。不是注入的,是全局静态类
嗨@Tom,WCF 可以在不使用界面的情况下完美地工作,但是如果界面真的与您相关,您可以简单地添加它。我从来不需要它。关于服务定位器,请尝试理解Composition Root和when something is and isn't a Service Locator的概念。在solidservices 项目中,CommandService
类是一个 Humble Object,可以看作是 Composition Root 的一部分。【参考方案2】:
Poor man 的 DI 现在称为 Pure DI。
您可以使用 Pure DI 来编写 WCF 应用程序。您需要在Composition Root 中执行此操作。
在 WCF 应用程序中,Composition Root 是一个自定义的 ServiceHostFactory。
This answer 展示了如何执行此操作的示例。
您可以自定义该答案中的代码以添加更多依赖项。
【讨论】:
第一件事:如果我错了,请纠正我,但是当我想自我托管时,我不需要MyServiceHostFactory
。根本不用碰ServiceHostFactory
,对吧?在 IIS 中托管时需要它。第二件事:如果我想要更多而不是一个ServiceLayer
。例如我可以有SecondServiceLayer : ISecondServiceContract
service :/
添加到我的“第一件事”:我可以说MyInstanceProvider
是我的“组合根”。它是由MyServiceHost
创建的,但IDependency
对象(这将是我的服务器逻辑)“存储”在我的MyInstanceProvider
提供程序中。因此,每次从客户端发送新请求并且需要创建我的ServiceLayer
服务时,它不会创建新的IDependency
,这很好。 IDependency
在服务器的整个生命周期中只有一个实例。我写的对吗?
@Tom,你对 IIS 和 ServiceHostFactory
的看法是正确的。在 IIS 之外托管时,您有更多选择。如果您在控制台应用程序中托管您的 WCF 服务(例如),则组合根将成为 main
方法,您将在那里创建您的依赖项并将任何依赖项注入您为 WCF 服务创建的自定义实例提供程序。您可以为您拥有的两个服务创建两个实例提供程序类。
一个问题。是否已经有实现IInstanceProvider
和IContractBehavior
的具体类?我的意思是,现在我必须编写大量代码(MyInstanceProvider 类)来实现我的构造函数(使用注入)和GetInstance(InstanceContext instanceContext)
方法来新建我的服务。我可以从实现这两个接口的类派生,只需覆盖这个单一方法并添加我的构造函数注入。这会更容易。当然如果存在这样的类以上是关于在带有 WCF 服务的 C# 服务器中使用穷人的 DI [重复]的主要内容,如果未能解决你的问题,请参考以下文章
C# Restful WCF 服务。无法在帖子正文中反序列化 XML
如何通过 Jquery 调用 C# WCF 服务来修复“ERR_ABORTED 400 (Bad Request)”错误?
如何使用 WCF 在 C# 中调试 localhost 客户端/服务