NativeScript extension methods - nativescript

Is it possible to extend existing class in native script? By extending I mean it in C# terminology, e.g. not inherit, but 'inject' method to existing class and call that method on instance of original class.
C# extension methods:
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
string s = "Hello Extension Methods";
int i = s.WordCount();

JavaScript allows you to change the prototype of any object; so you can do:
String.prototype.wordCount = function() {
var results = this.split(/\s/);
return results.length;
};
var x = "hi this is a test"
console.log("Number of words:", x.wordCount());
and it will output Number of words: 5.
You can also use Object.defineProperty to add properties (rather than functions) like so:
Object.defineProperty(String.prototype, "wordCount", {
get: function() {
var results = this.split(/\s/);
return results.length;
},
enumerable: true,
configurable: true
});
var x = "hi this is a test"
console.log("Number of words:", x.wordCount); // <-- Notice it is a property now, not a function

Related

Use common linq expression to avoid duplicate of entity to poco

How may I avoid to duplicate the code I use for mapping a database entity to a poco object?
Given this code:
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
}
}).AsQueryable();
}
Can I create a common linq expression to be re-used for both methods?
private IQueryable<DummyExtended> Find()
{
return (from dt in Entities.dummy_table
select new DummyExtended
{
Description = dt.table_1.table_2.description,
Dummy = ...???
}).AsQueryable();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return (from dt in Entities.dummy_table
select new DummyAlsoExtended
{
InnerHtml = dt.table_html.description,
Dummy = ....??
}).AsQueryable();
}
Example:
public static Expression<Func<dummy_table, Dummy>> EntityToPoco()
{
return d => new Dummy
{
Name = d.name,
Notes = d.notes,
HelpText = d.help_text
};
}
I can't quite get it right
....
Dummy = ExtensionClass.EntityToPoco()
So you have a dummy_table which is a Enumerable or Queryable sequence of objects. Let's assume that the sequence contains objects of class DummyTableElement.
You showed, that if you have a DummyTableElement you know how to convert it into a Dummy object. You want to reuse this function to create other objects like DummyExtended and DummyAlsoExtended. If you want to do this LINQ-alike, it is best to create extension functions for it:
static class DummyTableElementExtensions
{
public static Dummy ToDummy(this TableElement tableElement)
{
return new Dummy()
{
Name = tableElement.name,
Notes = tableElement.notes,
HelpText = tableElement.help_text
};
}
}
Once you have this, you can create similar functions to convert TableElements into DummyExtended and DummyAlsoExtended. They will be one-liners.
In the same extension class:
public static DummyExtended ToDummyExtended(this TableElement tableElement)
{
return new DummyExtended()
{
Description = tableElement.table_1.table_2.description,
Dummy = tableElement.ToDummy(),
};
}
public static DummyAlsoExtended ToDummyAlsoExtended(this TableElement tableElement)
{
return new DummyAlsoExtended
{
InnerHtml = tableElement.table_html.description,
Dummy = tableElement.ToDummy(),
};
}
And once you've got these, you can create extension functions to convert any IQueryable of TableElements:
public static IQueryable<DummyExtended> ToDummyExtended(
this IQueryable<TableElement> tableElements)
{
return tableElements
.Select(tableElement => tableelement.ToDummyExtended();
}
And a similar one-line function for DummyAlsoExtended.
Your Find function and FindAnother function will also be one-liners:
private IQueryable<DummyExtended> Find()
{
return dummy_table.ToDummyExtended();
}
private IQueryable<DummyAlsoExtended> FindAnother()
{
return dummy_table.ToDummyAlsoExtended();
}
I'm not sure why you wanted to use an expression in this. It doesn't seem that DummyExtended and DummyAlsoExtended are really similar, except that they both have a property Dummy.
One reason to parameterize the destination of your find function could be because you want to create anonymous classes in your Find function.
Again, once you've created ToDummy this will be a one-liner:
public static IQueryable<TResult> Find<TSource, TResult>(
this IQueryable<TSource> source,
Expression<Func<TSource, TResult>> resultSelector)
{
return source.Select(sourceElement => resultSelector(sourceElement);
}
Usage would be:
var X = dummy_Table.find(tableElement => new
{
foo = tableElement.CalculateFoo(),
bar = tableElement.CalculateBar(),
Dummy = tableElement.ToDummy(),
});

Apply Expression to object property in an Expression

I have a class with a property that is another class. I also have an Expression that maps each from other classes. How do I combine these two expressions into one expression without compiling the second Expression?
public class ClassA
{
public int SomeProperty { get; set; }
}
public class MappedClassA
{
public int MappedProperty { get; set; }
}
public class ClassB
{
public ClassA ClassAProperty { get; set; }
//snip...
}
public class MappedClassB
{
public MappedClassA MappedClassAProperty {get; set; }
}
public Expression<Func<ClassA, MappedClassA>> MapAExpression()
{
return a => new MappedClassA()
{
MappedProperty = a.SomeProperty
};
}
public Expression<Func<ClassB, MappedClassB>> MapBExpression()
{
return b => new MappedClassB()
{
//this should be done with the above expression
MappedClassAProperty = new MappedClassA()
{
MappedProperty = b.ClassAProperty.SomeProperty
}
};
}
This is possible without compiling the expression, but unfortunately not by using the simple lambda syntax to construct the expression.
You will have to create the expression tree "by hand", using expression methods like Expression.New() and Expression.Lambda().
This can get unreadable very quickly.
I tried assembling such an expression from memory below, but I lack practice; this is untested and there are possibly some bugs left.
public Expression<Func<ClassB, MappedClassB>> MapBExpression()
{
// generate a parameter of type ClassB.
// This is the parameter "b" our final lambda expression will accept.
var classBparam = Expression.Parameter(typeof(ClassB));
// access b.ClassAProperty; this is the property
// that we want to pass to the expression returned by MapAExpression()
var memberAccess = Expression.MakeMemberAccess(
classBparam,
typeof(ClassB).GetProperty("ClassAProperty"));
// invoke the lambda returned by MapAExpression()
//with the parameter b.ClassAProperty
var invocation = Expression.Invoke( MapAExpression(), memberAccess );
// create a new MappedClassB(), this is the object that will be returned
// by the expression we are currently creating
var ctor = Expression.New(typeof(MappedClassB));
// We want to assign something to the MappedClassB.MappedClassAProperty
var mappedClassAProperty =
typeof(MappedClassB).GetProperty("MappedClassAProperty");
// specifically, we want to assign the result of our MapAExpression(),
// when invoked with the parameter b.ClassAProperty
var mappedClassAAssignment =
Expression.Bind(mappedClassAProperty, invocation);
// Here we initialize the MappedClassAProperty,
// after creating the new MappedClassB.
// We initialize it with the assignment we just created
var memberInit = Expression.MemberInit(ctor, mappedClassAAssignment);
// finally, we construct the lambda
//that does all of the above, given a parameter of type ClassB
return Expression.Lambda<Func<ClassB, MappedClassB>>(memberInit, classBparam);
// this expression should now be equivalent to:
// return b => new MappedClassB()
// {
// MappedClassAProperty = new MappedClassA()
// {
// MappedProperty = b.ClassAProperty.SomeProperty
// }
// };
}

Cast ActionScript Object to Model

Is there any "automatic way" to casts an "Object" to a personalized Model Data Type in ActionScript 3?
Example:
package Example{
public class ExampleModel{
private _id:int;
private _randomAttribute:String;
public function ExampleModel(){
_id = 0;
_randomAttribute = "";
}
public function get id():int{
return _id;
}
public function set id(value:int):void{
_id = value;
}
public function get randomAttribute():String{
return _randomAttribute;
}
public function set randomAttribute(value:String):void{
_randomAttribute = value;
}
}
}
Then, in some part of my code, lets assume that I have something like this:
var _obj:Object = new Object();
_obj.id = 1;
obj.randomAttribute = "Hello World";
What I want would be something like:
var _exampleModel:ExampleModel = obj as ExampleModel;
But when I do this, the result on _exampleModel is null.
Any ideas?
Thanks.
EDIT:
According to Manish's answer, all I changed was the type of p var, which allows me to go through every kind of attribute:
public function fromObject(obj:Object):void{
//p:* includes every type of attributes.
for (var p:* in obj)
if (this.hasOwnProperty(p))
// Set private var directly.
this["_" + p] = obj[p];
}
Thanks Manish and rcdmk.
Manish's answer was enough for me and according to rcdmk's comment, the p:String isn't about the Type of data that the loop will go through, it is actually the name of the property, which makes sense because every name is a String.
The only way to automatically "cast" it is the following:
var model:Model = new Model();
var obj:Object = { id: "98123", name: "John Doe" };
for (var p:String in obj) {
if (model.hasOwnProperty(p))
model[p] = obj[p];
}
(Note: Model.id and Model.name are both type String in my example.)
A more proper way to do it, of course, is to pass the plain object to the Model object and let the Model object absorb it.
var model:Model = new Model(obj);
Or:
var model:Model = new Model();
model.fromObject(obj);
Where in the Model code you have:
public function Model(obj:Object = null)
{
if (obj != null)
fromObject(obj);
}
public function fromObject(obj:Object):void
{
for (var p:String in obj)
if (this.hasOwnProperty(p))
// Set private var directly.
this["_" + p] = obj[p];
}
This code can be in your abstract base Model class, and all your specific Model subclasses (e.g. ProductModel, CustomerModel, etc.) can use it automatically.
e.g.
public class ProductModel extends Model
{
public function ProductModel(obj:Object = null)
{
super(obj);
}
}

Attempting to perform complicated anonymous methods is failing

Update (Stupidity Fail)
So then, in all of my convoluted formula code, I neglected the fundamental principles of C#.
Methods may return a value.
static dynamic Construct<T>(T expression){
return expression;
}
Then just use that, instead of a variable ...
Method = Construct<Action<Context, string, int>>(
(context, key, change) =>
{
context.Saved[key] += change;
Console.WriteLine("{0}'s saved value of {1} was changed by {2}, resulting in {3}",
context.Name, key, change, context.Saved[key]);
}
)
I have a situation where I need to call upon methods that don't exist as compiled methods, but rather need to be able to accept an array of parameters and execute as an anonymous function. I thought I had it worked out, but I am running into an issue with the following..
public static IDictionary<string, Function> Expressions =
new Dictionary<string, Function> {
{
"Increase [X] by value of [Y]",
new Function {
Name = "Increase [X] by [Y]",
Parameters = 2,
Types = new List<Type>{
typeof(Param),
typeof(Param)
},
Method = (Expression<Func<Context, Param, Param, bool>>)
((context, x, y) => {
Console.WriteLine("test"); // this is where I need to do stuff...
})
}
}
};
I am being told that a Method name is expected on this. The problem is that Context will be passed in by the object that takes the function and runs its method, because the Context object cannot be pre-bound (it has to be late bound). So basically I package up the trailing 2 parameters (Param) and (Param) in this case and create a function to execute against them.
The database stores those parameters, and then invokes the method passing in the appropriate Context as the first parameter by using Compile().DynamicInvoke(object[] params).
Can anyone give me a hand here as to why I cannot put any kind of logic in between my { }?
UPDATE
Okay, since I've been told this example is unclear, here is an entire program running start to finish that illustrates what I am trying to accomplish.
public class Program {
static void Main(string[] args) {
// simple object stored in database.
var ctx = new Context {
Name = "Ciel",
Saved = new Dictionary<string, int> {
{ "First", 10 },
{ "Second", 20 }
}
};
// simple object stored in database.
var rule = new Rule {
Equations = new List<Equation> {
new Equation {
Parameters = new List<object>{
"First",
5
},
Name = "Increase [X] by value of [Y]"
}
}
};
// =======================================
// runtime environment!!!
// =======================================
var method = Evaluations.Expressions[rule.Equations[0].Name].Method;
var parameters = rule.Equations[0].Parameters;
// insert the specific context as the first parameter.
parameters.Insert(0, ctx);
method.DynamicInvoke(parameters.ToArray());
Console.ReadLine();
}
}
public class Function {
public string Name { get; set; }
public dynamic Method { get; set; }
}
public class Equation {
public string Name { get; set; }
// these objects will be simple enough to serialize.
public IList<object> Parameters { get; set; }
public Function Function { get; set; }
}
public class Context {
public string Name { get; set; }
// this is a crude example, but it serves the demonstration purposes.
public IDictionary<string, int> Saved { get; set; }
}
public class Rule {
// again, a crude example.
public IList<Equation> Equations { get; set; }
}
public static class Evaluations {
static Action<Context, string, int> expr = (context, key, change) =>
{
context.Saved[key] += change;
Console.WriteLine("{0}'s saved value of {1} was changed by {2}, resulting in {3}",
context.Name, key, change, context.Saved[key]);
};
public static IDictionary<string, Function> Expressions =
new Dictionary<string, Function> {
{
"Increase [X] by value of [Y]",
new Function {
Name = "Increase [X] by [Y]",
Method = expr
}
}
};
}
Four problems:
You're trying to create an expression tree from a lambda expression with a statement body (i.e. braces). C# doesn't allow this - you can only convert a statement lambda into a delegate, not an expression tree
Your lambda body doesn't return a Boolean value
You're trying to call an Expression<Func<Context, Param, Param, bool>> as if it were a method with a bool parameter. It's not at all clear what you're trying to do there.
Even if the third point were valid, I suspect you'd need more brackets.
If you refactor your code to make it a little more readable and manageable, you'll probably be well on your way to solving your problem. Rather than having one mammoth C# statement with a single semicolon, split it up into several lines. Something like this:
public static Dictionary<string, Function> Expressions = getExpressions();
private static Dictionary<string, Function> getExpressions()
{
var method = (Expression<Func<Context, Param, Param, bool>>)
((context, x, y) => {
Console.WriteLine("test"); // this is where I need to do stuff...
})(true);
var func = new Function()
{
Name = "Increase [X] by [Y]",
Parameters = 2,
Types = new List<Type>
{
typeof(Param),
typeof(Param)
},
Method = method
};
var dict = new Dictionary<string, Function>();
dict["Increase [X] by value of [Y]"] = func;
return dict;
}
Note: my syntax could be incorrect, but you get the general idea.

ASP.Net MVC 3 Custom HTML Helper - How to pass List<T> to helper using Object Literal Notation

I am trying to build a helper to create a simple single level menu. Upon calling the menu helper I would like to use object literal notation so that I can define the menu items in the view.
public class ActionsMenuHelper
{
public static string ActionsMenu(IList<ActionsMenuItem> menuItems)
{
string result = "";
return result;
}
}
I am just not sure on the syntax to call the menu.
I have tried something like.
#ActionsMenuHelper.ActionsMenu(List<ActionsMenuItem>{ new {Name = "Foo"},
new {Name = "Bar"}
});
I'm obviously lost on how to do this.
You're quite close. Try this:
#ActionsMenuHelper.ActionsMenu(new List<ActionsMenuItem> { new ActionsMenuItem { Name = "Foo" }, new ActionsMenuItem { Name = "Bar" }});
Can get a little messy if you have more than a couple items, though. I'd define the list ahead of time for readability:
#{
var menuItems = new List<ActionsMenuItem> {
new ActionsMenuItem { Name = "Foo" },
new ActionsMenuItem { Name = "Bar" },
new ActionsMenuItem { Name = "Etc" }
};
}
#ActionsMenuHelper.ActionsMenu(menuItems);
More information can be found here.

Resources