所以这就是问题:有没有办法创建一个 Context ,它只会共享代码的一部分。我真的不知道如何解释它,所以我会举一个例子。
假设我有:
using(Context ctx = new Context())
{
ctx.Set("abc","abc");
method1();
method2();
}
和(方法2相同):
public void method1()
{
Context ctx = Context.Instance();
string abc = ctx.Get("abc");
}
目标是方法中的Context.Instance()
返回在使用中创建的对象,但它必须保持线程安全。我的意思是如果调用是从外部使用,或在另一个内部同时使用,它将根据使用返回上下文。如果不存在,Context.Instante()
将返回一个新的Context
(或者null,我将在之后进行调整,这不是重点)。
我知道这不是经典的做法,但我不想在每次通话时传递上下文。真正的方法将有很多子方法,只有持续时间需要它,但它从一开始就必须是常见的。
目标是创建一个将与所有(且仅限)子方法共享的事务,但顶级方法无法访问EF类。我唯一的解决方案是使用会话来存储我的EF上下文,或者静态用于批量,因为它们没有会话。这是我的目标,但问题更为通用。
我希望我很清楚,不要犹豫提问。并添加标签,因为我真的不知道标签添加了什么。
谢谢!
修改
我可能不够清楚。单例是不够的,静态在所有实例之间共享。如果两个不同的用户同时完成两次对使用的调用,则Context对他们来说是相同的,但我希望它们不同。
理想情况下,我想允许这样的事情:
using(Context ctx = new Context())
{
ctx.Set("abc","abc");
method1();
using(Context ctx = new Context())
{
ctx.Set("abc","def");
method2();
}
method1();
}
但我想我问得太多了。
答案 0 :(得分:3)
让Context.Instance()方法管理thread static变量。第一个调用可以创建实例,其他调用可以使用它,并且在使用第一个调用结束时,您将其销毁。
使用线程静态方法,不会出现多线程问题,因为每个线程都有自己的实例。在单个线程中,每个“下一个方法执行”都将使用相同的实例。
更新:
一些代码。如果我通过它调试,只创建一个上下文,第二个using语句接收与第一个using语句相同的上下文。
class Context : IDisposable {
[ThreadStatic]
private static Context _instance;
[ThreadStatic]
private static int _instanceCounter;
public static Context Instance() {
if (_instanceCounter == 0) {
_instance = new Context();
}
_instanceCounter++;
return _instance;
}
private static void Release() {
_instanceCounter--;
if (_instanceCounter == 0) {
if (_instance != null)
_instance.Dispose();
_instance = null;
}
}
public void Dispose() {
Release();
}
}
public class Test {
public void Test1() {
using (var context = Context.Instance()) {
// do something
Test2();
}
}
private void Test2() {
using (var context = Context.Instance()) {
// identical context as in Test1
// do something
}
}
}
答案 1 :(得分:0)
如果你想要Singleton设计模式,这里是一个模板。它将确保只创建一个类的一个实例,并且程序的所有部分都使用相同的
public class Singleton {
private static Singleton instance;
private Singleton(){ // note private constructor
// intialize code here
}
public static Singleton GetInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
}
同样在多线程环境中,您可能想象一下当Instance为null时两个线程可以进入GetInstance方法的情况,并且最终都会初始化Singleton类的单独实例。
要检索实例,您可以调用Singleton.GetInstance()
答案 2 :(得分:0)
你需要使用ThreadStatic,就像Maarten所说,这样的事情可能有用:
public class Context : IDisposable
{
[ThreadStatic]
private static Context context;
private Context(Guid id)
{
this.Id = id;
}
public Guid Id
{
get;
private set;
}
public static Context Instance()
{
if (context == null)
{
context = new Context(Guid.NewGuid());
}
return context;
}
public void Dispose()
{
context = null;
}
}
如果你创建一个包含以下代码的控制台应用程序,你应该知道它是如何工作的。
private static void Main(string[] args)
{
Action action = () =>
{
using (var context = Context.Instance())
{
Console.WriteLine("Thread {0} - Context Id {1}", Thread.CurrentThread.ManagedThreadId, context.Id);
using (var context2 = Context.Instance())
{
Console.WriteLine("Thread {0} - Context Id {1}", Thread.CurrentThread.ManagedThreadId, context.Id);
}
}
Thread.Sleep(1000);
};
Task.Factory.StartNew(action);
Task.Factory.StartNew(action);
Console.ReadLine();
}
如果要确保上下文仅由最外面的using语句实际处理,则需要计算每个线程调用实例的次数。