For example I have OnMethodBoundaryAspect logger which I apply to iterator method:
public override void OnEntry(MethodExecutionArgs args) {
BeginMethodScope( args );
Logger.LogRequestEntry();
}
public override void OnSuccess(MethodExecutionArgs args) {
Logger.LogRequestSuccess();
}
public override void OnException(MethodExecutionArgs args) {
Logger.LogRequestError( args.Exception );
}
public override void OnExit(MethodExecutionArgs args) {
EndMethodScope( args );
}
If I use semantic advising:
OnEntry is invoked when IEnumerable is started.
OnExit is invoked when IEnumerable is finished.
If I use non-semantic advising:
OnEntry/OnExit is invoked before/after creation of IEnumerable.
But what if I want to use both ways at once? Because I want to log the method call itself (not iteration starting).
Maybe I can achieve this with low-level advices?
Yes, you can achieve this by creating two groups of advices within the same aspect, as shown in the example below.
[PSerializable]
public class MyAspect : MethodLevelAspect
{
[OnMethodEntryAdvice(SemanticallyAdvisedMethodKinds = SemanticallyAdvisedMethodKinds.None)]
[AdviceDependency(AspectDependencyAction.Order, AspectDependencyPosition.Before, nameof(OnEntrySemantic))]
[SelfPointcut]
public void OnEntry( MethodExecutionArgs args )
{
Console.WriteLine("OnEntry");
}
[OnMethodExitAdvice( Master = nameof( OnEntry ) )]
public void OnExit( MethodExecutionArgs args )
{
Console.WriteLine( "OnExit" );
}
[OnMethodEntryAdvice]
[SelfPointcut]
public void OnEntrySemantic( MethodExecutionArgs args )
{
Console.WriteLine( "OnEntrySemantic" );
}
[OnMethodExitAdvice( Master = nameof( OnEntrySemantic ) )]
public void OnExitSemantic( MethodExecutionArgs args )
{
Console.WriteLine( "OnExitSemantic" );
}
}
P.S. The current version of PostSharp will emit a build-time warning for the example above. This is due to a bug that should be fixed in one of the upcoming releases. The run-time behavior of the aspect is not affected.
Related
I think I fixed this error but I want to be certain I did it the right way.
Also I am not sure why is it happening this way.
Code before fix:
private Gee.ArrayList<Gtk.Widget> menuButtons;
// Some other code here
public override void remove (Gtk.Widget widget) {
if (widget in menuButtons) {
widget.unparent ();
menuButtons.remove ( widget ); // Look at this method call
if (this.get_visible () && widget.get_visible ()) {
this.queue_resize_no_redraw ();
}
}
}
The code causes:
ERROR:arraylist.c:957:gee_array_list_real_get: assertion failed: (index < _size)
./run: line 3: 11054 Aborted (core dumped) ./bin
Code after fix:
private Gee.ArrayList<Gtk.Widget> menuButtons;
// Some other code here
public override void remove (Gtk.Widget widget) {
if (widget in menuButtons) {
widget.unparent ();
if (this.get_visible () && widget.get_visible ()) {
this.queue_resize_no_redraw ();
menuButtons.remove ( widget ); // Moved method call here
}
}
}
And now it works, I am not sure but it might be something to do with remove method being called asynchronously, is it?
Any good explanation?
Is it a correct fix of a problem?
#After checking the code again I am certain that it is not a correct fix of my problem because menuButtons.remove ( widget ); never gets called in my case. The widget stays in the list and that is unwanted behaviour.
MVCE:
MyContainer.vala
public class MyContainer : Gtk.Container {
// ArrayList for storing menu buttons
private Gee.ArrayList<Gtk.Widget> menuButtons;
public MyContainer () {
base.set_has_window (false);
menuButtons = new Gee.ArrayList<Gtk.Widget> ();
}
public override void add (Gtk.Widget widget) {
widget.set_parent (this);
menuButtons.add (widget);
}
public override void remove (Gtk.Widget widget) {
if (widget in menuButtons) {
widget.unparent ();
menuButtons.remove ( widget ); // After removing the widget from the List I get "assertion failed error"
if (this.get_visible () && widget.get_visible ()) {
this.queue_resize_no_redraw ();
}
}
}
public override void forall_internal (bool include_internals, Gtk.Callback callback) {
foreach (var widget in menuButtons) {
callback (widget);
}
}
}
SimpleGtkApplication.vala
public class SimpleGtkApplication : Gtk.Application {
public SimpleGtkApplication () {
Object (application_id: "simple.gtk.application", flags: ApplicationFlags.FLAGS_NONE);
}
protected override void activate () {
Gtk.ApplicationWindow window = new Gtk.ApplicationWindow (this);
window.set_default_size (800, 600);
window.title = "SimpleGtkApplication";
Gtk.Container container = new MyContainer ();
container.add ( new Gtk.Button.with_label ("Button 1") );
container.add ( new Gtk.Button.with_label ("Button 2") );
window.add ( container );
window.show_all ();
}
public static int main (string[] args) {
SimpleGtkApplication app = new SimpleGtkApplication ();
return app.run (args);
}
}
Compile with: --pkg=gtk+-3.0 --pkg=gee-0.8
A couple of points:
You are overriding Gtk.Container::remove, but never chaining up to the parent class's implementation by calling base.remove(), which will cause you problems in the long run.
In MyContainer::remove you are calling widget.unparent(), which may be causing some kind of secondary invocation of MyContainer::remove. If so, both times the widget in menuButtons test evaluates to true, but when the original invocation tries to remove the widget from the list, it's already gone, hence the assertion failure.
TL;DR: Replace the call to widget.unparent() with base.remove(widget).
PS: I'd be really suprised if you need the explicit this.queue_resize_no_redraw() call either, GTK+ really should be managing that for you.
As Michael wrote, you are doing a lot of the things that Gtk could do for you yourself. You are also not calling the base methods in your overrides.
You are directly deriving from Gtk.Container, I have adapted your MVCE to use a Gtk.Box instead and get no warnings and no assertions with this code:
public class MyContainer : Gtk.Box {
private Gee.ArrayList<Gtk.Widget> menuButtons;
public MyContainer () {
menuButtons = new Gee.ArrayList<Gtk.Widget> ();
}
public override void add (Gtk.Widget widget) {
base.add (widget);
menuButtons.add (widget);
}
public override void remove (Gtk.Widget widget) {
if (widget in menuButtons) {
menuButtons.remove (widget);
}
base.remove (widget);
}
}
In java-9 Skins made it into public scope, while Behaviors are left in the dark - nevertheless changed considerably, in now using InputMap for all input bindings.
CellBehaviorBase installs mouse bindings like:
InputMap.MouseMapping pressedMapping, releasedMapping;
addDefaultMapping(
pressedMapping = new InputMap.MouseMapping(MouseEvent.MOUSE_PRESSED, this::mousePressed),
releasedMapping = new InputMap.MouseMapping(MouseEvent.MOUSE_RELEASED, this::mouseReleased),
new InputMap.MouseMapping(MouseEvent.MOUSE_DRAGGED, this::mouseDragged)
);
A concrete XXSkin now installs the behavior privately:
final private BehaviorBase behavior;
public TableCellSkin(TableCell control) {
super(control);
behavior = new TableCellBehavior(control);
....
}
The requirement is replace the mousePressed behavior (in jdk9 context). The idea is to grab super's field reflectively, dispose all its mappings and install the custom behavior. For some reason that I don't understand, the old bindings are still active (though the old mappings are empty!) and are invoked before the new bindings.
Below is a runnable example to play with: the mapping to mousePressed is simply implemented to do nothing, particularly to not invoke super. To see the old bindings at work, I set a conditional debug breakpoint at CellBehaviorBase.mousePressed like (in Eclipse):
System.out.println("mousePressed super");
new RuntimeException("whoIsCalling: " + getNode().getClass()).printStackTrace();
return false;
Run a debug and click into any cell, then the output is:
mousePressed super
java.lang.RuntimeException: whoIsCalling: class de.swingempire.fx.scene.control.cell.TableCellBehaviorReplace$PlainCustomTableCell
at com.sun.javafx.scene.control.behavior.CellBehaviorBase.mousePressed(CellBehaviorBase.java:169)
at com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
//... lots more of event dispatching
// until finally the output in my custom cell behavior
Feb. 02, 2016 3:14:02 NACHM. de.swingempire.fx.scene.control.cell.TableCellBehaviorReplace$PlainCustomTableCellBehavior mousePressed
INFORMATION: short-circuit super: Bulgarisch
I would expect to only see the very last part, that is the printout by my custom behavior. It feels like I'm somehow fundamentally off - but can't nail it. Ideas?
The runnable code (sorry for its length, most is boiler-plate, though):
public class TableCellBehaviorReplace extends Application {
private final ObservableList<Locale> locales =
FXCollections.observableArrayList(Locale.getAvailableLocales());
private Parent getContent() {
TableView<Locale> table = createLocaleTable();
BorderPane content = new BorderPane(table);
return content;
}
private TableView<Locale> createLocaleTable() {
TableView<Locale> table = new TableView<>(locales);
TableColumn<Locale, String> name = new TableColumn<>("Name");
name.setCellValueFactory(new PropertyValueFactory<>("displayName"));
name.setCellFactory(p -> new PlainCustomTableCell<>());
TableColumn<Locale, String> lang = new TableColumn<>("Language");
lang.setCellValueFactory(new PropertyValueFactory<>("displayLanguage"));
lang.setCellFactory(p -> new PlainCustomTableCell<>());
table.getColumns().addAll(name, lang);
return table;
}
/**
* Custom skin that installs custom Behavior. Note: this is dirty!
* Access super's behavior, dispose to get rid off its handlers, install
* custom behavior.
*/
public static class PlainCustomTableCellSkin<S, T> extends TableCellSkin<S, T> {
private BehaviorBase<?> replacedBehavior;
public PlainCustomTableCellSkin(TableCell<S, T> control) {
super(control);
replaceBehavior();
}
private void replaceBehavior() {
BehaviorBase<?> old = (BehaviorBase<?>) invokeGetField(TableCellSkin.class, this, "behavior");
old.dispose();
// at this point, InputMap mappings are empty:
// System.out.println("old mappings: " + old.getInputMap().getMappings().size());
replacedBehavior = new PlainCustomTableCellBehavior<>(getSkinnable());
}
#Override
public void dispose() {
replacedBehavior.dispose();
super.dispose();
}
}
/**
* Custom behavior that's meant to override basic handlers. Here: short-circuit
* mousePressed.
*/
public static class PlainCustomTableCellBehavior<S, T> extends TableCellBehavior<S, T> {
public PlainCustomTableCellBehavior(TableCell<S, T> control) {
super(control);
}
#Override
public void mousePressed(MouseEvent e) {
if (true) {
LOG.info("short-circuit super: " + getNode().getItem());
return;
}
super.mousePressed(e);
}
}
/**
* C&P of default tableCell in TableColumn. Extended to install custom
* skin.
*/
public static class PlainCustomTableCell<S, T> extends TableCell<S, T> {
public PlainCustomTableCell() {
}
#Override protected void updateItem(T item, boolean empty) {
if (item == getItem()) return;
super.updateItem(item, empty);
if (item == null) {
super.setText(null);
super.setGraphic(null);
} else if (item instanceof Node) {
super.setText(null);
super.setGraphic((Node)item);
} else {
super.setText(item.toString());
super.setGraphic(null);
}
}
#Override
protected Skin<?> createDefaultSkin() {
return new PlainCustomTableCellSkin<>(this);
}
}
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setScene(new Scene(getContent(), 400, 200));
primaryStage.setTitle(FXUtils.version());
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* Reflectively access super field.
*/
public static Object invokeGetField(Class source, Object target, String name) {
try {
Field field = source.getDeclaredField(name);
field.setAccessible(true);
return field.get(target);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
#SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(TableCellBehaviorReplace.class.getName());
}
Edit
The suggestion inherit from the abstract skin XXSkinBase instead of the concrete XXSkin (then you are free to install whatever behavior you want, dude :-) is very reasonable and should be the first option. In the particular case of XX being TableCell, that's currently not possible, as the base class contains abstract package-private methods. Also, there are XX that don't have an abstract base (like f.i. ListCell).
Might be a bug in InputMap:
Digging into the sources I found some internal book-keeping (eventTypeMappings) parallel to mappings (these are the handlers). InputMap is listening to changes in mappings and updates the internal book-keeping on changes
mappings.addListener((ListChangeListener<Mapping<?>>) c -> {
while (c.next()) {
// TODO handle mapping removal
if (c.wasRemoved()) {
for (Mapping<?> mapping : c.getRemoved()) {
removeMapping(mapping);
}
}
// removeMapping
private void removeMapping(Mapping<?> mapping) {
// TODO
}
Meaning that the internal structure is never cleaned, particularly not when the mappings are removed in behavior.dispose(). When looking up eventHandlers - by inputMap.handle(e), see debug stacktrace shown in the question - the old handler is found in the internal book-keeping structure.
Joys of early experiments ... ;-)
At the end, a (very dirty, very hacky!) solution is to take over InputMap's job and force a cleanup of the internals:
private void replaceBehavior() {
BehaviorBase<?> old = (BehaviorBase<?>) invokeGetField(TableCellSkin.class, this, "behavior");
old.dispose();
cleanupInputMap(old.getInputMap());
// at this point, InputMap mappings are empty:
// System.out.println("old mappings: " + old.getInputMap().getMappings().size());
replacedBehavior = new PlainCustomTableCellBehavior<>(getSkinnable());
}
/**
* This is a hack around InputMap not cleaning up internals on removing mappings.
* We remove MousePressed/MouseReleased/MouseDragged mappings from the internal map.
* Beware: obviously this is dirty!
*
* #param inputMap
*/
private void cleanupInputMap(InputMap<?> inputMap) {
Map eventTypeMappings = (Map) invokeGetField(InputMap.class, inputMap, "eventTypeMappings");
eventTypeMappings.remove(MouseEvent.MOUSE_PRESSED);
eventTypeMappings.remove(MouseEvent.MOUSE_RELEASED);
eventTypeMappings.remove(MouseEvent.MOUSE_DRAGGED);
}
BTW: just in case anybody is wondering wtf - without, my hack around the missing commitOnFocusLost when editing a cell stopped working in java-9.
Try in PlainCustomTableCellSkin to inherit from the abstract class TableCellSkinBase rather than from TableCellSkin.
Then you can call the super constructor, which takes an TableCellBehaviorBase object as additional param.
Then you can save your time replacing it, by initializing it directly with the right one.
Just for more claryfication:
TableCellSkin extends TableCellSkinBase
TableCellBehavior extends TableCellBehaviorBase
One more thing. You need to also call super.init(tableCell) in your constructor.
Take the TableCellSkin class as reference.
I'm using Trial Ultimate version of PostSharp 4.0 but this doesn't work for me. Can you please check my code and advise. The error doesn't gets logged. And if i put the breakpoint doesn't hit onException method
This is code that I've written for Error handling Aspect
[Serializable]
public class MyMethodAspectAttribute : OnMethodBoundaryAspect
{
public MyMethodAspectAttribute()
{
this.ApplyToStateMachine = true;
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.Write("Method Entry");
}
public override void OnException(MethodExecutionArgs args)
{
Console.Write(args.Exception.Message);
args.ReturnValue = null;
args.FlowBehavior = FlowBehavior.Return;
}
}
This is class where I've implemented this aspect
public class ErrorMethods
{
[MyMethodAspect]
public Task<int> Calculate(int i, int j)
{
var task = Task.Factory.StartNew(
() => i / j);
return task;
}
}
This is how I've used this method
private async void Button_Click(object sender, RoutedEventArgs e)
{
var obj = new ErrorMethods();
var result = await obj.Calculate(1, 0);
if (null == result)
{
MessageBox.Show("error");
}
}
The Calculate method in your example is not an async method, so setting ApplyToStateMachine aspect's property doesn't have effect on this method. The exception is thrown when a newly created task executes in the background and the aspect has no chance of catching it.
If you change your Calculate method to async method, then the async state machine execution can be intercepted by the aspect and OnException handler is invoked upon exception.
Note, however that setting the ReturnValue and FlowBehavior does not alter the flow of the state machine, so the exception will not be swallowed.
public class ErrorMethods
{
[MyMethodAspect]
public async Task<int> Calculate( int i, int j )
{
return await Task.Factory.StartNew( () => i / j );
}
}
PLEASE HELP ME TO FIND THIS ANSWER
NULL POINTER EXCEPTION ERROR HELP ME
on these two lines
25,83
null pointer exception please correct my code
i created a object l with reference to class linkk
to access methods in the class
but while accessing the methods in the class with different conditions
it is showing null pointer exception
i didnt finish the code due to this error im struck at this point i cant move
further
this is my post
in overflow
i have read answers in overflow but this is the
first time fr me to post a question in overflow ,
today i created a ac nd posting this question please help me frnds
import java . util.Scanner;
class node
{
int i,q;
node next;
node prev;
}
class link{
public static void main(String args[])
{
linkk l = new linkk();
l.op();
int user=0;
while(user!=10)
{Scanner a=new Scanner(System.in);
if(user==1)
{
System.out.println("\nenter data\n");
l.create(a.nextInt());
}System.out.println("\n1.create link\n2.insert beginning\n3.insert middle\n4.insert end\n5.delete data\n6.reverse");
user=a.nextInt();
}
if(user==2)
l.insertbeg();
if(user==3)
l.insertmid();
if(user==4)
l.insertend();
if(user==5)
l.del();
if(user==6)
l.reverse();
if(user==7)
l.display();
}
}
class linkk
{
node temp4;
int ch,add,cnt=0,t=0,b;
node p= new node();
node q;
node last;
node first=null;
public boolean isEmpty()
{
return first == null;
}
public void insertbeg()
{
}
public void insertmid()
{
}
public void insertend()
{
}
public void del()
{
}
public void reverse()
{
}
public void display()
{
}
public void create(int val)
{
first.i=val;
first.next=null;
cnt++;
}
public void ob()
{
}
public void op()
{
}
}
Your defined first as null as node first=null; and you are trying to access i with first object using first.i=val; by calling l.create(a.nextInt());.
You should initialize first as below:
node first = new node();//and then access i of it and so on.
Why does .net MVC source code ControllerBuilder use a delegate to assign the controller factory?:
private Func<IControllerFactory> _factoryThunk;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factoryThunk = () => controllerFactory;
}
Why can't it just assign the ControllerFactory directly?, ie:
private IControllerFactory _factory;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factory = controllerFactory;
}
public void SetControllerFactory(Type controllerFactoryType) {
_factory = (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
}
The reason that _factoryThunk is currently defined as a Func<IControllerFactory> is that it's a generic means to support both overloads:
void SetControllerFactory(Type);
void SetControllerFactory(IControllerFactory);
The implementation of the first one uses the fact that _factoryThunk is a Func by declaring that Func inline by using Activator to instantiate the Type lazily:
this._factoryThunk = delegate {
IControllerFactory factory;
try
{
factory = (IControllerFactory) Activator.CreateInstance(controllerFactoryType);
}
catch (Exception exception)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, new object[] { controllerFactoryType }), exception);
}
return factory;
};
Therefore, the reason the other overload looks like it has a spurious implementation is that since _factoryThunk is declared as a Func, the line you propose wouldn't have even compiled:
_factoryThunk = controllerFactory;
_factoryThunk is a Func<IControllerFactory> whereas controllerFactory is an IControllerFactory -- incompatible types.