获取创建WCF服务实例的调用者(或方法)的名称?

时间:2021-04-20 20:28:20

I have a WCF service with a private constructor. If I'm not wrong, constructors must be parameterless in WCF and the parameter I need is the caller's name (or caller's method name), so I can assign a few readonly fields.

我有一个私有构造函数的WCF服务。如果我没错,那么构造函数在WCF中必须是无参数的,而我需要的参数是调用者的名字(或调用者的方法名),所以我可以分配一些只读字段。

Is there a way that I can get the caller's name -- or the method that invoked it? I was playing around with OperationContext.Current, but without any luck.

有没有办法让我可以获得调用者的名字 - 或调用它的方法?我正在玩OperationContext.Current,但没有任何运气。

4 个解决方案

#1


I wouldn't recommend accessing the stack trace for performance reasons.

出于性能原因,我不建议访问堆栈跟踪。

WCF service constructors only need to be parameterless if you are using the default ServiceHostFactory. You can specify a custom service factory in your .svc file like this:

如果您使用默认的ServiceHostFactory,则WCF服务构造函数只需要是无参数的。您可以在.svc文件中指定自定义服务工厂,如下所示:

<%@ ServiceHost Language="C#" Debug="true"
   Service="Namespace.To.Service"
   Factory="Namespace.To.ServiceFactory" %>

The process to creating your class in a custom way goes like this:

以自定义方式创建类的过程如下:

  1. Your ServiceHostFactory creates an instance of your custom ServiceHost in CreateServiceHost
  2. 您的ServiceHostFactory在CreateServiceHost中创建自定义ServiceHost的实例

  3. ServiceHost overrides OnOpening and adds a custom IServiceBehavior to Description.Behaviors (Description is a property on the base class)
  4. ServiceHost重写OnOpening并向Description.Behaviors添加自定义IServiceBehavior(描述是基类的属性)

  5. Your IServiceBehavior implements ApplyDispatchBehavior and enumerates serviceHostBase.ChannelDispatchers, checking if each is a ChannelDispatcher.
    • Each ChannelDispatcher's Endpoints property is enumerated and it's DispatchRuntime.InstanceProvider is changed to a custom IInstanceProvider
    • 枚举每个ChannelDispatcher的Endpoints属性,并将DispatchRuntime.InstanceProvider更改为自定义IInstanceProvider

  6. 您的IServiceBehavior实现ApplyDispatchBehavior并枚举serviceHostBase.ChannelDispatcher,检查每个是否是ChannelDispatcher。枚举每个ChannelDispatcher的Endpoints属性,并将DispatchRuntime.InstanceProvider更改为自定义IInstanceProvider

  7. The custom IInstanceProvider creates the instance in GetInstance
  8. 自定义IInstanceProvider在GetInstance中创建实例

I have used this to delegate creation to an IoC container.

我用它来将创建委托给IoC容器。

#2


You can access the .NET call stack like this:

您可以像这样访问.NET调用堆栈:

var trace = new System.Diagnostics.StackTrace();
var frame = trace.GetFrame( 1 ); // Frame 0 is current function
var callingMethodName = frame.GetMethod().Name;

I do not know whether this technique works in your situation, but you could give it a try.

我不知道这种技术是否适用于您的情况,但您可以尝试一下。

#3


I have never seen a valid case for the called method to do something different based on the identity of the caller. If the caller's identity matters, then the caller should pass into the called method whatever information it needs. Instead of:

我从未见过被调用方法根据调用者的身份做一些不同的事情的有效案例。如果调用者的身份很重要,那么调用者应该将所需的信息传递给被调用的方法。代替:

public MyClass(string callerName) {
    if (callerName == "Caller1")
        _field = "Value1";
    else
        _field = "Value2";
}

use

public MyClass(string value) {
    _field = value;
}

#4


I think your best bet is to either break your service down to multiple similar services (yuk) or break out your method(s) to be overloads intended for different callers to use.

我认为你最好的办法是将你的服务分解为多个类似的服务(yuk),或者将你的方法分解为不同的呼叫者使用的重载。

i.e. if you have Service1 which provides method foo() to CallerA and CallerB, maybe try making foo private, and exposing fooA() and fooB(), which are exclusively called by CallerA and CallerB, respectively. Then fooA() and fooB() can set the readonly properties appropriately before calling foo().

即如果你有Service1为CallerA和CallerB提供方法foo(),可能会尝试使foo为private,并暴露fooA()和fooB(),它们分别由CallerA和CallerB独占调用。然后fooA()和fooB()可以在调用foo()之前适当地设置readonly属性。

#1


I wouldn't recommend accessing the stack trace for performance reasons.

出于性能原因,我不建议访问堆栈跟踪。

WCF service constructors only need to be parameterless if you are using the default ServiceHostFactory. You can specify a custom service factory in your .svc file like this:

如果您使用默认的ServiceHostFactory,则WCF服务构造函数只需要是无参数的。您可以在.svc文件中指定自定义服务工厂,如下所示:

<%@ ServiceHost Language="C#" Debug="true"
   Service="Namespace.To.Service"
   Factory="Namespace.To.ServiceFactory" %>

The process to creating your class in a custom way goes like this:

以自定义方式创建类的过程如下:

  1. Your ServiceHostFactory creates an instance of your custom ServiceHost in CreateServiceHost
  2. 您的ServiceHostFactory在CreateServiceHost中创建自定义ServiceHost的实例

  3. ServiceHost overrides OnOpening and adds a custom IServiceBehavior to Description.Behaviors (Description is a property on the base class)
  4. ServiceHost重写OnOpening并向Description.Behaviors添加自定义IServiceBehavior(描述是基类的属性)

  5. Your IServiceBehavior implements ApplyDispatchBehavior and enumerates serviceHostBase.ChannelDispatchers, checking if each is a ChannelDispatcher.
    • Each ChannelDispatcher's Endpoints property is enumerated and it's DispatchRuntime.InstanceProvider is changed to a custom IInstanceProvider
    • 枚举每个ChannelDispatcher的Endpoints属性,并将DispatchRuntime.InstanceProvider更改为自定义IInstanceProvider

  6. 您的IServiceBehavior实现ApplyDispatchBehavior并枚举serviceHostBase.ChannelDispatcher,检查每个是否是ChannelDispatcher。枚举每个ChannelDispatcher的Endpoints属性,并将DispatchRuntime.InstanceProvider更改为自定义IInstanceProvider

  7. The custom IInstanceProvider creates the instance in GetInstance
  8. 自定义IInstanceProvider在GetInstance中创建实例

I have used this to delegate creation to an IoC container.

我用它来将创建委托给IoC容器。

#2


You can access the .NET call stack like this:

您可以像这样访问.NET调用堆栈:

var trace = new System.Diagnostics.StackTrace();
var frame = trace.GetFrame( 1 ); // Frame 0 is current function
var callingMethodName = frame.GetMethod().Name;

I do not know whether this technique works in your situation, but you could give it a try.

我不知道这种技术是否适用于您的情况,但您可以尝试一下。

#3


I have never seen a valid case for the called method to do something different based on the identity of the caller. If the caller's identity matters, then the caller should pass into the called method whatever information it needs. Instead of:

我从未见过被调用方法根据调用者的身份做一些不同的事情的有效案例。如果调用者的身份很重要,那么调用者应该将所需的信息传递给被调用的方法。代替:

public MyClass(string callerName) {
    if (callerName == "Caller1")
        _field = "Value1";
    else
        _field = "Value2";
}

use

public MyClass(string value) {
    _field = value;
}

#4


I think your best bet is to either break your service down to multiple similar services (yuk) or break out your method(s) to be overloads intended for different callers to use.

我认为你最好的办法是将你的服务分解为多个类似的服务(yuk),或者将你的方法分解为不同的呼叫者使用的重载。

i.e. if you have Service1 which provides method foo() to CallerA and CallerB, maybe try making foo private, and exposing fooA() and fooB(), which are exclusively called by CallerA and CallerB, respectively. Then fooA() and fooB() can set the readonly properties appropriately before calling foo().

即如果你有Service1为CallerA和CallerB提供方法foo(),可能会尝试使foo为private,并暴露fooA()和fooB(),它们分别由CallerA和CallerB独占调用。然后fooA()和fooB()可以在调用foo()之前适当地设置readonly属性。