I have managed to stop OnItemSaved events being triggered via the use of
item.Editing.EndEdit(false,true);
This however still triggers OnItemSaving events. Is there a way to disable this as well?
You can do that using an EventDisabler:
using (new EventDisabler())
{
item.Editing.BeginEdit();
item.Editing.EndEdit();
}
Found here: Temporarily disable events through the Sitecore API
Just to expand on #Ruud van Falier's answer, it is worth noting that the EventDisabler, like the SecurityDisable, inherits from IDisposable. As such, you can create a property or local variable that is an EventDisabler and Sitecore Events will be disabled from the moment that the variable or property is initialized up until the moment when the Dispose() method is called.
For example, in the following class, events will be disabled from the time that the Foo() method is called until the time that the Bar() method is called.
public class SomeClass
{
private EventDisabler _eventDisabler;
...
public void ToggleEventDisabler(bool eventDisablerOn)
{
_eventDisabler = eventDisablerOn ? new EventDisabler() : null;
}
public void Foo()
{
ToggleEventDisabler(true); //turn on the event disabler
...do stuff...
}
public void Bar()
{
...do stuff...
if (_eventDisabler != null)
{
_eventDisabler.Dispose();
}
}
}
Related
I do not understand some things of work with callbacks.
I have some third-party code wich connect,disconnect,subscribe to values from some system.
So, the example is:
class Subscriber:ISubscriber
{
public void OnConnected()
{
}
public void OnDisconnected()
{
}
}
Then, it uses:
var subscriber=new Subscriber();
_someSystemObj.CreateConnection(subscriber); //i do not understand how it works there
And then _someSystemObj calls OnConnected or OnDisconnected.
So, i have two questions:
1.How can _someSystemObj calls OnConnected method (it use Observer pattern or may be it use it other way. Can you describe it? Get some schematic code to understand how it may work.
If i want to do many steps when OnDisconnect happens: should i throw some public event to other classes? I mean than i can not do Disconnection in this OnDisconnect method (i have to do some steps in other part of my code and at old version of this API i just rethrow event OnDisconnect on top of my program and then handle it.)
This old version of code looks like:
_server.OnDisconnect+=OnDisconnectHandler;
void OnDisconnectHandler(..)
{
if(OnReconnect!=null)//some public event
OnReconnect(e);// throw on top of my program and then handle it there
}
At new version of API i try to solve it by add public event and when OnDisconnect happens throw it on top:
class Subscriber:ISubscriber
{
public event EventHandler<EventArgs> OnDisconnectedHappens;
public void OnConnected()
{
}
public void OnDisconnected()
{
if(OnDisconnectedHappens!=null)
OnDisconnectedHappens(this,e);//thow on top
}
}
And in some place:
_subscriber.OnDisconnectHappens+=OnDisconnectHandler; //and do my work
Or, may be it not right way. May be i should do something else?
Please,can you give me a some link, that i can learn about this model of event callbacks?
Or, may be i do it correctly?
How can _someSystemObj call OnConnected method?
Well, you gave it a subscriber when you called CreateConnection(subscriber). It's probably implemented something like this:
private readonly List<ISubscriber> _subscribers = new List<ISubscriber>();
public void CreateConnection(ISubscriber subscriber)
{
_subscribers.Add(subscriber);
}
private void OnConnectedNotifySubscribers()
{
foreach (ISubscriber subscriber in _subscribers)
{
subscriber.OnConnected();
}
}
If I want to do many steps when OnDisconnect happens, should I raise some public event to other classes?
That is a valid option, but it can get difficult to debug when there are too many layers in an event chain. Another option is to increase the capability of your Subscriber class so that it can do everything necessary to handle the subscription events.
class EmpoweredSubscriber : ISubscriber
{
private readonly DisconnectWorker _worker;
private readonly DisconnectHelper _helper;
public EmpoweredSubscriber(DisconnectWorker worker, DisconnectHelper helper)
{
_worker = worker;
_helper = helper;
}
public void OnConnected()
{
}
public void OnDisconnected()
{
_worker.DoWork();
_helper.DoHelp();
// more...
}
}
Suppose I have a component Bar that does Foo and notifies about that calling FooHappened method on all services implementing IFooConsumer interface.
I can write Bar like this
class Bar
{
public Bar(IEnumerable<IFooConsumer> fooConsumers) { ... }
public void Foo()
{
// foo-ing
foreach (var f in _fooConsumers) f.FooHappened();
}
}
It will work, but instantiating Bar will instantiate all possible IFooConsumers. What if I need to notify only those IFooConsumers that exist at the moment when Foo happened?
Is there a way to get some kind of tracker that knows about all instantiated instances of IFooConsumer?
I could probably write one myself via subscribing to IWindsorContainer.Kernel.ComponentCreated, but I'm interested if something like that exists? Or maybe there's another way to solve my issue?
You can create a simple facility like the one showing below, that will do the event registration every time a components get's instantiated. The code below here is for using Winsor with Caliburn.Micro. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In your case I would not have Bar directly fire the event's to all the classes, but rather use a singleton component (like IEventAggregator below) to fire events to multiple classes. This will also make sure that events get deregistered, which will otherwise result in weird behaviour. In the code every class that derives from IHandle will receive events. You can change this according to your needs.
If you have any questions just let me know.
class EventRegistrationFacility : AbstractFacility
{
private IEventAggregator _eventAggregator;
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) _eventAggregator = Kernel.Resolve<IEventAggregator>();
_eventAggregator.Subscribe(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IHandle)) return;
if (_eventAggregator == null) return;
_eventAggregator.Unsubscribe(instance);
}
}
===EDIT====
Combining this with the bouncer as described by Sammy:
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public class Bouncer {
private IList<IFooConsumer> _inside {get;}
void WelcomeTo(IFooConsumer consumer) {
_inside.Add(consumer);
}
void EscortOut(IFooConsumer consumer);
_inside.Remove(consumer);
}
IEnumerable<IFooConsumer> WhoIsInside {
get {
return _inside;
}
}
public Consumer: IFooConsumer {
FooHappened() {
// Do something.
}
// no need to implement constructor/dispose
}
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing ==> alernatively create a function on Bouncer that does this. And keep WhoIsInside private.
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}
class BouncerRegistrationFacility : AbstractFacility
{
private IBouncer _bouncer
protected override void Init()
{
Kernel.ComponentCreated += ComponentCreated;
Kernel.ComponentDestroyed += ComponentDestroyed;
}
void ComponentCreated(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) _bouncer = Kernel.Resolve<IEventAggregator>();
_bouncer.WelcomeTo(instance);
}
void ComponentDestroyed(Castle.Core.ComponentModel model, object instance)
{
if (!(instance is IFooConsumer)) return;
if (_bouncer == null) return;
_bouncer.EscortOut(instance);
}
}
Allthough you need some more code for writing the facility, there is no need for FooConsumers to register/unregister themselves. As the registration code must originally be written in all FooConsumers it tends to repeat. In this way the subscription/unsubscription is done as a commission/decommission requirement and only needs to be dealt with once.
P.S. Code is written in notepad and might contain compile errors.
I think that putting the crux of knowing which objects are instantiated on Castle Windsor is not the best way forward; you will certainly need to access some container methods and doing so will link your components to Castle, which shouldn't happen.
What I'd recommend instead is to create a component IBouncer. That component would be injected as singleton in all IFooConsumer which would call it upon being created and disposed (dispose being one option, you could use other methods)
public interface IBouncer {
IEnumerable<IFooConsumer> WhoIsInside {get;}
void WelcomeTo(IFooConsumer consumer);
void EscortOut(IFooConsumer consumer);
}
public Consumer: IFooConsumer {
public Consumer(IBouncer bouncer) {
bouncer.WelcomeTo(this);
}
public Dispose() {
bouncer.EscortOut(this); // dispose pattern ommitted
}
}
Now instead of passing the list of IFooConsumer to your Bar, just add the IBouncer to it and ask which consumers are inside.
class Bar
{
public Bar(IBouncer bouncer) { ... }
public void Foo()
{
// foo-ing
foreach (var f in bouncer.WhoIsInside) f.FooHappened();
}
}
I'm writing a program that logs user idle time, however when I attempt to run the program it throws a Stack Overflow Exception.
These are my custom events
public void OnInactive(EventArgs e)
{
this.OnInactive(new EventArgs());
do
{
var idle2 = GetIdleTime();
GetIdleTime();
System.Diagnostics.Debug.WriteLine(idle2);
}
while (timer.Interval > 5000);
}
public void OnActive(EventArgs e)
{
this.OnActive(new EventArgs());
if (timer.Interval < 5000)
{
var idle3 = GetIdleTime();
System.Diagnostics.Debug.WriteLine(idle3);
}
}
I've breakpointed the code to try and locate the source of the issue, which appears to lie within this.OnInactive(new EventArgs());, However I'm pretty stumped on how to resolve this issue as I'm a beginner to Custom Events and haven't been coding in C# for long.
Any and all help with this issue would be greatly appreciated!
Thanks in Advance =]
Your handler method is calling itself immediately on entry:
this.OnInactive(new EventArgs());
this leads to a sequence of calls:
OnInactive -> OnInactive -> OnInactive -> ... ->
which will continue until you run out of stack space and the StackOverflowException is thrown by the runtime.
It's not clear what you're trying to achieve with the recursive call, but you should be able to just remove it.
You have the same issue in your OnActive handler.
EDIT: In response to the comments, it seems you're trying to raise the event itself at the beginning of your method. Assuming your event declaration looks like:
public event EventHandler InActive;
then you can raise it with:
EventHandler inactiveEvent = this.InActive;
if(inactiveEvent != null)
{
inactiveEvent(this, e);
}
and similarly for your Active event.
I gues you are trying to call the base method, but in fact you are now calling OnInactive when hitting OnInactive. This behaviour is recursive and will finaly stop due StackOverflow exception.
You can call the base function with base.<function name>.
For example:
class SpecialDerived : Base
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
More info: http://msdn.microsoft.com/en-us/library/hfw7t1ce(v=vs.71).aspx
I think what you need is a bit more understanding about events. Let me explain the same through a sample code.
Class A{
public event OnInactive;
public event OnActive;
}
when any changes occur in classA you want to update things in ClassB. So you will implement events of class A in ClassB.
this link will describe you the same in detail.
My understanding says that there is no use of events when you are triggering it from the same class and listening in the same class.
these aren't event handlers, these are the methods that are going to
be called in order to raise the active and inactive events – Reece
Cottam
You need to actually call the event.
public class ReecesWatcher
{
public event EventHandler ActiveEvent;
public event EventHandler InactiveEvent;
protected virtual void OnInactive(EventArgs e)
{
// Fire the event using the () syntax. Fire it through
// a test variable so that we can reliabilty test for null,
// if there are no subscribers.
EventHandler inactiveEventTest = InactiveEvent;
if (inactiveEventTest != null)
{
inactiveEventTest(this, new EventArgs());
}
do
{
var idle2 = GetIdleTime();
GetIdleTime();
System.Diagnostics.Debug.WriteLine(idle2);
}
while (timer.Interval > 5000);
}
protected virtual void OnActive(EventArgs e)
{
// Fire the event using the () syntax. Fire it through
// a test variable so that we can reliabilty test for null,
// if there are no subscribers.
EventHandler activeEventTest = ActiveEvent;
if (activeEventTest != null)
{
activeEventTest(this, new EventArgs());
}
if (timer.Interval < 5000)
{
var idle3 = GetIdleTime();
System.Diagnostics.Debug.WriteLine(idle3);
}
}
// ... the rest of your class, where you call OnActive and OnInactive to
// cause the events to be fired.
}
I recommend not making your OnActive and OnInactive methods public, otherwise you're exposing too much of the implementation to the rest of your program. If you expect the class to be inherited from, then make them protected, otherwise I usually make them entirely private, since they're basically wrapper functions called by the rest of the class.
This seems to be basics of the language, but I do not understand how is this accomplished in .Net. I have a member variable in a class, say a bool _isCommitted. I want something to happen whenever _isCommitted is true. Something like this:
//Whenever _isCommitted == true()
{
Foo()
}
Basically like an event, but here it is my variable. How to? Many thanks..
This is normally done through properties and a backing private field. You need to ensure you only ever access through the property.
private bool _isCommitted;
public bool IsCommitted
{
get { return _isCommitted; }
set
{
if(value)
{
//do something
}
_isCommitted = value;
}
}
At the most basic level, you can create an event in your class:
public delegate void MyHandler(bool b);
public event MyHandler CommittedChanged;
Now people can subscribe to your event like so:
public void SomeHandlerMethod(bool b) { ... }
...
someInstance.CommittedChanged += SomeHandlerMethod;
someInstance.CommittedChanged += ASecondHandlerMethod;
someInstance.CommittedChanged += x => { /* inline handler using lambda */ };
A user can unregister his event handler this way:
someInstance.CommittedChanged -= SomeHandlerMethod;
And wherever you decide to change your variable, you will follow it up with:
if (CommittedChanged != null) CommittedChanged(_isCommitted);
This will call everyone who has registered a function with your event.
Having said this, there are plenty of improvements that you can do. First, make _isCommitted into a property, and do the event callback in its setter. This way, you won't forget to call the handlers.
public IsCommitted {
get { return _isCommitted; }
set {
_isCommitted = value;
if (CommittedChanged != null) CommittedChanged(_isCommitted);
}
}
Read more about events here.
This is enough to get you going. However, if you delve further into the C# framework, you will find a standardized way of using this event framework inside of the System.ComponentModel namespace. Sepcifically, the interface INotifyPropertyChanged, which ties neatly into a more generic event system that also plays well with some of Microsoft's own technologies, such as WPF, allowing GUI elements to pick up on changes to your class automatically. Read more about INotifyPropertyChanged here.
You basically need PropertyChangedEvent PropertyChangedEventHandler Delegate
I think C# properties is what you need.
private bool _isCommitted;
public bool IsCommitted
{
get { return _isCommitted; }
set { if(value){/*DO SOMETHING HERE*/}
_isCommitted = value; }
}
I put "volatile" because it's only vaguely so.
I have a class which has a property called StopRequested. This flag can be set by other threads at any time, and needs to indicate to my code that it should stop what it's doing and exit (this is a Windows Service based process, and when Stop is called, all processing needs to clean up and stop).
I wish to create some other classes to do the actual brunt of the processing work, however these classes also have to be aware of the "stop" flag. You can't just pass the flag because it will pass a copy, and you can't pass properties as ref types.
So how do you propagate a property that might change at any time into other classes?
The only thing I can think of is to pass a reference to the parent class, but I dislike coupling the worker classes to the parent for one flag. Any suggestions would be appreciated.
EDIT:
Here's a basic example:
public class A
{
public bool StopRequested { get; set; }
private Worker = new Worker();
public void DoWork();
{
worker.DoWork();
}
}
public class Worker
{
public void DoWork()
{
while(!StopRequested)
{
....
}
}
}
You could have each of your worker classes have their own StopRequest property and then just set that whenever StopRequest is flagged.
private List<IStopable> WorkerClasses = new List< IStopable > ()
public Bool StopRequest{
get
{
return _stopRequest;
}
set
{
_stopReqest = value;
foreach (var child in WorkerClasses)
child.StopRequest = value;
}
}
Like Rubens said, use an event. What you described basically defines event to a T:
Propagate a property change to other classes.
There is actually a facility in .NET that provides this already, albeit in a generic way: INotifyPropertyChanged. This interface provides a single event, PropertyChanged, that allows a class to notify any listeners of any property change.
In your case, you could easily provide your own interface that is more specific:
interface IStopNotifier
{
event EventHandler StopRequested;
}
This interface would be implemented by your main work manager (whatever it is), and could propagate itself like so:
class WorkManager: IStopNotifier
{
public event EventHandler StopRequested;
protected void OnStopRequested()
{
if (StopRequested != null) StopRequested(this, new EventArgs());
}
public void StopAllWorkers()
{
OnStopRequested();
}
public Worker CreateWorker<T>()
where T: Worker
{
var worker = new T(this);
return worker;
}
}
class abstract Worker: IDisposable
{
public Worker(IStopNotifier stopNotifier)
{
stopNotofier.StopRequested += HandleStopRequested;
}
private IStopNotifier m_stopNotifier;
private bool m_stopRequested = false;
internal void HandleStopRequested(object sender, EventArgs e)
{
m_stopRequested = true;
}
public void Dispose()
{
m_stopNotifier.StopRequested -= HandleStopRequested;
}
}
Why don't to create an event to handle stop requests?