在我们的SharePoint/ASP.NET环境中,我们有一系列数据检索器类,这些类都来自通用接口.我被分配了创建数据检索器的任务,该数据检索器可以使用WCF与其他SharePoint场远程通信.我现在实现它的方式ChannelFactory<T>是在静态构造函数中创建单例,然后由远程数据检索器的每个实例重用,以创建单独的代理实例.我认为这样可以很好地工作,因为那时ChannelFactory只在app域中实例化一次并且它的创建保证是线程安全的.我的代码看起来像这样:
public class RemoteDataRetriever : IDataRetriever
{
protected static readonly ChannelFactory<IRemoteDataProvider>
RequestChannelFactory;
protected IRemoteDataProvider _channel;
static RemoteDataRetriever()
{
WSHttpBinding binding = new WSHttpBinding(
SecurityMode.TransportWithMessageCredential, true);
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType =
MessageCredentialType.Windows;
RequestChannelFactory =
new ChannelFactory<IRemoteDataProvider>(binding);
}
public RemoteDataRetriever(string endpointAddress)
{
_channel = RemoteDataRetriever.RequestChannelFactory.
CreateChannel(new EndpointAddress(endpointAddress));
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这是一个很好的设计吗?我想,一旦ChannelFactory创建,我不需要担心线程安全,因为我只是用它来打电话,CreateChannel()但我错了吗?它是在改变状态还是在幕后做一些可能导致线程问题的时髦的东西?另外,我是否需要在某个地方放置一些代码(静态终结器?)来手动处理ChannelFactory或者我可以假设每当IIS重新启动它时,它会为我做所有的清理工作吗?
wcf singleton static-constructor thread-safety channelfactory
您可以在IL中的.NET中的接口上定义静态构造函数.但是,如果这样做,则在接口上运行方法时不会运行静态构造函数:
.method public static void Main() {
.entrypoint
.locals init ( class IInterface cls1 )
// InterfaceClass static constructor is run
newobj instance void InterfaceClass::.ctor()
stloc.0
ldloc.0
// IInterface static constructor is not run!!!!!
callvirt instance int32 IInterface::Method()
call void [mscorlib]System.Console::WriteLine(int32)
ret
}
.class public interface IInterface {
.method private static specialname rtspecialname void .cctor() {
ldstr "Interface static cctor"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public abstract virtual instance int32 Method() {}
}
.class public InterfaceClass implements IInterface { …Run Code Online (Sandbox Code Playgroud) public class ClassA
{
public static readonly string processName;
}
public class ClassB : ClassA
{
static ClassB()
{
processName = "MyProcess.exe";
}
}
Run Code Online (Sandbox Code Playgroud)
编译上面的C#代码时出错.
错误说 - "无法分配静态只读字段(静态构造函数或变量初始化程序除外)"
但我在静态构造函数中分配它.
对这种静态变量的需求是,基类具有使用此变量的方法,但派生类和基类必须具有此变量的不同值.但是,相应类的所有实例的值都是常量.它必须是只读的,因为它不能被任何地方改变.
上面代码中的错误是什么?(如果有的话)我似乎无法发现一个.错误消息没有帮助.因为我根据它没有做错任何事.
如果出现错误,我该如何实现此功能?我知道一个简单的解决方法是使它成为一个实例变量,并在派生类中为它们分配不同的值.但这是不必要的,因为值在各个类的所有实例中是恒定的.
我搜索了很多,但没有一个答案是清楚的(至少对我来说!).现在我把这个问题放进去,因为我相信我无法在其他任何地方得到更明确的答案.
我什么时候应该在班上使用私有/静态构造函数?
我厌倦了通常的答案,所以请帮助我一些实时的例子和使用这些构造函数的优点/缺点.
我有一个带有静态构造函数的类.
我希望在不调用或使用任何成员的情况下调用静态构造函数,但前提是尚未调用构造函数.
我尝试过使用反射.使用反射,我可以调用静态构造函数(很多次),但我不知道它是否已经被调用过.
我该怎么做呢?
编辑
这不仅是我正在谈论的一个班级,它可能更多.可以说,所有标有特殊属性的类.
我在这里有点头疼,我想知道是否有人知道答案.
设置基本上是这样的:
//in Visual Studio plug-in application
SpinUpProgramWithDebuggerAttached();
//in spun up program
void Start()
{
StaticClass.StaticVariable = "I want to use this.";
XmlSerializer.Deserialize(typeof(MyThingie), "xml");
}
class MyThingie : IXmlSerializable
{
ReadXml()
{
//why the heck is this null?!?
var thingIWantToUse = StaticClass.StaticVariable;
}
}
Run Code Online (Sandbox Code Playgroud)
让我脱头发的问题是,在IXmlSerializable.ReadXml()方法中,StaticClass.StaticVariable为null,即使在设置变量后它被称为RIGHT.
值得注意的是,没有命中断点,并且在问题发生的精确位置忽略Debugger.Launch().
神秘的是,我通过提出异常来确定AppDomain.CurrentDomain.FriendlyName属性对于静态变量填充的位置与null相同!
为什么heck是超出范围的静态变量?!?这是怎么回事?!?我如何分享我的变量?
编辑:
我根据响应中的建议添加了一个静态构造函数,并让它执行Debug.WriteLine.我注意到它被调用了两次,即使所有代码似乎都在同一个AppDomain中运行.这是我在输出窗口中看到的内容,我希望这是一个有用的线索:
静态构造函数调用时间:2015-01-26T13:18:03.2852782-07:00
...加载'C:...\GAC_MSIL\System.Numerics\v4.0_4.0.0.0__b77a5c561934e089\System.Numerics.dll'...
......加载'Microsoft.GeneratedCode'......
...加载'C:...\GAC_MSIL\System.Xml.Linq\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.Linq.dll'....
...加载'C:\ USERS ...\APPDATA\LOCAL\MICROSOFT\VISUALSTUDIO\12.0EXP\EXTENSIONS ... SharePointAdapter.dll'.符号已加载.
...加载'Microsoft.GeneratedCode'.
静态构造函数调用时间:2015-01-26T13:18:03.5196524-07:00
附加细节:
这是实际的代码,因为有几位评论者认为它可能有所帮助:
//this starts a process called "Emulator.exe"
var testDebugInfo = new VsDebugTargetInfo4
{
fSendToOutputWindow = 1,
dlo = …Run Code Online (Sandbox Code Playgroud) 我正在使用以下代码调用类的静态ctor:
Type type;
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
Run Code Online (Sandbox Code Playgroud)
这会导致cctor运行两次吗?
我正在尝试使用参数初始化静态类,然后在该类中运行更多静态代码.
我知道这个static块,但它似乎不能采取任何论点.
有没有办法将参数传递给静态构造函数?
如果没有,使用参数初始化Static类的推荐技术是什么?
编辑: 我理解的静态类是一个无法实例化的类(在c#中它们被称为静态类,如果Java对它们有不同的术语,很抱歉没有意识到它) - 它通过它的类名来访问而不是对象名称.
我想要实现的(非常简化的)是一个类,它接收字典作为String,解析它,并且方法操纵它就像GetRandomEntry.
这是我的代码的详细摘录:
public class QuestionsRepository {
private static Map<String,String[]> easyDefinitions = new HashMap<String,String[]>();
//...
static
{
// need to receive and parse dictionary here
}
//...
Run Code Online (Sandbox Code Playgroud)
获取代码片段的相关部分绝非易事,希望我明智地选择(:
另一个可能相关的细节 - 我通常是#程序员.刚开始学习Java.
谢谢.
可以说我有两节课:
public abstract class Foo
{
static Foo()
{
print("4");
}
}
public class Bar : Foo
{
static Bar()
{
print("2");
}
static void DoSomething()
{
/*...*/
}
}
Run Code Online (Sandbox Code Playgroud)
我希望在调用之后Bar.DoSomething()(假设这是我第一次访问Bar类),事件的顺序将是:
42DoSomething在底线,我希望42打印出来.
经过测试,似乎只是2在打印.
这甚至都不是答案.
你能解释一下这种行为吗?
环境:C#6,Visual Studio 2015 CTP 6
给出以下示例:
namespace StaticCTOR
{
struct SavingsAccount
{
// static members
public static double currInterestRate = 0.04;
static SavingsAccount()
{
currInterestRate = 0.06;
Console.WriteLine("static ctor of SavingsAccount");
}
//
public double Balance;
}
class Program
{
static void Main(string[] args)
{
SavingsAccount s1 = new SavingsAccount();
s1.Balance = 10000;
Console.WriteLine("The balance of my account is \{s1.Balance}");
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
}
由于某种原因,静态ctor没有被执行.如果我将SavingsAccount声明为类而不是结构,它就可以正常工作.
c# static-constructor visual-studio c#-6.0 visual-studio-2015