Is it possible to map a route with MapRoute and specify a generic controller e.g
context.MapRoute(
"Dashboard_Edit", // Route name
"dashboard/edit/{*pagePath}",
new { controller = "Dashboard`1", action = "edit", pagePath = "home" }
);
It is unfortunately not allowed with the default controller factory. The type "Dashboard`1" is for an open generic type and cannot be constructed. In other words, with the default controller factory the only allowed values for "controller" are ones that can fit the following pseudo syntax:
IController c = new SomeControllerType();
The SomeControllerType must be valid (though without the "Controller" suffix or namespace), and it must have a parameterless constructor.
You could always write a custom controller factory that has more advanced functionality and understands how to construct generic types.
Related
I would like to know which property in the JSON model has changed when modified by a view.
For a test I took OpenUI5 walkthrough example and added the following lines in the application controller
oProductModel.attachPropertyChange( function(oEvent){
console.log("event: ", oEvent);
}, this);
When I change a property in the text input, the function in the attachPropertyChange is called but oEvent object is empty as I print it in console.
I know I could connect to text input change event, but I would like to use attachPropertyChange in case there would be multiple views of the same model.
As far as I understood, you'd like to avoid using the change event of the Input control because there is no information about which property in the model has changed. However, you can still get all the relevant information within the change handler via:
oControl.getBinding(/*controlPropertyName*/).getPath() to get the name of the bound property, or
oControl.getBindingContext(/*modelName*/).getPath(/*suffix*/) to get the path of the bound context. The getPath here awaits an optional suffix that will be appended to the context path with a "/" in between.
Combine those two APIs to get an absolute path in case the property binding was relative. E.g.:
onInputChange: function (event) {
const inputControl = event.getSource();
const property = inputControl.getBinding("value").getPath(); // "myProperty"
const absolutePath = inputControl.getBindingContext(/*modelName*/).getPath(property) // "/0/myProperty"
// ...
},
You can use change event for all input field in UI, and write event handling method in the controller. You will get the property as well as value in the oEvent of the event handling method easily. I hope you understood.
I am using fold method of form as follows
def regSubmit = Action { implicit request =>
userForm.bindFromRequest.fold({
formWithErrors=>BadRequest(views.html.Error("Registration failed")( formWithErrors.errors))
},
{
userData=>Ok(views.html.regconf("Registration Successful")(**//here I want to send a Form, not data from the form**))
})
How can I create Form from a tuple or single variable, a class or a case class?
userForm will (usually?) be defined as a val, so immutable. It holds the mapping (this field name into a variable in this position of this type, ...) When you use bindFromRequest.fold you are not changing userForm, you are using the mapping information in userForm to generate a new instance of your case class, say userData (or a version of the form with errors in it). Each time you execute that method, you will get a new instance of userData.
userForm.fill(userData) returns a new form instance, a populated instance of the form, so also does not change userForm itself.
I want to create specific Object according to the type argument.
Pseudo code looks like this.
sub new {
my $type = shift;
if($type eq "S1") {$interface = X->new(); }
if($type eq "S2") {$interface = Y->new(); }
etc...
return $interface;
}
Options might be:
Substitute "package" name with $type argument. Requires package name coordination with $type.
Use Hash{S1 => X} in the Master constructor to select Value according to $type passed. Requires Hash maintenance when adding new
Object types.
I don't like any of above. Looking trully polimorphic way to accomplish that.
Thank You,
k
Your best option would likely be to use a factory pattern. A factory method takes the parameters for creating an instance of your class, then decides which object to instantiate and return from that. This can also make dependency injection easier for testing.
You'd probably be looking at something like this (in Java-esque code), with an employee object:
public class EmployeeFactory
{
public static create(String type)
{
switch (type) {
case type1:
return new EmployeeTypeOne();
case type2:
return new EmployeeTypeTwo();
default:
throw new Exception("Unrecognized type");
}
}
}
Your employees would inherit from a common interface or abstract class. You can use the factory to handle constructor parameters as well if you prefer, just try to keep things fairly reasonable (don't pass a million parameters - the factory should internally handle complex objects)
See http://refactoring.com/catalog/replaceConstructorWithFactoryMethod.html for more information.
You might like Module::PluginFinder for that. Create all your specific types in a specific namespace and give them each some identifying (constant? sub?) that the main dispatcher will then use to identify which class handles a given type.
I would need to map classA fields to classB fields along with localization i.e ClassA field values needs to be converted to localized value before it mapped to classB field. Locale should be passed as an argument to mapper in order get the localized value. Is there any option to pass runtime argument to mapper along with Source and Target classes?
Thanks.
Yes, you can do this. Let's get this example from Dozer docs
BeanMappingBuilder builder = new BeanMappingBuilder() {
protected void configure() {
mapping(Bean.class, Bean.class,
TypeMappingOptions.oneWay(),
mapId("A"),
mapNull(true)
)
.exclude("excluded")
.fields("src", "dest",
copyByReference(),
collectionStrategy(true,
RelationshipType.NON_CUMULATIVE),
hintA(String.class),
hintB(Integer.class),
FieldsMappingOptions.oneWay(),
useMapId("A"),
customConverterId("id")
)
.fields("src", "dest",
customConverter("org.dozer.CustomConverter")
);
}
};
Here we can find an example of dynamically configuration definition. Take a look at this part
customConverter("org.dozer.CustomConverter")
Here you can define a custom converter using this method
FieldsMappingOption customConverter(final String type)
But it has another version
customConverter(final Class<? extends CustomConverter> type, final String parameter)
And that's your case. You can write smth like
customConverter(com.yourproject.TranslatorConverter.class, "en")
in your dynamic code base config to define a parameter for you converter. How to write an implementation of CustumConverter which apply a parameter - take a look here
I could use some really good links that explain Generics and how to use them. But I also have a very specific question, relater to working on a current project.
Given this class constructor:
public class SecuredDomainViewModel<TDomainContext, TEntity> : DomainViewModel<TDomainContext, TEntity>
where TDomainContext : DomainContext, new()
where TEntity : Entity, new()
public SecuredDomainViewModel(TDomainContext domainContext, ProtectedItem protectedItem)
: base(domainContext)
{
this.protectedItem = protectedItem;
}
And its creation this way:
DomainViewModel d;
d = new SecuredDomainViewModel<MyContext, MyEntityType>(this.context, selectedProtectedItem);
Assuming I have 20 different EntityTypes within MyContext, is there any easier way to call the constructor without a large switch statement?
Also, since d is DomainViewModel and I later need to access methods from SecuredDomainViewModel, it seems I need to do this:
if (((SecuredDomainViewModel<MyContext, MyEntityType>)d).CanEditEntity)
But again "MyEntityType" could actually be one of 20 diffent types. Is there anyway to write these types of statements where MyEntityType is returned from some sort of Reflection?
Additional Info for Clarification:
I will investigate ConstructorInfo, but I think I may have incorrectly described what I'm looking to do.
Assume I have the DomainViewModel, d in my original posting.
This may have been constructed via three possible ways:
d = new SecuredDomainViewModel<MyContext, Order>(this.context, selectedProtectedItem);
d = new SecuredDomainViewModel<MyContext, Invoice>(this.context, selectedProtectedItem);
d = new SecuredDomainViewModel<MyContext, Consumer>(this.context, selectedProtectedItem);
Later, I need to access methods on the SecuredDomainViewModel, which currently must be called this way:
ex: if (((SecuredDomainViewModel<MyContext, Order)d).CanEditEntity)
ex: if (((SecuredDomainViewModel<MyContext, Invoice)d).CanEditEntity)
ex: if (((SecuredDomainViewModel<MyContext, Consumer)d).CanEditEntity)
Assuming I have N+ entity types in this context, what I was hoping to be able to do is
something like this with one call:
ex: if (((SecuredDomainViewModel<MyContext, CurrentEntityType)d).CanEditEntity)
Where CurrentEntityType was some sort of function or other type of call that returned Order, Invoice or Consumer based on the current item entity type.
Is that possible?
You can create a non-generic interface that has the CanEditEntity property on it, make SecuredDomainViewModel inherit off that, then call the property through the interface...
Also, the new() constructor allows you to call a constructor on a generic type that has no arguments (so you can just write new TEntity()), but if you want to call a constructor that has parameters one handy trick I use is to pass it in as a delegate:
public void Method<T>(Func<string, bool, T> ctor) {
// ...
T newobj = ctor("foo", true);
// ...
}
//called later...
Method((s, b) => new MyClass(s, b));
I can't help on the links, and likely not on the type either.
Constructor
If you have the Type, you can get the constructor:
ConstructorInfo construtor = typeof(MyEntityType).GetConstructor(new object[]{TDomainContext, ProtectedItem});
Type
I'm not really sure what you're looking for, but I can only see something like
if (((SecuredDomainViewModel<MyContext, entityType>)d).CanEditEntity)
{
entityType=typeof(Orders)
}
being what you want.