如何创建可以访问的上下文?

时间:2009-10-23 13:15:51

标签: c# .net architecture

是否可以创建一个可从一组窗口访问但不能从另一组窗口访问的上下文?

例如,两个Web请求在他们自己的上下文中运行,而像ServiceSecurityContext.Current这样的对象指向不同的实例。

我的应用程序是一个类似Word的应用程序,其中PlanWindow可以打开计划文档。我希望能够执行类似PlanContext.Current的操作,它会返回当前计划,而不必将文档传递给从PlanWindow打开的任何对话框。

我认为这与线程有关,但我不知道从哪里开始。

8 个答案:

答案 0 :(得分:1)

如何使用以下架构解决这个问题:

IPlanContextReceiver
{   
     public object StateByWichPlanContextCanDeciceWhatToReturn get;
}

class SomeWindow : Window, IPlanContextReceiver

在PlanContext中,改为使用Current属性

public static PlanContext GetCurrent(IPlanContextReceiver receiver)
{
     lock(contextSync) // be threadsafe if necessary
     {
         if(/*condition that checks receiver.StateByWichPlanContextCanDeciceWhatToReturn*/)
         {
            // context is valid for this receiver
            // return the correct context from an internal store or similar
            return Contexts["TheContextForCoolReceivers"];
         }
         else if(/*condition that checks receiver.StateByWichPlanContextCanDeciceWhatToReturn*/)
         {
            // context is valid for this receiver
            // return the correct context from an internal store or similar
            return Contexts["TheContextForUncoolReceivers"];
         }

         // no existing context is available for this receiver
         return null;
    } 
}

如果再次将它设为单例,GetCurrent也可以是实例方法。而不是一个方法,它也可以是一个索引器 - 这是一个品味问题。

此外,由StateByWichPlanContextCanDeciceWhatToReturn实际上取决于您。它可能像需要检查的多个属性一样复杂,也可能像为窗口上下文组的每个设置一次的字符串一样简单。

答案 1 :(得分:1)

因此,即使活动表单是一个对话框,这是另一个有效的命题:

1)使用此界面标记所有窗口(子窗口):

public interface IPlanViewer
{
    //this means that all you windows will have this property
    PlanDocument Document { get; }
}

2)创建“上下文”类

public class Context
{
    public static Context Current { get; set; }
    public IPlanDocument Document { get; set; }
    static Context()
    {
        Current = new Context();
    }
}

3)在您的MDI表单中使用此方法处理MdiChildActive事件

private void MdiForm_MdiChildActivate(object sender, EventArgs e)
{
    var currentView = Form.ActiveForm as IPlanViewer;
    if (currentView != null)
        Context.Current.Document = currentView.Document;
}

4)使用此上下文

private void WorkWithCurrentDoc() 
{
    var doc = Context.Current.Document;
    doc.Title = "totot"
    // etc ...
}

就是这样。它还好吗?

Manitra。

答案 2 :(得分:1)

我在其中一个项目中遇到了类似的问题。我使用了 GetDataSetDataSystem.Runtime.Remoting.Messaging.CallContext方法。

CallContext对每个线程都是唯一的,您可以使用它来存储特定于线程的对象。

在这个特定场景中,我将创建一个PlanContext类,如下所示:

public class PlanContext
{
    const string _PlanDocumentSessionKey = "Current_PlanDocument";
    public static PlanDocument Current
    {
        get
        {
            return CallContext.GetData(_PlanDocumentSessionKey) as PlanDocument;
        }
        set
        {
            CallContext.SetData(_PlanDocumentSessionKey,value);
        }
    }
}

在您实例化文档的代码中,添加以下内容:

PlanContext.Current = newDocument;

FYI,HttpContext.Current也使用CallContext来检索特定线程的Context。

答案 3 :(得分:0)

静态字典? PlanContext [sessionID]?

答案 4 :(得分:0)

我从来没有这样做过,所以我只能指出你看似正确的方向。

首先,这里是如何在两个线程上使用Application.Run来创建Windows窗体应用程序中的多个“主”窗口,每个窗口都在自己的线程上:

http://msdn.microsoft.com/en-us/library/ms157901.aspx

其次,这是如何拥有每线程状态:

How does HttpContext.Current work in a multi-threaded environment?

http://blogs.msdn.com/jfoscoding/archive/2006/07/18/670497.aspx

答案 5 :(得分:0)

我认为这与线程无关。

如果按Current表示Selected or Active Plan,则可以在跟踪所选计划的Property对象上设置PlanWindow(即:每当有不同的计划时更新)被选中/激活)并且所有其他窗口/对话框都可以访问此属性(例如,使其静态)

答案 6 :(得分:0)

我不做C,但在Java中你有java.lang.ThreadLocal

public class MyClass {

    private static ThreadLocal<MyClass> instance = new ThreadLocal<MyClass>() {
        protected View initialValue() {
            return null;
        }
    };

    private MyClass(Object arg1, Object arg2) {
        this.arg1 = arg1; // Web request?
        this.arg2 = arg2; // Web response?
    }

    public static MyClass getInstance() {
        return instance.get();
    }

    public static MyClass createInstance(Object arg1, Object arg2) {
        MyClass myClass = new MyClass(arg1, arg2);
        setInstance(myClass);
        return myClass;
    }

    protected static void setInstance(MyClass myClass) {
        if (myClass == null) {
            instance.remove();
        } else {
            instance.set(myClass);
        }
    }

    public void release() {
        setInstance(null);
    }

}

您第一次创建createInstance()时会调用它。然后,您可以在仍然运行相同线程时随时调用getCurrentInstance()

看看C中是否存在类似的东西。祝你好运。

答案 7 :(得分:0)

首先,我假设你的应用程序是MDI Windows Form 1,每个子窗口都向用户显示一个文档。

1)使用此界面标记所有窗口(子窗口):

public interface IPlanViewer
{
    //this means that all you windows will have this property
    PlanDocument Document { get; }
}

2)创建“上下文”类

public class Context
{
    public static Context Current { get; set; }
    static Context()
    {
        Current = new Context();
    }

    //The key method : I'm returning the document of the currently selected child windows or null if no windows are opened
    public PlanDocument Document
    {
        get { 
            var currentView =  Form.ActiveForm as IPlanViewer;
            if (currentView != null)
                return currentView.Document;
            else
                return null;
        }
    }
}

3)使用此上下文

private void WorkWithCurrentDoc() 
{
    var doc = Context.Current.Document;
    doc.Title = "totot"
    // etc ...
}

就是这样。我希望这会对你有所帮助。

Manitra。