How can I use Mono.Cecil to call a generic method - il

I'm trying to import a method and its IL code like
callvirt instance !!0 [UnityEngine]UnityEngine.GameObject::AddComponent<class RealMono>()
The RealMono is a MonoBehavior which I created .
I have no idea to get the generic method.

It works!!
using System.Reflection;
...
MemberInfo[] ms = typeof(GameObject).GetMember("AddComponent*", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance);
MethodInfo mm = null;
foreach(MemberInfo m in ms) {
if (((MethodInfo)m).IsGenericMethod) {
mm = (MethodInfo)m;
mm = mm.MakeGenericMethod(mm);
break;
}
}
il.InsertBefore(method.Body.Instructions[0], il.Create(OpCodes.Callvirt, assembly.MainModule.Import(mm)));

Related

How to identify a component is spark or mx

I need to check the component is spark or mx I have tried with checking is IVisualElementContainer
But both spark and mx component are fall into IVisualElementContainer my code sample are as follows
displayMessage(vidbox, 'videbox removed');
public function displayMessage(messageParent:*, message:String, fontSize:String = "30"):void {
messageLabel.text = message;
if(messageParent is IVisualElementContainer)
messageParent.addElement(messageLabel);
else
messageParent.addChild(messageLabel);
}
any helps are highly appreciated
There is getQualifiedClassName which returns "the fully qualified class name of an object.", so then you can check if class name starts with "mx." or "spark.".
Code sample:
var fullClassName:String = getQualifiedClassName(messageParent).toLowerCase();
if(fullClassName.indexOf("spark.") == 0)
{
//spark comp
messageParent.addElement(messageLabel);
}
else if(fullClassName.indexOf("mx.") == 0)
{
// mx comp
messageParent.addChild(messageLabel);
}
else
{
// other
}

Antlr4 StringTemplate not compatible with Json.net dynamic items

I would like to read a dynamic object from a json file and then use this in a stringTemplate.
The following code works.
dynamic data = new { bcName = "Lixam B.V", periodName = "July 2013" };
var engine = new Template("<m.bcName> <m.periodName>");
engine.Add("m", data);
engine.Render().Should().Be("Lixam B.V July 2013");
The following code fails
var json = "{bcName : 'Lixam B.V', periodName : 'July 2013'}";
dynamic data = JsonConvert.DeserializeObject(json);
string name = (data.bcName);
name.Should().Be("Lixam B.V"); // this passes
var engine = new Template("<m.bcName> <m.periodName>");
engine.Add("m", data);
engine.Render().Should().Be("Lixam B.V July 2013"); //fails
Is there another way to configure JsonConverter to be compatible with StringTemplate
You need to create an IModelAdaptor for whatever the compiled type representing dynamic is, and register it using TemplateGroup.RegisterModelAdaptor.
Inspired on Mr. Harwell's answer, I've implemented an IModelAdaptor that enable the usage of Newtonsoft.Json parsed objects.
Here it goes:
internal class JTokenModelAdaptor : Antlr4.StringTemplate.IModelAdaptor
{
public object GetProperty(
Antlr4.StringTemplate.Interpreter interpreter,
Antlr4.StringTemplate.TemplateFrame frame,
object obj,
object property,
string propertyName)
{
var token = (obj as JToken)?.SelectToken(propertyName);
if (token == null)
return null;
if (token is JValue)
{
var jval = token as JValue;
return jval.Value;
}
return token;
}
}
You just need to register the adaptor in your template group, like this:
template.Group.RegisterModelAdaptor(typeof(JToken), new JTokenModelAdaptor());

How to insert a Path in between an existing Path

I am working on an implementation to generate alternate Paths using via node method.
While checking for local optimality I do the following
forwardEdge = bestWeightMapFrom.get(viaNode);
reverseEdge = bestWeightMapTo.get(viaNode);
double unpackedUntilDistance = 0;
while(forwardEdge.edge != -1) {
double parentDist = forwardEdge.parent != null ? forwardEdge.parent.distance : 0;
double dist = forwardEdge.distance - parentDist;
if(unpackedUntilDistance + dist >= T_THRESHOLD) {
EdgeSkipIterState edgeState = (EdgeSkipIterState) graph.getEdgeProps(forwardEdge.edge, forwardEdge.adjNode);
unpackStack.add(new EdgePair(edgeState, false));
sV = forwardEdge.adjNode;
forwardEdge = forwardEdge.parent;
break;
}
else {
unpackedUntilDistance += dist;
forwardEdge = forwardEdge.parent;
sV = forwardEdge.adjNode;
}
}
int oldSV = forwardEdge.adjNode;
EdgeEntry oldForwardEdge = forwardEdge;
I unpack the edge in the stack to further narrow down sV.
I get vT and oldVt in a similar fashion by traversing reverseEdge.
if I determine that the path from sV and vT is <= length of unpacked edges I accept this via node and construct the alternatePath as follows.
PathBidirRef p = (PathBidirRef) algo.calcPath(oldSV, oldVT);
Path4CHAlt p1 = new Path4CHAlt(graph, flagEncoder);
p1.setSwitchToFrom(false);
p1.setEdgeEntry(oldForwardEdge);
p1.segmentEdgeEntry = p.edgeEntry;
double weight = oldForwardEdge.weight + oldReverseEdge.weight + p.edgeEntry.weight + p.edgeTo.weight;
p1.setWeight(weight);
p1.edgeTo = oldReverseEdge;
p1.segmentEdgeTo = p.edgeTo;
Path p2 = p1.extract();
Path4CHAlt is
public class Path4CHAlt extends Path4CH {
private boolean switchWrapper = false;
public EdgeEntry segmentEdgeTo;
public EdgeEntry segmentEdgeEntry;
public Path4CHAlt( Graph g, FlagEncoder encoder )
{
super(g, encoder);
}
public Path4CHAlt setSwitchToFrom( boolean b )
{
switchWrapper = b;
return this;
}
#Override
public Path extract()
{
System.out.println("Path4CHAlt extract");
if (edgeEntry == null || edgeTo == null || segmentEdgeEntry == null || segmentEdgeTo == null)
return this;
if (switchWrapper)
{
EdgeEntry ee = edgeEntry;
edgeEntry = edgeTo;
edgeTo = ee;
ee = segmentEdgeEntry;
segmentEdgeEntry = segmentEdgeTo;
segmentEdgeTo = ee;
}
EdgeEntry currEdge = segmentEdgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
currEdge.parent = edgeEntry;
currEdge = edgeEntry;
while (EdgeIterator.Edge.isValid(currEdge.edge))
{
processEdge(currEdge.edge, currEdge.adjNode);
currEdge = currEdge.parent;
}
setFromNode(currEdge.adjNode);
reverseOrder();
currEdge = segmentEdgeTo;
int tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
currEdge.parent = edgeTo;
currEdge = edgeTo;
tmpEdge = currEdge.edge;
while (EdgeIterator.Edge.isValid(tmpEdge))
{
currEdge = currEdge.parent;
processEdge(tmpEdge, currEdge.adjNode);
tmpEdge = currEdge.edge;
}
setEndNode(currEdge.adjNode);
return setFound(true);
}
}
This is not working all the time. I get exceptions in Path4CH
java.lang.NullPointerException
at com.graphhopper.routing.ch.Path4CH.expandEdge(Path4CH.java:62)
at com.graphhopper.routing.ch.Path4CH.processEdge(Path4CH.java:56)
at com.graphhopper.routing.PathBidirRef.extract(PathBidirRef.java:95)
at com.graphhopper.routing.DijkstraBidirectionRef.extractPath(DijkstraBidirectionRef.java:99)
at com.graphhopper.routing.AbstractBidirAlgo.runAlgo(AbstractBidirAlgo.java:74)
at com.graphhopper.routing.AbstractBidirAlgo.calcPath(AbstractBidirAlgo.java:60)
In Path
java.lang.IllegalStateException: Edge 1506012 was empty when requested with node 1289685, array index:0, edges:318
at com.graphhopper.routing.Path.forEveryEdge(Path.java:253)
at com.graphhopper.routing.Path.calcInstructions(Path.java:349)
I dont know what I am doing wrong. I could really use some help with this.
Thanks.
I solved this issue.
Inside DijkstraBidirectionRef.calcPath I was trying to calculate shortest path from an arbitrary node to source node and vertex node.
The error used to occur because the original call to calcPath was operating on QueryGraph and inside I was creating a new Object of DijkstraBidirectionRef using LevelGraphStorage.
This was a problem because QueryGraph may create virtual nodes and edges for source and target nodes. Call to calcPath(node, virtualNode) operating on LevelGraphStorage would throw an exception.
The fix was to call algo.setGraph(queryGraph) after creating DijkstraBidirectionRef.

Explicit construction of entity type ### in query is not allowed

I use a Windows phone 8, MVVM + SQL Server CE 3.5 database
In folder model I have a declaration of table <TblCollections>
In folder ViewModel have this code for getting the collection.
public IEnumerable<TblCollections> GetTblCollections()
{
using (DbContext db = new DbContext(DbContext.ConnectionString))
{
var query = from collection in db.TblCollections
select new TblCollections
{
a = (string)collection.a,
b = (int)collection.b,
id = (int)collection.id,
};
IEnumerable<TblCollections> _TblCollections = query.ToList();
return _TblCollections;
}
}
I receive error on query.ToList();
Explicit construction of entity type "TblCollections" in query is not allowed
Why?
Do not specify class and Try this(Untested code):
IEnumerable<TblCollections> query = from collection in db.TblCollections
select new
{
a = (string)collection.a,
b = (int)collection.b,
id = (int)collection.id,
};

How to test if an object is a vector?

I want to test if an object is a vector, any vector, not only a vector of a single type.
I ran a test:
var v:Vector.<int> = new Vector.<int>();
v.push(3);
v.push(1);
v.push(2);
trace(v is Array); // false
trace(v is Vector); // false
trace(v is Vector.<int>); // true
trace(v is Vector.<*>); // false
It seems that the only thing that returns true is the one which specifies the vector type, but I want to test it for ANY type.
I will need a very efficient method to compare, because getQualifiedClassName is too slow.
My current approach is:
private static function isVector(obj:Object):Boolean {
return (getQualifiedClassName(obj).indexOf('__AS3__.vec::Vector') == 0);
}
But it is 2x slower than the is operator.
I need speed because it's for a object serialization class, and it needs to be very fast.
The problem is that Vector.<*> is a different class than that used for <Number>, <int>, or <uint>. The numeric primitives have special classes for better efficiency. String and Boolean are also primitives, but unlike the numeric primitives they are detected by <*>. As a result, you need only test for the generic Vector and the 3 numeric types.
This solution is over 2 times as fast as getQualifiedClassName in the worst case where the object is either not a Vector, or is a Vector.<uint>, and 5 times faster if the object is a non-primitive base type Vector, like Vector.<Object>:
return (obj is Vector.<*>
|| obj is Vector.<Number>
|| obj is Vector.<int>
|| obj is Vector.<uint>);
Here's a simplistic test:
var moo:Vector.<uint> = new Vector.<uint>();
var timer:Timer = new Timer();
var b:Boolean;
timer.startTimer();
for (var i:int = 0; i < 1000000; i++)
{
b = (moo is Vector.<*>
|| moo is Vector.<Number>
|| moo is Vector.<int>
|| moo is Vector.<uint>);
}
logger.info(" is timer: " + timer.endTimer());
timer.startTimer();
for (i = 0; i < 1000000; i++)
{
b = (flash.utils.getQualifiedClassName(moo).indexOf('__AS3__.vec::Vector') == 0);
}
logger.info("gqcn timer: " + timer.endTimer());
[LOG] com.tcg.test: is timer: 320
[LOG] com.tcg.test: gqcn timer: 756
Change moo to Vector.<Object>:
[LOG] com.tcg.test: is timer: 158
[LOG] com.tcg.test: gqcn timer: 743
Other methods are way too inefficient, so I'm still using my approach:
private static function isVector(obj:Object):Boolean {
return (getQualifiedClassName(obj).indexOf('__AS3__.vec::Vector') == 0);
}
trace(new Array().fixed);//undefined
trace(new Object().fixed);//undefined
trace(new Vector.<Sprite>().fixed);//false
trace(new Vector.<*>().fixed);// false
If you need serialization for any kind of object, you have to iterate over all possible types anyway, so you could use a sequential approach to find your vector type:
v is ... (simple data types)
v is ... (object types that are not collections)
v is Array
v is XMLList
v is ... (all other collection types you can think of)
if none of the above is true, it must be a vector
serialize objects in the vector. If you have more than one type, it's Vector.<*>, otherwise set the vector type according to the object type of the content items.
Use
(obj as Vector.<*>) is Vector.<*>
/// Return Class of any Target
static public function getClass( Target:* ):Class
{
return getDefinitionByName ( getQualifiedClassName( Target ) ) as Class ;
}
/// Check if object is type of Vector.< * >
static public function isVector( any:* ):Boolean
{
return String( getClass( any ) ).indexOf( "[class Vector.<" ) > -1;
}
/// Get Vector < Class >
static public function getVectorType( vector:* ):Class
{
var c:String = String( getClass( vector ) );
var s:int = c.indexOf( '<' ) + 1;
var e:int = c.indexOf( '>' );
return getDefinitionByName( c.substring( s, e ) ) as Class;
}
private function getIsVector(obj:Object):Boolean
{
return String(obj.constructor).indexOf('[class Vector.<*>]') == 0;
}