How to simulate Unity's PerResolveLifetimeManager with DryIoc?
That is, reuse within the current call to resolve, but not otherwise:
var a = container.Resolve<A>();
Assert( ReferenceEquals(a.B.D, a.C.D ) );
var a2 = container.Resolve<A>();
Assert( !ReferenceEquals(a.B.D, a2.B.D ) );
with
class A
{
public B B {get;}
public C C {get;}
}
class B
{
public D D {get;}
}
class C
{
public D D {get;}
}
With Unity, I'd register D with a PerResolveLifetimeManager, but I've got no idea how to achieve that with DryIoc.
In my application, A might be a top-level view model and D an Entity Framework context: whenever I navigate (i.e. resolve a new view model), I want to create a new context to be used while this view model is active, and I want it to be shared by all dependencies that view model might have.
Here is the doc and the example below:
container.Register<A>(setup: Setup.With(openResolutionScope: true));
container.Register<B>(Reuse.ScopedTo<A>());
container.Register<D>(Reuse.ScopedTo<A>());
var a = container.Resolve<A>();
Assert( ReferenceEquals(a.B.D, a.C.D ) );
var a2 = container.Resolve<A>();
Assert( !ReferenceEquals(a.B.D, a2.B.D ) );
Related
A little clearer than the question. I want to get the same instance of a class everywhere the class is used inside of an object. I'm using google guice through out the project. Here's an example to better explain.
#Singleton class A {
C c;
D d;
#Inject public A(C c, D d){
this.c = c;
this.d = d;
}
}
class B {
Map<Integer,String> hashmap = new Hashmap<>();
public String getInfo(Integer number){
return hashmap.get(number);
}
}
#Singleton class C {
Class B;
#Inject public C( B b){
this.b = b;
}
}
#Singleton class D {
Class B;
#Inject public D(B b){
this.b = b;
}
}
So each time a new A is created. I want that A's C and D to share the same B , but I don't want all A 's to share one B . Also C and D are being injected into the constructor and A is a Singleton.
You have to define your own scope.
To do that, read the Custom Scopes page on Guice's wiki.
Edited as the original post was impossible to understand...sorry guys.
Why did I want to use expando/weakmap?
I had a custom layout/sizer element that resizes children. By using expando, I wanted to control that resizing behavior without creating a strong reference.
e.g.
var l1 = new Layout();
var e1 = new DivElement();
e1.text = 'The size of this element will remain as is';
//setting property prior to appending to avoid resizing
l1.add_resizable_attribute(e1,false);
l1.append(e1);
print(l1.isFrozen(e1));//returns true
I found a better solution, but I want to know how to map an object with data in Dart and share it across multiple objects safely and dynamically manage that.
Why did I want to share a expando property?
My Layout element may contain another layout element and form a tree. Allowing access to the expando property of an object anywhere in the tree seems a rational thing to do.
e.g.
var l1 = new Layout();
var l2 = new Layout();
var e1 = new DivElement();
e1.text = 'The size of this element will remain as is';
l1.add_resizable_attribute(e1,false);
print(l1.isFrozen(e1));//returns true
print(l2.isFrozen(e1));//returns false as l2 is not part of the tree
l1.append(l2)//forming a tree
print(l1.isFrozen(e1));//returns true
print(l2.isFrozen(e1));// returns true on l2 as well
l2.add_resizable_attribute(e1,true);
print(l1.isFrozen(e1));//changed on l2 but returns false on l1 as well
What is the problem?
Cannot merge or split expando instances.
Potential solutions
Give up on expando property/weakmap (works only on a dom element)
new HtmlElement()..dataset['allow_layout_resize_this']='false';
Did not think of this, but the simplest.
Reflection
Obvious but currently needs 'dart:mirror' to make this work with any class instances.
Traversing the tree
Complex and ugly.
class Layout extends HtmlElement{
Expando<bool> _freeze_resizing = new Expando<bool>();
Layout.created():super.created();
void add_resizable_attribute(HtmlElement e, bool isResizable) {
_freeze_resizing[e] = !isResizable;
}
isFrozen(HtmlElement e,
{bool search_down: true,
bool search_up: true
}) {
///resize allowed by default
bool v;
if (search_up) {
Layout t = _get_topmost_layout();
return t.isFrozen(
e, search_down: true,
search_up: false);
} else if (search_down) {
v = _freeze_resizing[e];
v = v == null ? false : v;
if (v) return true;
return isFrozen_in_children(e);
}
return _freeze_resizing[e];
}
bool isFrozen_in_children(e) {
for (var c in children) {
if (c is! Layout) continue;
if (c.isFrozen(
e,
search_up: false,
search_down: true
)) return true;
}
return false;
}
Layout _get_topmost_layout() {
Layout tm;
var e = this;
while (e is Layout) {
tm = e;
e = e.parent;
}
return tm;
}
void _enforce_owner_exclusive_expando(element,[bool search_up=true]){
///remove expando properties from non-owner
if(!children.contains(element)){
_freeze_resizing[element]=null;
}
void enforce_on_children(){
for(var c in children){
if(c is! Layout) continue;
c._enforce_owner_exclusive_expando(element,false);
}
}
if(search_up){
var tm = _get_topmost_layout();
tm._enforce_owner_exclusive_expando(element,false);
}else{
enforce_on_children();
}
}
append(e){
super.append(e);
_enforce_owner_exclusive_expando(element);
}
}
Generally the problem can be circumvented and Dart is still easier than javascript. This is, however, the first ever time I have found Dart frustrating.
How would you solve an issue like this?
Weakmap like structure with keys method
Yay, I've finally solved this!!!!
https://github.com/TastyCatFood/mistletoe
Has keys method
import 'package:mistletoe/mistletoe.dart';
void main(){
var m = new Mistletoe();
var t = new DateTime.now();
m.add( t, 'hi', 'bye');
print(m.keys(t));//prints 'hi'
print(m.value(t,'hi'));//prints bye;
t = null;
//With t garbage collected, m is empty now
}
Support for pseudo dynamic addition of properties
import 'package:mistletoe/mistletoe.dart';
Dynamism d = new Dynamism(expert:true);
void main(){
var o = new Object();
d.on(o).set('greetings',()=>print('hello world'));
d.on(o).invoke('greetings');//prints hello world
o = null;
//With o garbage collected, d is empty now.
}
I requested the feature here: https://github.com/dart-lang/sdk/issues/25781
published: https://pub.dartlang.org/packages/mistletoe
I have a list of Cars where each car has an engine that is defined through the Engine interface. In this example concrete types are CombustionEngine, with a variable number of cylinders, and ElectricMotor.
I want to find all (combustion) engines with four cylinders. Using Java streams I came up with this pipeline:
Car[] carsWithFourCylinders
= cars.stream()
.filter( car -> car.engine instanceof CombustionEngine )
.filter( car -> ( ( CombustionEngine )car.engine ).cylinderCount == 4 )
.toArray( Car[]::new );
While this works, I was wondering if it is possible to avoid the cast in the second filter predicate or to rewrite the pipeline altogether to be more readable?
For reference and in order to experiemnt with I've attached the full source of the example:
public class CarTest {
interface Engine { }
class CombustionEngine implements Engine {
final int cylinderCount;
CombustionEngine( int cylinderCount ) {
this.cylinderCount = cylinderCount;
}
}
class ElectricMotor implements Engine { }
class Car {
final Engine engine;
Car( Engine engine ) {
this.engine = engine;
}
}
#Test
public void filterCarsWithFourCylinders() {
List<Car> cars = Arrays.asList( new Car( new CombustionEngine( 4 ) ),
new Car( new ElectricMotor() ),
new Car( new CombustionEngine( 6 ) ) );
Car[] carsWithFourCylinders
= cars.stream()
.filter( car -> car.engine instanceof CombustionEngine )
.filter( car -> ( ( CombustionEngine )car.engine ).cylinderCount == 4 )
.toArray( Car[]::new );
assertEquals( 1, carsWithFourCylinders.length );
}
}
I don't think it is possible to avoid the cast. After all, neither Car nor Engine provide any methods which make it possible to differentiate between electric cars and those with an ICE.
But if your Engine has no methods, in my opinion it means it should not matter to the Car what kind of engine a it has.
The best I could come up with is
final List<Car> combustionCars = cars.stream()
.collect(groupingBy(c -> c.engine.getClass()))
.get(CombustionEngine.class);
long count = combustionCars
.stream()
.map(Car::getEngine)
.map(CombustionEngine.class::cast)
.filter(c -> c.cylinderCount == 4).collect(Collectors.counting());
but I am not sure if this is more readable.
In the new Vaadin 7.4 release, the new Grid widget debuted as an alternative to the venerable Table.
After getting a Grid displayed, I later want to replace the entire set of data with fresh data. Rather than update the individual rows, I want to simply replace them.
I happen to be using a BeanItemContainer for easy read-only display of some objects with JavaBeans-style getter methods.
I considered two approaches:
Two step process of replacing bean items.
(1) First remove all BeanItem objects with Container::removeAllItems method.
(2) Then add replacement BeanItem objects with the BeanItemContainer::addAll method.
Replace entire BeanItemContainer.
Call Grid::setContainerDataSource and pass a new instance of BeanItemContainer constructed with fresh data.
Below is a sample application (Vaadin 7.4.2) showing both approaches. A pair of identical Grid widgets appear. Each has a button that updates data with either approach.
Results
The first approach (removing items and adding items) works. The fresh data immediately appears.
The second approach (replacing container rather than items) seems like it should work, with nothing contrary suggested in the scant documentation. But nothing happens. No exceptions or errors occur, yet no fresh data appears. I opened Ticket # 17268 on Vaadin trac for this issue.
Perhaps there are other better ways. Please post or comment with any alternatives.
Example App
Three classes are displayed below. You should be able to copy-paste into a new Vaadin 7.4.x app.
One class is the usual "MyUI" created in every new Vaadin app.
Another is simple JavaBeans-style class, "Astronomer", providing data for the rows in our Grid. That Astronomer class includes a convenient static method for generating a List of instances. Each new Astronomer gets a random number of popularity votes, to show fresh data values.
The meaty part of the example is in the "AstronomersLayout" class which creates the pair of Grids with their assigned buttons.
I use Java 8 Lambda syntax and the new java.time classes. So you may need to change your project's settings to use Java 8. In NetBeans 8 that means Project > Properties > Sources > Source/Binary Format (popup menu) > 1.8.
MyUI.java
Get your Vaadin app going.
package com.example.vaadingridexample;
import javax.servlet.annotation.WebServlet;
import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.UI;
/**
* Example app in Vaadin 7.4.2 experimenting with two ways to replace data in a
* displayed Grid.
*
* #author Basil Bourque
*/
#Theme ( "mytheme" )
#Widgetset ( "com.example.vaadingridexample.MyAppWidgetset" )
public class MyUI extends UI
{
#Override
protected void init ( VaadinRequest vaadinRequest )
{
this.setContent( new AstronomersLayout() );
}
#WebServlet ( urlPatterns = "/*" , name = "MyUIServlet" , asyncSupported = true )
#VaadinServletConfiguration ( ui = MyUI.class , productionMode = false )
public static class MyUIServlet extends VaadinServlet
{
}
}
AstronomersLayout.java
The main part of the example.
package com.example.vaadingridexample;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.VerticalLayout;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* Layout displays a pair of Grids, each with a Button to replace its contents
* with fresh data in either of two ways: (a) Replace all the items within the
* Container, or (b) Replace container itself.
*
* #author Basil Bourque
*/
#SuppressWarnings ( "serial" )
public class AstronomersLayout extends VerticalLayout
{
// -----| Member vars |--------------------------
Grid grid_ReplaceItems;
String gridCaption_ReplaceItems = "Astronomers - Replacing Items";
Button button_ReplaceItems;
Grid grid_ReplaceContainer;
String gridCaption_ReplaceContainer = "Astronomers - Replacing Container";
Button button_ReplaceContainer;
// -----| Constructor |--------------------------
public AstronomersLayout ()
{
this.prepareWidgets();
this.composeLayout();
}
// -----| Helper Methods |--------------------------
private void prepareWidgets ()
{
// Show updating a Grid by replacing the bean items within a container.
// Grid
List<Astronomer> listA = Astronomer.makeList();
BeanItemContainer<Astronomer> containerA = new BeanItemContainer<>( Astronomer.class , listA );
this.grid_ReplaceItems = new Grid( this.gridCaption_ReplaceItems , containerA );
//this.grid_ReplaceItems.setColumnOrder( "votes" , "givenName" , "surName" , "birthYear" );
this.grid_ReplaceItems.setColumnOrder( Astronomer.FIELD.VOTES.getName() , Astronomer.FIELD.GIVENNAME.getName() , Astronomer.FIELD.SURNAME.getName() , Astronomer.FIELD.BIRTHYEAR.getName() ); // Enum is a safer way of doing this: this.grid_ReplaceItems.setColumnOrder( "votes" , "givenName" , "surName" , "birthYear" );
this.grid_ReplaceItems.setHeightMode( HeightMode.ROW ); // Show all rows of data for this grid.
this.updateCaptionAndSize( this.grid_ReplaceItems , this.gridCaption_ReplaceItems );
// Button
this.button_ReplaceItems = new Button( "Replace Items" );
this.button_ReplaceItems.addClickListener( ( ClickEvent event ) -> {
#SuppressWarnings ( "unchecked" )
BeanItemContainer<Astronomer> bic = ( BeanItemContainer<Astronomer> ) this.grid_ReplaceItems.getContainerDataSource(); // Access existing container. Cast as need be.
bic.removeAllItems(); // Remove existing items.
bic.addAll( Astronomer.makeList() ); // Add fresh bean items to existing container.
this.updateCaptionAndSize( this.grid_ReplaceItems , this.gridCaption_ReplaceItems );
} );
// Show updating a Grid by replacing the container rather than its contents.
// Grid
List<Astronomer> listB = Astronomer.makeList();
BeanItemContainer<Astronomer> containerB = new BeanItemContainer<>( Astronomer.class , listB );
this.grid_ReplaceContainer = new Grid( this.gridCaption_ReplaceContainer , containerB );
this.grid_ReplaceContainer.setColumnOrder( Astronomer.FIELD.VOTES.getName() , Astronomer.FIELD.GIVENNAME.getName() , Astronomer.FIELD.SURNAME.getName() , Astronomer.FIELD.BIRTHYEAR.getName() );
this.grid_ReplaceContainer.setHeightMode( HeightMode.ROW ); // Show all rows of data for this grid.
this.updateCaptionAndSize( this.grid_ReplaceContainer , this.gridCaption_ReplaceContainer );
// Button
this.button_ReplaceContainer = new Button( "Replace Container" );
this.button_ReplaceContainer.addClickListener( ( ClickEvent event ) -> {
#SuppressWarnings ( "unchecked" )
BeanItemContainer<Astronomer> bic = new BeanItemContainer<>( Astronomer.class , listB ); // Create replacement container.
this.grid_ReplaceContainer.setContainerDataSource( bic );
this.updateCaptionAndSize( this.grid_ReplaceContainer , this.gridCaption_ReplaceContainer );
} );
}
private void updateCaptionAndSize ( final Grid grid , final String caption )
{
// Caption
grid.setCaption( caption + " ( updated " + this.now() + " )" ); // Update caption of Grid to indicate fresh data.
// Show all rows.
double h = grid.getContainerDataSource().size() > 0 ? grid.getContainerDataSource().size() : 3; // Cannot set height to zero rows. So if no data, set height to some arbitrary number of (empty) rows.
grid.setHeightByRows( h );
}
private void composeLayout ()
{
// Initialize this layout.
this.setMargin( true );
this.setSpacing( true );
// Content
this.addComponent( this.button_ReplaceItems );
this.addComponent( this.grid_ReplaceItems );
this.addComponent( this.button_ReplaceContainer );
this.addComponent( this.grid_ReplaceContainer );
}
// Helper method.
private String now ()
{
// Get current time in UTC. Truncate fractional seconds. Append a 'Z' to indicate UTC time zone.
return ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_LOCAL_TIME ).substring( 0 , 8 ).concat( "Z" );
}
}
Astronomer.java
The data, the bean items, stored in a BeanItemContainer for display in a Grid.
A nested Enum provides a safer way to refer to the field names in the other class, AstronomersLayout for call to setColumnOrder.
package com.example.vaadingridexample;
import java.util.ArrayList;
import java.util.List;
/**
* Provides the beans to appear as rows in a BeanItemContainer backing a Grid.
*
* Note the static convenience method for generating a List of instances.
*
* #author Basil Bourque
*/
public class Astronomer
{
public enum FIELD
{
SURNAME( "surname" ),
GIVENNAME( "givenName" ),
BIRTHYEAR( "birthYear" ),
VOTES( "votes" );
private String name;
private FIELD ( String s )
{
this.name = s;
}
public String getName ()
{
return this.name;
}
}
// Members
private String surname;
private String givenName;
private Integer birthYear;
private Integer votes;
public Astronomer ( final String givenName , final String surName , final Integer birthYear )
{
this.surname = surName;
this.givenName = givenName;
this.birthYear = birthYear;
this.votes = this.random();
}
public static List<Astronomer> makeList ()
{
List<Astronomer> list = new ArrayList<>( 7 );
list.add( new Astronomer( "Hypatia" , "of Alexandria" , -370 ) );
list.add( new Astronomer( "Nicolaus" , "Copernicus" , 1473 ) );
list.add( new Astronomer( "Tycho" , "Brahe" , 1546 ) );
list.add( new Astronomer( "Giordano" , "Bruno" , 1548 ) );
list.add( new Astronomer( "Galileo" , "Galilei" , 1564 ) );
list.add( new Astronomer( "Johannes" , "Kepler" , 1571 ) );
list.add( new Astronomer( "Isaac" , "Newton" , 1643 ) );
list.add( new Astronomer( "Caroline" , "Herschel" , 1750 ) );
return list;
}
// ----| Helper Methods |----------------------------------
private Integer random ()
{
return ( int ) ( java.lang.Math.random() * 100 );
}
// ----| Bean Getters |----------------------------------
public String getSurname ()
{
return this.surname;
}
public String getGivenName ()
{
return this.givenName;
}
public Integer getBirthYear ()
{
return this.birthYear;
}
public Integer getVotes ()
{
return this.votes;
}
// ----| Object Superclass |----------------------------------
#Override
public String toString ()
{
return "Astronomer{ " + "surName=" + surname + " | givenName=" + givenName + " | birthYear=" + birthYear + " | votes=" + votes + " }";
}
}
You can simply get the record you have removed from button through clickListener with .getSelectedRow() .
After this you can remove your item from your grid with .removeItem().
IE:
Grid yourGrid = new Grid();
yourGrid.setContainerDataSource(yourData);
Button removeItem = new Button("Remove item");
removeItem.addClickListener(l -> {
Item selectedItem = (Item) yourGrid.getSelectedRow();
yourGrid.getContainerDataSource().removeItem(selectedItem);
});
Bye!
Consider this in D programming language:
import luad.all
class C1
{
auto l1 = new LuaState;
l1["somebool"] = true;
this()
~this()
}
class C2
{
C1 cc = new C1;
auto l2 = new LuaState;
// here I want to inject l1["somebool"] to l2
}
void main() { C2 cx = new C2; }
As a solution, it is possible that I make a local variable
bool var = cc.l1["somebool"]
and then insert it in l2 - but this does not seem to be the best solution.
Is there any way to copy one lua stack defined inside a class to another stack in another class?
I don't know much about LuaD or Lua, but you can extract globals into a struct as shown in the last example on this page. And then you can set the values from the struct into l2 state.
// warning: untested
struct State
{
bool somebool;
}
State state;
l1.globals.toStruct!State(state);
foreach (member; __traits(allMembers, State))
{
l2.globals.set(member, __traits(getMember, state, member));
}