I've created a facility for castle windsor to automatic configure an instance, it works great except for the type with an interceptor! In that cases the ComponentCreated event doesn't fire and i can't configure my instance, how can I intercept the creation of a proxied class?
This is my facility code:
_conf = this.Kernel.Resolve<Configuration>();
this.Kernel.ComponentCreated += (s, o) =>
{
//Subscribe the every IHandler to the caliburn micro event aggregator
if (typeof(IHandle).IsAssignableFrom(o.GetType()))
Kernel.Resolve<IEventAggregator>().Subscribe(o);
var attr = o.GetType().GetCustomAttributes(false).OfType<ConfigurableAttribute>().FirstOrDefault();
SettingsCollection setter = null;
if (attr != default(ConfigurableAttribute) && (setter = _conf.GetSettings(attr.Name)) != null)
setter.Set(o);
};
Solution
the ComponentCreated event parameter "s" is a ComponentModel so it holds the unproxied type in the Implementation property!
My fixed code look like this:
this.Kernel.ComponentCreated += (s, o) =>
{
var attr = o.GetType().GetCustomAttributes(false).OfType<ConfigurableAttribute>().FirstOrDefault();
SettingsCollection setter = null;
if(attr != default(ConfigurableAttribute) && (setter = _conf.GetSettings(attr.Name)) != null)
setter.Set(o);
}
Related
The framework layout is like the following
/modules/module_name/controller_name.php
/modules/module_name/templates/controller_name.php
The controller and (view / template) always has the same name.
Is there anyway to create a hotkey to switch between the two?
I created a plugin with the following action and its working well.
#Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getProject();
VirtualFile vFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
String fileName = vFile != null ? vFile.getName() : null;
if(fileName == null){
return;
}
String filePath = vFile.getPath();
String fileDirectory = filePath.replace(fileName,"");
String newPath;
if(fileDirectory.contains(File.separator+"templates"+File.separator)){
newPath = filePath.replace("templates"+File.separator+fileName,fileName);
}else{
newPath = filePath.replace(fileName,"templates"+File.separator+fileName);
}
VirtualFile newVFile = com.intellij.openapi.vfs.LocalFileSystem.getInstance().findFileByPath(newPath);
if (newVFile == null) {
return;
}
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
fileEditorManager.openFile(newVFile,true,true);
}
Okay, this is a hard one to explain but I'll try my best.
I have a JTextField and a JComboBox in a JTable, whose getCellEditor method has been overriden as follows:
public TableCellEditor getCellEditor( int row, int column ) {
if ( column == 3 ) {
// m_table is the JTable
if ( m_table.getSelectedRowCount() == 1 ) {
JComboBox choices = new JComboBox();
choices.setEditable( true );
choices.addItem( new String( "item 1" ) );
return new DefaultCellEditor( choices );
}
return super.getCellEditor( row, column );
}
Here are the behavioral differences (NOTE that from this point on, when I say JTextField or JComboBox, I mean the CELL in the JTable containing either component):
When I click once on a JTextField, the cell is highlighted. Double clicking brings up the caret and I can input text. Whereas, with a JComboBox, single clicking brings up the caret to input text, as well as the combo drop down button.
When I tab or use the arrow keys to navigate to a JTextField and then start typing, the characters I type automatically get entered into the cell. Whereas, when I navigate to a JComboBox the same way and then start typing, nothing happens apart from the combo drop down button appearing. None of the characters I type get entered unless I hit F2 first.
So here's my question: What do I need to do have JComboBoxes behave exactly like JTextFields in the two instances described above?
Please do not ask why I'm doing what I'm doing or suggest alternatives (it's the way it is and I need to do it this way) and yes, I've read the API for all components in question....the problem is, it's a swing API.
Further Googling led me to the following article:
http://www.jroller.com/santhosh/entry/keyboard_handling_in_tablecelleditor
Although it doesn't describe the same issue as mine, it definitely shares some common traits.
Using some of the suggestions in that article, I was able to (atleast) resolve the keyboard bit of my problem (the one described in point 2 of my question). I did this by overriding the processKeyBinding method of JTable as follows:
protected boolean processKeyBinding( KeyStroke key_stroke, KeyEvent e, int condition, boolean pressed ) {
Object source = e.getSource();
if ( source instanceof JTable ) {
JTable table = (JTable) source;
Component comp = table.getEditorComponent();
if ( comp instanceof JComboBox ) {
JComboBox combo_box = (JComboBox) comp;
// this bit is quite hacky. Since I want comboboxes to behave exactly like textfields,
// simply check to see how a textfield would handle this event.
JTextField tmp_field = new JTextField();
InputMap input_map = tmp_field.getInputMap( condition );
ActionMap action_map = tmp_field.getActionMap();
if( input_map != null && action_map != null && isEnabled() ) {
Object binding = input_map.get( key_stroke );
Action action = ( binding == null ) ? null : action_map.get( binding );
if( action != null ) {
combo_box.requestFocus();
ComboBoxEditor combo_editor = combo_box.getEditor();
JTextField text_field = (JTextField) combo_editor.getEditorComponent();
if ( e.getKeyChar() == ' ' ) { // backspace
String cur_val = text_field.getText();
if ( ! cur_val.equals( "" ) )
text_field.setText( cur_val.substring( 0, cur_val.length() - 1 ) );
}
else
text_field.setText( text_field.getText() + e.getKeyChar() );
return false;
}
}
}
}
return super.processKeyBinding( key_stroke, e, condition, pressed );
}
This method seems like bit of a hack to me but then again it's swing, so it might be reasonable.
The problem of getting JComboBoxes to behave like JTextFields in the scenario described in point 1 of my question (i.e when using a mouse) is still open, if someone want's to have a go at it.
Ash
An alternative for bullet 2 is to move all the passing-on of the keyEvents into a custom JComboBox implementation: in there, implement its processKeyBinding similar to table.processKeyBinding. Something like:
public static class JTableEditorComboBox extends JComboBox {
#Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
int condition, boolean pressed) {
boolean result = super.processKeyBinding(ks, e, condition, pressed);
if (!result)
result = processKeyBindingForTextField(ks, e, condition, pressed);
return result;
}
private boolean processKeyBindingForTextField(KeyStroke ks, KeyEvent e,
int condition, boolean pressed) {
// sanity check: really used as cellEditor
if (!Boolean.TRUE.equals(getClientProperty("JComboBox.isTableCellEditor"))
|| !isEditable()
|| !(getEditor().getEditorComponent() instanceof JTextField)) return false;
JTextField field = (JTextField) getEditor().getEditorComponent();
// basically c&p JComponent.processKeyBinding (it's protected so
// can't call directly from here)
InputMap map = field.getInputMap(WHEN_FOCUSED);
ActionMap am = field.getActionMap();
if(map != null && am != null && isEnabled()) {
Object binding = map.get(ks);
Action action = (binding == null) ? null : am.get(binding);
if (action != null) {
return SwingUtilities.notifyAction(action, ks, e, field,
e.getModifiers());
}
}
return false;
}
}
Then, use an instance of that in your cellEditor, like:
JTable table = new JTable(new AncientSwingTeam()) {
#Override
public TableCellEditor getCellEditor(int row, int column) {
if (column == 1) {
// m_table is the JTable
JComboBox choices = new JTableEditorComboBox();
choices.setEditable(true);
choices.addItem(new String("item 1"));
DefaultCellEditor editor = new DefaultCellEditor(choices);
editor.setClickCountToStart(2);
return editor;
}
return super.getCellEditor(row, column);
}
};
I want to register a generic delegate that resolves itself at runtime, but I cannot find a way to do this on generics.
Given a delegate that looks like this:
public delegate TOutput Pipe<in TInput, out TOutput>(TInput input);
And given a discretely registered delegate that look like this:
public class AnonymousPipe<TInput, TOutput>
{
public Pipe<TInput, TOutput> GetPipe(IContext context)
{...}
I want to register a function along the lines of this:
builder.RegisterGeneric(typeof(Pipe<,>)).As(ctx =>
{
var typeArray = ctx.RequestedType.GetGenericArguments();
// this can be memoized
var pipeDefinition = ctx.Resolve(typeof(AnonymousPipe<,>).MakeGenericType(typeArray));
return pipeDefinition.GetPipe(ctx);
I cannot find a way to provide an implementation of the generic as a parameter in Autofac - I may just be missing something. I know I can do this through a generic object or interface, but I want to stick with the lightness of a delegate. It makes unit testing super simple on the injection of these.
Any thoughts? I am having to do discrete registrations at the moment(one per type combination and no generics).
I can only come up with the registration source solution (the universal hammer in Autofac.)
class PipeSource : IRegistrationSource
{
public bool IsAdapterForIndividualComponents { get { return true; } }
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt == null || !swt.ServiceType.IsGenericType)
yield break;
var def = swt.ServiceType.GetGenericTypeDefinition();
if (def != typeof(Pipe<,>))
yield break;
var anonPipeService = swt.ChangeType(
typeof(AnonymousPipe<,>).MakeGenericType(
swt.ServiceType.GetGenericArguments()));
var getPipeMethod = anonPipeService.ServiceType.GetMethod("GetPipe");
foreach (var anonPipeReg in registrationAccessor(anonPipeService))
{
yield return RegistrationBuilder.ForDelegate((c, p) => {
var anon = c.ResolveComponent(anonPipeReg, p);
return getPipeMethod.Invoke(anon, null); })
.As(service)
.Targeting(anonPipeReg)
.CreateRegistration();
}
}
}
Then:
builder.RegisterSource(new PipeSource());
Now, I'm certain that I can't type that code into a web page and have it actually compile and run, but it might come close :)
Currently this is what I have:
public partial class LinqToSqlEntity {
public IQueryable<AnotherLinqToSqlEntity> AnotherLinqToSqlEntities {
using(DataContext context = new DataContext) {
return context.AnotherLinqToSqlEntities.Where(item => item.Property == SOME_VALUE);
}
}
}
Is there a way to get the DataContext of this so that I would not need to create a new DataContext?
Sorry, that is not possible. An entity or querable in that case keeps no direct reference of the context.
You can achieve that using the reflection by figuring out if PropertyChanging event was hooked up, but consider this a hack and maybe you can avoid using it with better design.
Our use case of this is on detach_EntityName delegate where we change the default Linq behaviour of only deleting the foreign key of a record (setting it to null), with the actual delete from DB.
public static DataContext GetDataContextFromEntityObject(object entity)
{
// Use a reflection to get the invocaiton list.
var o = (PropertyChangingEventHandler)entity.GetType().GetField("PropertyChanging", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(entity);
var o = GetFieldValue(entity, "PropertyChanging");
if (o == null) return null;
var invocationList = o.GetInvocationList();
if (invocationList != null)
{
// DataContext changes are tracked through StandardChangeTracker
object changeTracker = (from i in invocationList where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault();
if (changeTracker != null)
{
object services = GetFieldValue(changeTracker, "services");
return (DataContext)GetFieldValue(services, "context");
}
}
return null;
}
private static object GetFieldValue(object instance, string propertyName)
{
return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance);
}
The task was meant to be quite simple: I needed to initialize variable with new keyword dynamically, depending on it's type. For example:
public var object:Sprite;
...
object = new Sprite();
In this case type is Sprite, but it could be anything and a method which actually instantiates it with new, doesn't know with what type it was declared. Of course I could store type (or class name) in string variable and instantiate object with it. But I just wonder if I could get that type info from the object itself, 'cause it's declared in a class and logically thinking it's type info might be stored somewhere and be retrievable.
Yes, you can, but the variable must be public (or have accessor methods), and you need its name as a String:
Use describeType() to get an XML Description of your class, then get accessors and variables as XMLList, iterate until you find your variable's name, and get the class by calling getDefinitionByName(). Here's an example:
var className : String = "";
var type:XML = describeType (this);
var variables:XMLList = type..variable;
for each (var variable:XML in variables) {
if (variable.#name == myVariableName) {
className = variable.#type;
break;
}
}
if (className == "") {
var accessors:XMLList = type..accessor;
for each (var accessor:XML in accessors) {
if (accessor.#name == myVariableName) {
className = accessor.#type;
break;
}
}
}
if (className=="") {
trace ("no such variable");
return;
}
var ClassReference : Class = getDefinitionByName( className.replace ("::", ".") ) as Class;
myVariable = new ClassReference( );
I can't figure out how to "reply" to an answer, otherwise I would add this to the current top answer.
If you have a list of known types that the object could be, you could test against those types using typeof.
switch(typeof unknownVar)
{
case typeof Function:
unknownVar = new Function();
break;
case typeof String:
unknownVar = "Bruce Lee";
break;
case typeof Number:
unknownVar = 3.14;
break;
default:
trace(typeof unknownVar); // This is not normally helpful...
}
In short no, you can't get the type of an uninitialised variable.
Sounds like this is kind of a factory pattern implementation. Your best bet is to pass a reference of the Class to the method
method:
public function create(class:Class) : void
{
return new class();
}
calling code:
public var object:Sprite;
...
object = createObject(Sprite)