On a build server, I see some weird message. It doesn't say so, but I think it's from some software called 'fx cop'
Warning CS0067: The event 'SunGard.Adaptiv.AnalyticsEngine.UI.CommonControls.DisabledCommand.CanExecuteChanged' is never used
How can I silence this message? Without changing what my class does.
sealed class DisabledCommand : ICommand
{
public event EventHandler CanExecuteChanged;
I stumbled upon docs for System.Diagnostics.CodeAnalysis.SuppressMessageAttribute which sounds useful, but there aren't any examples for my warning.
If you need to create an event that is never raised, you should make a noop event:
public EventHandler CanExecuteChanged {
add { }
remove { }
}
The compiler is complaining because a default ("field-like") event will create a hidden backing field to store the handlers. Since you never raise the event, that field just wastes memory.
Related
I am working on an editor plugin and now implementing support for code hovers.
I have extended AbstractInformationControl (and implemented IInformationControlExtension2) to create a new control for showing the hover info.
It works almost fine, but I am unable to receive property change events in my information control. What I try is like this, but the event handler does not fire:
public class MyHoverInfoControl extends AbstractInformationControl implements IInformationControlExtension2 {
public MyHoverInfoControl(Shell parentShell, String string) {
super(parentShell, string);
create();
Activator.getDefault().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent event) {
// TODO Auto-generated method stub
}
});
}
The control itself contains a StyledText. I have also tried to add a KeyListener to this StyledText to see if key events are received, and it only seemed to work if I click into the control (it is not enough to hover over a text to show the control). But property change event does not seem to be received even after the click.
Is it possible to receive property change events for an AbstractInformationControl subclass?
In Xamarin Forms, I created a bindable property like so:
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem));
public MyItem SelectedItem
{
get { return (MyItem)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
Here's my constructor:
public MyView()
{
InitializeComponent();
PropertyChanged += OnPropertyChanged;
}
protected void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if (propertyChangedEventArgs.PropertyName == "SelectedItem")
{
// called twice
}
}
Can somebody explain why property changed event is firing twice? If I create a changed handler in the definition of the bindable property, then the handler is called once.
public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(MyItem), typeof(MyGrid), default(MyItem), null, SelectedItemChanged);
I have noticed the issue exists only in code-behind. If I set the property directly in XAML, property changed event fires once.
We don't really have enough information to answer this question with certainty, but I can speculate.
Without seeing your SetValue method, my assumption would be that it lacks a short circuit, e.g. "don't do anything if the new value and the old value are the same".
Then my second assumption would be that the control that is being bound to this property is setting it (after being bound). This can happen with list-type controls when SelectedItem is bound.
The resulting chain of events might be something like:
Code sets property
PropertyChanged event is fired
Binding sets the value on a control
Control reports it's value has been changed, and two-way binding sets the value on the ViewModel again
The lack of a short circuit causes the PropertyChanged event to be raised again
The binding sets the value on the control again (to the same value as before)
The control does not report a change, because it's property is short-circuited properly
My guess is that if you were to short circuit your setter (by checking against the existing value and bailing out if they are the same) this behavior would stop.
Currently I have this generic implementation by inheriting from an existing base class that provides INotifyPropertyChanged. I cannot change this base class, but I want to provide the property change notifications also as an Observable so I implement the IReactiveNotifyPropertyChanged interface as well.
I find the code below (obtained through a process of trial and error) to be quite involved and was wondering if this could be done in a more simple, concise manner.
Also, I'm struggling to come up with ideas to suppress notifications. Any thoughts?
public class MyReactiveClass<T> : PropertyChangeNotifyingBaseClass<T>, IReactiveNotifyPropertyChanged<T>
where T : class
{
public MyReactiveClass()
{
Changed = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>
(
t => PropertyChanged += t, // add handler
t => PropertyChanged -= t // remove handler
// conversion from EventPattern to ReactivePropertyChangedEventArgs
).Select(ev => new ReactivePropertyChangedEventArgs<T>(ev.Sender as T, ev.EventArgs.PropertyName));
Changing = Observable.FromEventPattern<System.ComponentModel.PropertyChangingEventHandler, PropertyChangingEventArgs>
(
t => PropertyChanging += t, // add handler
t => PropertyChanging -= t // remove handler
// conversion from EventPattern to ReactivePropertyChangedEventArgs
).Select(ev => new ReactivePropertyChangedEventArgs<T>(ev.Sender as T, ev.EventArgs.PropertyName));
}
public IObservable<IReactivePropertyChangedEventArgs<T>> Changing { get; }
public IObservable<IReactivePropertyChangedEventArgs<T>> Changed { get; }
public IDisposable SuppressChangeNotifications()
{
// how to deal with suppression of change notifications?!
return Disposable.Empty;
}
}
You have written the shortest possible piece of code to implement Changed and Changing observables, what do you want to achieve more? :)
Since you need Changed, Changing, SuppressChangeNotifications, and maybe in a month you will want something else of ReactiveObject, the best solution would be to use ReactiveObject as base class.
But if you can't do that, I will suggest you to download the source code of reactiveui and take just the pieces of code that you need:
https://github.com/reactiveui/ReactiveUI
You better don't implement certain features by yourself. The creators of the framework have dealt with many bugs and issues so their code is certainly more solid of what I or you can produce by ourselves (unless we're genius).
So, I have a message bus that instantiates message handlers through Ninject. I'd like to decorate my handlers with cross cutting concerns such as logging, transaction management, etc.
I setup my bindings like so:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Which works fantastically whenever I have a single handler of a specific message type. However, when I have more than one handler defined:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Ninject will find and inject the decorator to the message bus, and then attempt unsuccessfully to inject both handlers into the decorator constructor.
public HandlerDecorator(IMessageHandler<T> handler)
You may be thinking, why don't I just modify my decorator to accept the list of handlers? I thought about this, but that defeats the purpose of the handler. I want to be able to easily chain multiple decorators together transparently. Each instance of IMessageHandler<T> should get an entirely new chain of handlers.
I've published an example test library on GitHub that should illustrate what I'm talking about here.
Is there any way to do this in Ninject?
Use
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>().WhenParentNamed("One");
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>().WhenParentNamed("Two");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("One");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("Two");
Also be aware that most of the Bus Frameworks have some way to do decorations for message handlers. May have a look there first.
You should wrap those handlers in a composite:
public class CompositeMessageHandler<T> : IMessageHandler<T>
{
private readonly IEnumerable<IMessageHandler<T>> handlers;
CompositeMessageHandler(IEnumerable<IMessageHandler<T>> handlers)
{
this.handlers = handlers;
}
public void Handle(T message)
{
foreach (var handler in this.handlers)
{
handler.Handle(message);
}
}
}
This composite can again be injected into your decorator. Or perhaps you should do it the other way around: Wrap each handler with a decorator and wrap those into the composite.
I'm not sure how to register this with Ninject though.
I have an Aspect that implements INotifyPropertyChanged on a class. The aspect includes the following:
[OnLocationSetValueAdvice, MethodPointcut("SelectProperties")]
public void OnPropertySet(LocationInterceptionArgs args)
{
var currentValue = args.GetCurrentValue();
bool alreadyEqual = (currentValue == args.Value);
// Call the setter
args.ProceedSetValue();
// Invoke method OnPropertyChanged (ours, the base one, or the overridden one).
if (!alreadyEqual)
OnPropertyChangedMethod.Invoke(args.Location.Name);
}
This works fine when I instantiate the class normally, but I run into problems when I deserialize the class using a DataContractSerializer. This bypasses the constructor, which I'm guessing interferes with the way that PostSharp sets itself up. This ends up causing a NullReferenceException in an intercepted property setter, but before it has called the custom OnPropertySet, so I'm guessing it interferes with setting up the LocationInterceptionArgs.
Has anyone else encountered this problem? Is there a way I can work around it?
I did some more research and discovered I can fix the issue by doing this:
[OnDeserializing]
private void OnDeserializing(StreamingContext context)
{
AspectUtilities.InitializeCurrentAspects();
}
I thought, okay, that's not too bad, so I tried to do this in my Aspect:
private IEnumerable<MethodInfo> SelectDeserializing(Type type)
{
return
type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(
t => t.IsDefined(typeof (OnDeserializingAttribute), false));
}
[OnMethodEntryAdvice, MethodPointcut("SelectDeserializing")]
public void OnMethodEntry(MethodExecutionArgs args)
{
AspectUtilities.InitializeCurrentAspects();
}
Unfortunately, even though it intercepts the method properly, it doesn't work. I'm thinking the call to InitializeCurrentAspects isn't getting transformed properly, since it's now inside the Aspect rather than directly inside the aspect-enhanced class. Is there a way I can cleanly automate this so that I don't have to worry about calling this on every class that I want to have the Aspect?
Support for serialization has been added lately and is available as a hotfix.
http://www.sharpcrafters.com/downloads/postsharp-2.0/hot-fixes