I saw an article that shows how I can Concatenate two Expression<Func<T, bool>> variables.
But is here some ways to do this also with Expression<Action<T>> ?
Here is what I have tried:
public static Expression<Action<T>> Add<T>(this Expression<Action<T>> left, Expression<Action<T>> right)
{
//var param = Expression.Parameter(typeof(T), "x");
var body = Expression.AndAssign(
Expression.Invoke(left),
Expression.Invoke(right)
);
var lambda = Expression.Lambda<Action<T>>(body);
return lambda;
}
Related
I want to determine where to optimize code in a LINQPad query. How can I do that?
Note that I'm not asking how to profile LINQ queries; just regular (C#) code in a LINQPad 'query' file (a regular LINQPad file).
I think the easiest is to write a Visual Studio console app. Barring that, I use a class I added to My Extensions - it is not terribly accurate in that it doesn't account for its own overhead well, but multiple loops through help:
using System.Runtime.CompilerServices;
public static class Profiler {
static int depth = 0;
static Dictionary<string, Stopwatch> SWs = new Dictionary<string, Stopwatch>();
static Dictionary<string, int> depths = new Dictionary<string, int>();
static Stack<string> names = new Stack<string>();
static List<string> nameOrder = new List<string>();
static Profiler() {
Init();
}
public static void Init() {
SWs.Clear();
names.Clear();
nameOrder.Clear();
depth = 0;
}
public static void Begin(string name = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0) {
name += $" ({Path.GetFileName(sourceFilePath)}: {memberName}#{sourceLineNumber})";
names.Push(name);
if (!SWs.ContainsKey(name)) {
SWs[name] = new Stopwatch();
depths[name] = depth;
nameOrder.Add(name);
}
SWs[name].Start();
++depth;
}
public static void End() {
var name = names.Pop();
SWs[name].Stop();
--depth;
}
public static void EndBegin(string name = "",
[CallerMemberName] string memberName = "",
[CallerFilePath] string sourceFilePath = "",
[CallerLineNumber] int sourceLineNumber = 0) {
End();
Begin(name, memberName, sourceFilePath, sourceLineNumber);
}
public static void Dump() {
nameOrder.Select((name, i) => new {
Key = (new String('\t', depths[name])) + name,
Value = SWs[name].Elapsed
}).Dump("Profile");
}
}
I have following code:
protocol Protocol_1 {
var prop_1: String { get set }
var prop_2: Int { get set }
}
protocol Protocol_2 {
var prop_3: Double { get set }
var prop_4: Bool { get set }
}
extension Protocol_1 {
mutating func set<T>(value: T, forKey key: String)
{
switch key {
case "prop_1":
if value is String {
prop_1 = value as! String
}
case "prop_2":
if value is Int {
prop_2 = value as! Int
}
default:
break
}
}
}
extension Protocol_2 {
mutating func set<T>(value: T, forKey key: String)
{
switch key {
case "prop_3":
if value is Double {
prop_3 = value as! Double
}
case "prop_4":
if value is Bool {
prop_4 = value as! Bool
}
default:
break
}
}
}
struct MyStruct : Protocol_1, Protocol_2 {
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
}
var myStruct = MyStruct(prop_1: "hello", prop_2: 0, prop_3: 3.5, prop_4: true)
myStruct.set(value: "bye", forKey: "prop_1")
Now the playground gives me an error because it is not clear what set function should be called. Playground execution failed: error: ProtocolsPlayground.playground:59:1: error: ambiguous use of 'set(value:forKey:)'
myStruct.set(value: "bye", forKey: "prop_1")
This is clear but how can I achieve such function extension or is there a work around? Especially if the Protocol_1 is not editable.
I don't know of any way to extend an existing function or another protocol's function using a protocol.
What I would suggest is that you separate the mechanism that assigns properties by name from the two protocols using a third protocol that does that specifically and separately.
Here's one way to approach this:
Define a class that will handle getting and setting properties based on a mapping between names (keys) and variable references:
class PropertyMapper
{
static var sharedGetter = PropertyMapperGet()
static var sharedSetter = PropertyMapperSet()
var value : Any = 0
var success = false
var key = ""
func map<T>(_ key:String, _ variable:inout T) {}
func clear()
{
value = 0
success = false
key = ""
}
}
class PropertyMapperGet:PropertyMapper
{
func get(forKey:String)
{
key = forKey
success = false
}
override func map<T>(_ key:String, _ variable:inout T)
{
if !success && self.key == key
{
value = variable
success = true
}
}
}
class PropertyMapperSet:PropertyMapper
{
override func map<T>(_ key:String, _ variable:inout T)
{
if !success && self.key == key,
let newValue = value as? T
{
variable = newValue
success = true
}
}
func set(value newValue:Any, forKey:String)
{
key = forKey
value = newValue
success = false
}
}
Then, you can define a protocol for all struct and classes that will have the ability to assign their properties by name (key):
protocol MappedProperties
{
mutating func mapProperties(_ :PropertyMapper)
}
extension MappedProperties
{
mutating func get(_ key:String) -> Any?
{
let mapper = PropertyMapper.sharedGetter
defer { mapper.clear() }
mapper.get(forKey:key)
mapProperties(mapper)
return mapper.success ? mapper.value : nil
}
#discardableResult
mutating func set(value:Any, forKey key:String) -> Bool
{
let mapper = PropertyMapper.sharedSetter
defer { mapper.clear() }
mapper.set(value:value, forKey:key)
mapProperties(mapper)
return mapper.success
}
}
Your protocols can require that the struct that adopt them offer the named assignments. (see farther down for making the property mapping part of your protocol)
protocol Protocol_1:MappedProperties
{
var prop_1: String { get set }
var prop_2: Int { get set }
}
protocol Protocol_2:MappedProperties
{
var prop_3: Double { get set }
var prop_4: Bool { get set }
}
Your struct will need to implement the property mapping in order to adopt your protocols. The key/variable mapping is performed in a centralized function for the whole struct and needs to provide keys for all the variables in both protocols.
struct MyStruct : Protocol_1, Protocol_2
{
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
mutating func mapProperties(_ mapper:PropertyMapper)
{
mapper.map("prop_1", &prop_1)
mapper.map("prop_2", &prop_2)
mapper.map("prop_3", &prop_3)
mapper.map("prop_4", &prop_4)
}
}
This allows the struct to assign properties by name (key):
var myStruct = MyStruct(prop_1: "hello", prop_2: 0, prop_3: 3.5, prop_4: true)
myStruct.set(value: "bye", forKey: "prop_1")
To refine this further and make the property mapping part of your protocols, you can add a mapping function to the protocol so that the structs that adopt it don't have to know the details of this mapping.
They will still need to implement the mapping protocol's function but they can simply use functions provided by your protocols to do the job.
For example( I only showed Protocol_1 but you can do it with both of them):
extension Protocol_1
{
mutating func mapProtocol_1(_ mapper:PropertyMapper)
{
mapper.map("prop_1", &prop_1)
mapper.map("prop_2", &prop_2)
}
}
With the function provided by the protocol, the struct doesn't need to know which properties are mapped. This should make maintenance of the structs and protocols less error prone and avoid duplications.
struct MyStruct : Protocol_1, Protocol_2
{
var prop_1: String
var prop_2: Int
var prop_3: Double
var prop_4: Bool
mutating func mapProperties(_ mapper:PropertyMapper)
{
mapProtocol_1(mapper)
mapper.map("prop_3", &prop_3)
mapper.map("prop_4", &prop_4)
}
}
I have two questions here
Is it possible to add dynamic lists values to field injection list input ?
Can I create a trigger for this so this can be initiated from any other input selection say a class selection will populate all fields
I was just looking into FieldInjection.js whether that can be extented for the same
Can someone please provide a hint or direction for this ?
Thanks.
For anyone interested in the answer, I was able to achieve the above goal by changing the set function of the Java Class select input as folllowing
few imports
var extensionElementsHelper = require('../../../../helper/ExtensionElementsHelper'),
elementHelper = require('../../../../helper/ElementHelper')
var CAMUNDA_FIELD_EXTENSION_ELEMENT = 'camunda:Field';
function getExtensionFields(bo) {
return bo && extensionElementsHelper.getExtensionElements(bo, CAMUNDA_FIELD_EXTENSION_ELEMENT) || [];
}
then changing the set function to create extension element and push the field values as :
set: function(element, values, node) {
var bo = getBusinessObject(element);
var type = getImplementationType(element);
var attr = getAttribute(type);
var prop = {}
var commands = [];
prop[attr] = values.delegate || '';
var extensionElements = getExtensionFields(bo);
//remove any extension elements existing before
extensionElements.forEach(function(ele){
commands.push(extensionElementsHelper.removeEntry(getBusinessObject(element), element, ele));
});
if(prop[attr] !== ""){
var extensionElements = elementHelper.createElement('bpmn:ExtensionElements', { values: [] }, bo, bpmnFactory);
commands.push(cmdHelper.updateBusinessObject(element, bo, { extensionElements: extensionElements }));
var arrProperties = ["private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varOne","private org.camunda.bpm.engine.delegate.Expression com.cfe.extensions.SampleJavaDelegate.varTwo"]
var newFieldElem = "";
arrProperties.forEach(function(prop){
var eachProp = {
name:"",
string:"",
expression:""
}
var type = prop.split(" ")[1].split(".").reverse()[0];
var val = prop.split(" ")[2].split(".").reverse()[0];
eachProp.name = val;
if( type == "String"){
eachProp.string = "${" + val +" }"
}else if( type == "Expression"){
eachProp.expression = "${" + val +" }"
}
newFieldElem = elementHelper.createElement(CAMUNDA_FIELD_EXTENSION_ELEMENT, eachProp, extensionElements, bpmnFactory);
commands.push(cmdHelper.addElementsTolist(element, extensionElements, 'values', [ newFieldElem ]));
});
}
commands.push(cmdHelper.updateBusinessObject(element, bo, prop));
return commands;
}
Cheers !.
I need to read objects and save them in array. I did that on c# but can't figure out how to do that on actionscript.
c# example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TestingWSDLLOad.ServiceReference2;
namespace TestingWSDLLOad
{
class Program
{
static void Main(string[] args)
{
ServiceReference2.Service1Client testas = new ServiceReference2.Service1Client();
SortedList<int, PlayListItem> playList = new SortedList<int, PlayListItem>();
int cc = 0;
foreach (var resultas in testas.GetPlayList(394570))
{
PlayListItem ss = new PlayListItem(resultas.Id, resultas.VideoId, resultas.Path);
playList.Add(cc, ss);
cc++;
}
Console.WriteLine(playList[0].Id);
Console.ReadKey();
}
}
public class PlayListItem
{
public int VideoId { get; private set; }
public string Path { get; private set; }
public int Id { get; private set; }
public PlayListItem(int id, int videoId, string path)
{
Id = id;
VideoId = videoId;
Path = path;
}
}
}
I know how to get a simple result from wsdl using actionscript, but don't know how to get objects with parameteres and save them.
Service has a method GetPlaylist(int value) which returns an array of objects (id, videoId, path). How to handle this and save them ?
Here is my as3:
package {
public class data extends CasparTemplate {
var flvControl:FLVPlayback;
var refreshTimer:Timer;
var videoList:Array;
var videoNew:Array;
var videoMaxIds:Array;
var videoNewMaxIds:Array;
var videoIndex:uint;
var videoIdFrom:uint;
var loopAtEnd:Boolean;
var _playListItems:Array;
var _playList:PlayListItem;
var gotNewPlaylist:Boolean;
var webService:WebService;
var serviceOperation:AbstractOperation;
public function data()
{
_playListItems = new Array();
flvControl = new FLVPlayback();
videoNew = new Array();
videoNewMaxIds = new Array();
videoIndex = 0;
videoIdFrom = videoMaxIds[videoIndex];
loopAtEnd = true;
gotNewPlaylist = false;
refreshTimer = new Timer(20000);
refreshTimer.addEventListener(TimerEvent.TIMER, getNewPlaylist);
refreshTimer.start();
flvControl.addEventListener(VideoEvent.COMPLETE, completeHandler);
flvControl.addEventListener(VideoEvent.STATE_CHANGE, vidState);
flvControl.setSize(720, 576);
flvControl.visible = true;
//addChild(flvControl);
var url:String = "http://xxx/yyy.svc?wsdl";
webService = new WebService();
webService.loadWSDL(url);
webService.addEventListener(LoadEvent.LOAD, BuildServiceRequest);
}
function BuildServiceRequest(evt:LoadEvent):void
{
webService.removeEventListener(LoadEvent.LOAD, BuildServiceRequest);
//serviceOperation.addEventListener(ResultEvent.RESULT, displayResult);
for (var resultas in webService.getOperation("GetPlaylist(394575)"))
{
trace(resultas.Id);
}
//serviceOperation = webService.getOperation("GetPlaylist");
//serviceOperation.arguments[{videoId: "394575"}];
}
private function displayResult(e:ResultEvent):void
{
trace("sss");
}
// Handle the video completion (load the next video)
function completeHandler(event:VideoEvent):void
{
if (gotNewPlaylist)
{
videoList = videoNew;
videoMaxIds = videoNewMaxIds;
videoNew = null;
videoNewMaxIds = null;
gotNewPlaylist = false;
videoIndex = 0;
} else
videoIndex++;
nextVideo();
}
private function vidState(e:VideoEvent):void {
var flvPlayer:FLVPlayback = e.currentTarget as FLVPlayback;
if (flvPlayer.state==VideoState.CONNECTION_ERROR) {
trace("FLVPlayer Connection Error! -> path : "+flvPlayer.source);
videoIndex++;
nextVideo();
} else if (flvPlayer.state==VideoState.DISCONNECTED) {
videoIndex++;
nextVideo();
}
}
function nextVideo():void
{
trace("Video List:"+videoList.toString());
if( videoIndex == videoList.length ){
if( loopAtEnd )
{
videoIndex = 0;
} else { return; }
}
flvControl.source = videoList[videoIndex];
if (videoIdFrom < videoMaxIds[videoIndex])
videoIdFrom = videoMaxIds[videoIndex];
trace(videoIdFrom);
}
}
}
internal class PlayListItem
{
private var _videoId:int;
private var _path:String;
private var _id:int;
public function get VideoId():int { return _videoId; }
public function get Path():String { return _path; }
public function get Id():int { return _id; }
public function set VideoId(setValue:int):void { _videoId = setValue };
public function set Path(setValue:String):void { _path = setValue };
public function set Id(setValue:int):void { _id = setValue };
public function PlayListItem(id:int, videoId:int, path:String)
{
_videoId = videoId;
_id = id;
_path = path;
}// end function
}
I think you were on the right track with your commented-out code. Be aware that the getOperation() will return an AbstractOperation, which in my mind is simply a pointer to the remote function. You can set arguments on the object, or simply pass the arguments when you call send(). I know some people have had issues with the argument property approach, so simply passing your arguments in the send function may be the smart way to go.
The following replace BuildServiceRequest and displayResult
private function BuildServiceRequest(evt:LoadEvent):void {
webService.removeEventListener(LoadEvent.LOAD, BuildServiceRequest);
serviceOperation.addEventListener(ResultEvent.RESULT, displayResult);
serviceOperation = webService.getOperation("GetPlaylist");
serviceOperation.send(394575);
}
private function displayResult(e:ResultEvent):void {
// Store the token as our array.
_playListItems = e.token;
var msg:String;
// Loop through the array
for each (var entry:Object in _playListItems) {
msg = "";
// For every key:value pair, compose a message to trace
for (var key:String in entry) {
msg += key + ":" + entry[key] + " ";
}
trace(msg);
}
}
Is it possible to use underscore's groupBy function with ember.js?
I have the following attempt which is obviously not working:
var activities = App.store.findMany(App.Activity, feed.mapProperty('id').uniq())
var grouped = _.groupBy(activities, function(activity){
return activity.get('dateLabel;')
});
I get the following error:
Object App.Activity has no method 'get'
The store is loaded with the correct data so findMany will not make a remote call.
The problem is that findMany returns a DS.ManyArray which is probably a lot different than what _.groupBy is looking for.
You could implement your own groupBy function tailored for ember-data DS-ManyArray objects and extend _ with it:
_.emberArrayGroupBy = function(emberArray, val) {
var result = {}, key, value, i, l = emberArray.get('length'),
iterator = _.isFunction(val) ? val : function(obj) { return obj.get(val); };
for (i = 0; i < l; i++) {
value = emberArray.objectAt(i);
key = iterator(value, i);
(result[key] || (result[key] = [])).push(value);
}
return result;
};
Now you can call
var grouped = _.emberArrayGroupBy(activities, function(activity) {
return activity.get('dateLabel');
});
or more simply
var grouped = _.emberArrayGroupBy(activities, 'dateLabel');
The function above is based on underscore's original groupBy() implementation, which looks very similar:
_.groupBy = function(obj, val) {
var result = {};
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
each(obj, function(value, index) {
var key = iterator(value, index);
(result[key] || (result[key] = [])).push(value);
});
return result;
};
Try this code:
var activities = App.store.findMany(App.Activity, feed.mapProperty('id').uniq())
var grouped = _.groupBy(activities, function(activity){
return activity.get('dateLabel;')
}).bind(this);
I did not run this code to test how it works but the idea is to 'bind' outer scope into inner closure function scope.
Hope this helps to get you some ideas...