Underscores in MvvmCross data binding - mvvmcross

I'm using the fluent syntax and lambdas for data binding in MvvmCross. An example of this is:
var bindings = this.CreateBindingSet<MyTableCell, MyTableCellViewModel>();
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE);
bindings.Apply();
Whenever I try this with an underscore in a view model property I get an exception:
Cirrious.CrossCore.Exceptions.MvxException: Unexpected character _ at
position 3 in targetProperty text MY_TITLE
I believe the error message is a result of MvvmCross parsing the data binding, yet this seems to only make sense for people using string-based data binding, not the lambda expression syntax.
Unfortunately, I cannot change the view models so I'm looking for a workaround to allow underscores in the view models. Any ideas?

I'd guess this is a general problem in the MvvmCross parser - probably in
private void ParsePropertyName()
{
var propertyText = new StringBuilder();
while (!IsComplete && char.IsLetterOrDigit(CurrentChar))
{
propertyText.Append(CurrentChar);
MoveNext();
}
var text = propertyText.ToString();
CurrentTokens.Add(new MvxPropertyNamePropertyToken(text));
}
In https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Parse/PropertyPath/MvxSourcePropertyPathParser.cs#L80
Which probably needs to be fixed to something like:
while (!IsComplete &&
(char.IsLetterOrDigit(CurrentChar) || CurrentChar == '_')
There are workarounds you could do, but the easiest solution is probably to fix this and rebuild, rather than to try workarounds.
But if you do want to try workarounds....
Assuming this is static (non-changing) text and this is just a one-off for now, then one workaround might be to add a property to your cell called Hack and to then bind like:
bindings.Bind(this).For(v => v.Hack).To(vm => vm);
//...
private MyTableCellViewModel _hack;
public MyTableCellViewModel Hack
{
get { return _hack; }
set { _hack = value; if (_hack != null) titleLabel.Text = _hack.MY_VALUE; }
}
Another alternative (with the same assumptions) might be to use a value converter -
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE).WithConversion(new WorkaroundConverter(), null);
// ...
public class WorkaroundConverter : MvxValueConverter<MyTableCellViewModel, string>
{
protected override string Convert(MyTableCellViewModel vm, /*...*/)
{
if (vm == null) return null;
return vm.MY_TITLE;
}
}

Related

Skipping Lines of Code & Setting Variables inside Public Function within PHPUnit When Testing

I'm sure something like this has been asked before, but I've read several forums and have not come to a solution. I am using PHPUnit version 3.7.38, if that makes any difference.
I'm in PHPUnit testing a function.
public function someFunction()
{
$variable2 = Input::get('someValue');
if (strlen($variable2) == 0) {
return Redirect::to('/somepage')->with(
'notification',
array(
'type' => 'danger',
'text' => 'text.'
)
);
}
...More Code that needs to be tested
My problem is that everytime PHPUnit runs, $variable2 returns null because it can't get someValue. The code the returns and skips the rest of the function. I want to somehow skip over $variable2's declaration and assign it to a value that has a strlen() greater than zero, so the test covers the rest of the function. Is there a way to do this?
I have read the documentation on PHPUnit's site about ignoring codeblocks, but have not had any luck with that. Maybe I'm not implementing the
/**
* #codeCoverageIgnore
*/
properly or maybe that's not even what codeCoverageIgnore is meant for. I tried putting the #codeCoverage in the actual code I'm testing, but I don't think that would be right either seeing how I still want to test the if branch if it is true. I wouldn't think you would have to edit the code being tested in order to test it either.
#CodeCoverageIgnore
This is used to tell the code coverage calculations to skip the this section and not include it in the calculation of test coverage. Therefore, this module would not be included in the counts for covered/uncovered lines of the test.
However, you really want to handle the Input:: method and set it. The best way to do this is to refactor your code, to move the Input rountine out, to be supplied by dependency injection, which would then allow you to Mock the Input routine to set your text string, and allow your test to continue.
class ToTest
{
private $InputObject
public function __construct($Input = NULL)
{
if(! is_null($Input) )
{
if($Input instanceof Input) // The class that you were referencing Input::
{
$this->SetInput($Input);
}
}
}
public function SetInput(Input $Input)
{
$this->InputObject = $Input
}
public function someFunction()
{
$variable2 = $this->InputObject::get('someValue');
if (strlen($variable2) == 0) {
return Redirect::to('/somepage')->with(
'notification',
array(
'type' => 'danger',
'text' => 'text.'
)
);
}
...More Code that needs to be tested
}
}
Test:
class InputTest extends PHPUnit_Framework_TestCase
{
// Simple test for someFunctione to work Properly
// Could also use dataProvider to send different returnValues, and then check with Asserts.
public function testSomeFunction()
{
// Create a mock for the Your Input class,
// only mock the someFunction() method.
$MockInput = $this->getMock('YourInput', array('someFunction'));
// Set up the expectation for the someFunction() method
$MockInput->expects($this->any())
->method('get')
->will($this->returnValue('Test String'));
// Create Test Object - Pass our Mock as the Input
$TestClass = new ToTest($MockInput);
// Or
// $TestClass = new ToTest();
// $TestClass->SetInput($MockInput);
// Test someFunction
$this->assertEquals('Test String', $TestClass->someFunction());
}
}

Can a second parameter be passed to Controller constructors?

Castle Windsor passes the registered concrete type to Controller's constructors. A typical implementation (no pun intended) is:
private readonly IDepartmentRepository _deptsRepository;
public DepartmentsController(IDepartmentRepository deptsRepository)
{
if (deptsRepository == null)
{
throw new ArgumentNullException("deptsRepository");
}
_deptsRepository = deptsRepository;
}
I need to pass the ctor a second parameter, if possible, so that I can pass that val on to the Repository constructor (I know: tramp data alert, but I don't know if there's a straightforward way around it:
public DepartmentsController(IDepartmentRepository deptsRepository, int DBInstance)
{
if (deptsRepository == null)
{
throw new ArgumentNullException("deptsRepository");
}
_deptsRepository = deptsRepository(DBInstance);
}
REPOSITORY
public DepartmentRepository(int dbInst)
{
string connStr = string.Format("Phoo{0}Bar", dbInst);
using (var conn = new OleDbConnection(connStr))
{
using (var cmd = conn.CreateCommand())
{
. . .
Is it possible to tweak what Castle Windsor sends to the Controller constructor this way? If so, how?
AND/BUT: For this to be of any value (to me, anyway), I need to be able to get the int val (that will be passed to the Controller) from the URL the client sends. IOW, if the client asks the server for data via:
http://locohost:4242/Platypus/GetAll/1
I need to pass a "1" as the second argument to PlatypusController.
If the user asks the server for data via:
http://locohost:4242/Platypus/GetAll/42
I need to pass a "42" as the second argument to PlatypusController.
etc.
This is what I did to solve my Controller/Repository data context Dilemma:
0) Added a database context argument to the Controller's routing attribute. IOW, this:
[Route("api/HHSUsers/GetAll")]
...got changed to this:
[Route("api/HHSUsers/GetAll/{dbContext=03}")]
1) Passed that database context arg to the Repository. To wit, this:
return _hhsusersrepository.GetAll();
...got changed to this:
return _hhsusersrepository.GetAll(dbContext);
...so that the Controller method is now:
[Route("api/HHSUsers/GetAll/{dbContext=03}")]
public IEnumerable<HHSUsers> GetAllHHSUsersRecords(int dbContext)
{
return _hhsusersrepository.GetAll(dbContext);
}
2) Changed the corresponding method in the Repository interface from:
IEnumerable<HHSUsers> GetAll();
...to this:
IEnumerable<HHSUsers> GetAll(string dbContext);
3) Changed the Repository method from this:
public HHSUsersRepository()
{
// All the data is loaded here in the ctor
}
public IEnumerable<HHSUsers> GetAll()
{
return hhsusers;
}
....to this:
public IEnumerable<HHSUsers> GetAll(string dbContext)
{
LoadHHSUsers(dbContext);
return hhsusers;
}
private void LoadHHSUsers(int dbContext)
{
string connStr = string.Format("Foo{0}Bar", dbContext);
// The same as previously from this point on, except that this:
// using (var conn = new OleDbConnection(#"Foo Bar Phoo Bar etc"...
// becomes:
// using (var conn = new OleDbConnection(connStr))
4) Tack the dbcontext val to the end of the URL when calling the method, so that it is this:
http://localhost:28642/api/HHSUsers/GetAll/42
...instead of this:
http://localhost:28642/api/HHSUsers/GetAll
If the data context to use is "03" I can omit the dbcontext arg from the URL, as 03 is the default value I set when I appended "=03" to the Controller's "dbContext" routing attribute arg.
I know some fancy-pants propeller-heads will find fault with this for some reason (for one reason because of the tramp data going here and there and everywhere like a hobo on steroids), but my response is the same as that of an athlete who is getting trash-talked by an opposing player and yet whose team is winning: just point at the scoreboard. IOW, this works for me, so that's pretty much all I care about. Style points are for runway models and, again, fancy-pants propeller-heads (AKA Star-Bellied Sneeches (as opposed to us plain
cats with the unstarred bellies)); see "The perfect is the enemy of the good."
This simple way has that self-same benefit -- of being (relatively) simple to grok and, thus, modify/refactor as necessary. Inelegant? Sure, but so was Joe Kapp.

How to export data from LinqPAD as JSON?

I want to create a JSON file for use as part of a simple web prototyping exercise. LinqPAD is perfect for accessing the data from my DB in just the shape I need, however I cannot get it out as JSON very easily.
I don't really care what the schema is, because I can adapt my JavaScript to work with whatever is returned.
Is this possible?
A more fluent solution is to add the following methods to the "My Extensions" File in Linqpad:
public static String DumpJson<T>(this T obj)
{
return
obj
.ToJson()
.Dump();
}
public static String ToJson<T>(this T obj)
{
return
new System.Web.Script.Serialization.JavaScriptSerializer()
.Serialize(obj);
}
Then you can use them like this in any query you like:
Enumerable.Range(1, 10)
.Select(i =>
new
{
Index = i,
IndexTimesTen = i * 10,
})
.DumpJson();
I added "ToJson" separately so it can be used in with "Expessions".
This is not directly supported, and I have opened a feature request here. Vote for it if you would also find this useful.
A workaround for now is to do the following:
Set the language to C# Statement(s)
Add an assembly reference (press F4) to System.Web.Extensions.dll
In the same dialog, add a namespace import to System.Web.Script.Serialization
Use code like the following to dump out your query as JSON
new JavaScriptSerializer().Serialize(query).Dump();
There's a solution with Json.NET since it does indented formatting, and renders Json dates properly. Add Json.NET from NuGet, and refer to Newtonsoft.Json.dll to your “My Extensions” query and as well the following code :
public static object DumpJson(this object value, string description = null)
{
return GetJson(value).Dump(description);
}
private static object GetJson(object value)
{
object dump = value;
var strValue = value as string;
if (strValue != null)
{
var obj = JsonConvert.DeserializeObject(strValue);
dump = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented);
}
else
{
dump = JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.Indented);
}
return dump;
}
Use .DumpJson() as .Dump() to render the result. It's possible to override more .DumpJson() with different signatures if necessary.
As of version 4.47, LINQPad has the ability to export JSON built in. Combined with the new lprun.exe utility, it can also satisfy your needs.
http://www.linqpad.net/lprun.aspx

Interface function returning untyped value (*) while implementation return specific type?

Out of curiosity I was wondering if it was possible to have an interface definition returning untyped values, while its implementations return typed value ?
For example, having the following interface :
interfaceExample
{
function someExampleFunction():*
}
implemented the following way :
classA implements interfaceExample
{
public function someExampleFunction():Int{ ... }
}
classB implements interfaceExample
{
public function someExampleFunction():String{ ... }
}
( I've googled with no result, maybe I haven't been able to ask the right way )
I guess the answer is 'no it's not possible in any way, Interface aren't designed like that' -- so what could be a friendly way to achieve such a thing ?
You're right, this won't compile. This is because the compiler doesn't support overloading of the signature of methods from parent classes or interfaces.
If you think about it, it doesn't really make sense to override the return type when implementing an interface because the code consuming your interface API should not depend on the implementation (int or String return value).
The solution to use really depends on what you are trying to do in the end. In general, the return type should be the common denominator between the different types you could produce. This could also be another interface that describes what to expect from the return value.
While I'm not heavily familiar with interface definitions, I do know that I write a lot of functions that work with typed and untyped arguments and returns.
In the event that what you're describing is not possible, and depending on what you're doing, I would recommend writing a simple function that can convert an untyped variable into a typed variable. They're fairly simple. Then, you could call this function to handle whatever data comes in via the interface definition.
A rough example (untested):
function convertDataTo(type:String, input:*):*
{
var rI:int;
var rN:Number;
var rS:String;
var rB:Boolean;
switch(type)
{
case "int":
if(isNaN(int(input))
{
rI = 0;
}
else
{
rI = int(input);
}
break;
case "Number":
if(isNaN(Number(input))
{
rN = 0;
}
else
{
rN = Number(input);
}
break;
case "Boolean":
if(input == "true")
{
rB = true;
}
else if(input == "false")
{
rB = false;
}
else
{
rB = Boolean(input);
}
return rB;
break;
case "String":
rS = input.toString();
break;
default:
trace("Invalid data type!");
return 0;
break;
}
}
You can also rewrite this function to convert from String type to any other type, and have your interface definition always return strings. On the other end, you can have a similar function that converts all variables to strings that can be interpreted by this function.
By the way, I've had to use that kind of string interpretation in writing my own scripting language for use inside one of my larger projects.
Of course, I don't pretend this answers your question directly, but I wanted to throw out this contingency in case what you're looking for doesn't work.

AS3: Is it possible to create a variable to hold instance name?

I am trying to have a more dynamic function and would like to allow the functions instance name were it outputs the text to be changeable.
for example
function example_function(url,instance_name){
instance_name.text = url;
}
example_function('www.example.com','url_txt');
example_function('www.another.com','more_txt');
Is this possible?
Yes, just parse the string into square brackets next to the instance's owner. For example:
this[instance_name].text = url;
More info:
Take this object:
var obj:Object = {
property1: 10,
property2: "hello"
};
Its properties can be accessed either as you'd expect:
obj.property1;
obj.property2;
Or as mentioned above:
obj["property1"];
obj["property2"];
I suggest using a function like this one I've created to tighten your code up a bit:
function selectProperty(owner:*, property:String):*
{
if(owner.hasOwnProperty(property)) return owner[property];
else throw new Error(owner + " does not have a property \"" + property + "\".");
return null;
}
trace(selectProperty(stage, "x")); // 0
trace(selectProperty(stage, "test")); // error
It is definitely possible, but it's not really best practice to do it with Strings like that. Instead, you can pass in a reference to the variable you're trying to modify.
function example_function(url : String, instance : TextField) : void {
instance.text = url;
}
example_function("www.example.com", url_txt);
This gives you strong typing so you can tell at compile time if you're operating on a TextField or not. If you aren't, you'll get an error because the 'text' property doesn't exist. You'll be able to find and track down errors faster this way.
However, if you must do it with Strings, you can access any property on any object using a string key like:
var myInstance = this[instance_name]
So in your example, you could do:
function example_function(url : String, instance : TextField) : void {
this[instance_name].text = url;
}
example_function("www.example.com", "url_txt");