2009-10-23 5 views
0

Возможно ли создать контекст, доступный из набора окон, но не из другого набора?Как создать контекст, к которому вы можете получить доступ?

Например, два веб-запроса работают в своем собственном контексте, а объекты, такие как ServiceSecurityContext.Current, указывают на разные экземпляры.

Мое приложение - это приложение, подобное Word, с PlanWindow, которые открывают документ плана. Я хотел бы сделать что-то вроде PlanContext.Current, которое вернет мне текущий план, вместо того, чтобы передавать документ в любое диалоговое окно, открытое из этого PlanWindow.

Я полагаю, что это связано с потоками, но я не знаю, с чего начать.

+0

Передача ссылки ParentForm на ChildForm не является неразумной задачей.Затем вы можете проверить любые общедоступные свойства в ParentForm, которые вы хотели. – Greg

+0

Где вы хотите назвать «PlanContext.Current»? Это только в ваших GUI-объектах (UserControls и Forms)? –

ответ

1

Я столкнулся с аналогичной проблемой в одном из моих проектов. Я использовал методы GetData и SetDataSystem.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 для извлечения контекста для определенного потока.

+0

В контексте Winform у вас есть один единственный поток GUI. Использование CallContext всегда возвращало бы тот же PlanDocument ... Таким образом, это было бы эквивалентно статическому свойству Current on the PlanContext. Или я чего-то не хватает? –

+0

Если он планирует использовать один поток, статическая переменная будет работать отлично. Но я предположил, что он хочет использовать несколько потоков для каждого созданного PlanWindow (поскольку он сравнивал свой сценарий с двумя веб-запросами). Лично я считаю, что использование нескольких потоков - это лучший подход, так как модальный диалог (скажем, диалог печати), открытый в одном из окон, не будет блокировать вход для другого документа. – madaboutcode

0

Статический словарь? PlanContext [sessionID]?

+0

Но это заставило бы меня нести SessionId. Если я должен передать значение всем формам и объектам, это должен быть сам документ. –

0

Я никогда не делал этого, поэтому могу указать только на то направление, которое кажется правильным.

Во-первых, вот как использовать Application.Run на два потока, чтобы сделать на нескольких «основных» окна в Windows Forms Application, каждый на своем собственном потоке:

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

0

Я думаю, что это не имеет ничего общего с потоками.

Если по Current, вы имеете в виду Selected or Active Plan, то вы можете установить Property на PlanWindow объекте, который отслеживает выбранный план (т.е. обновляется каждый раз, когда выбран другой план/активации) и имеет это свойство быть доступным для всех других окон/диалоги (сделать его статическим, например)

1

Как насчет решения этого со следующей архитектурой:

IPlanContextReceiver 
{ 
    public object StateByWichPlanContextCanDeciceWhatToReturn get; 
} 

class SomeWindow : Window, IPlanContextReceiver 

И в PlanContext, вместо текущей собственности у вас есть

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. Он может быть таким же сложным, как несколько свойств, которые необходимо проверить, или он может быть таким же простым, как строка, которую вы устанавливаете один раз для каждого из ваших контекстных групп окна.

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. Удачи.

0

Во-первых, я предполагаю, что вы - приложение MDI Windows Form, и каждый дочерний окна отображает документ пользователю.

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.

+0

Проблема, с которой я сталкиваюсь в использовании Form.ActiveForm, заключается в том, что если я в диалоге, это теперь активная форма, а не IPlanViewer. –

+0

Привет, Пьер Ален, я понимаю вашу проблему, я просто представил еще один ответ, который может быть лучше. –

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.

Смежные вопросы