My first foray into writing an expression tree in c# is not going too well :). Here's the c# code I'm trying to duplicate
public static object Test<S, D>(S source, Func<D, object> selector )
where S : class
where D : class
{
D derived = source as D;
object retVal = null;
if( derived != null ) retVal = selector(derived);
return retVal;
}
Conceptually, this is intended to take an object and apply a selector to it to return a property of a derived class if the supplied object is of the derived class.
Here's what I've got so far:
public static object OrderByDerivedProperty<S>( S source, Type derivedType, string fieldName )
{
ParameterExpression parameter = Expression.Parameter(typeof(S), "source");
UnaryExpression typeAs = Expression.TypeAs(parameter, derivedType);
ConstantExpression nullConst = Expression.Constant(null);
BinaryExpression isNotNull = Expression.NotEqual(typeAs, nullConst);
ParameterExpression varDest = Expression.Variable(derivedType, "varDest");
ParameterExpression retVal = Expression.Variable(typeof(object), "retVal");
BlockExpression block = Expression.Block(
new[] { varDest, retVal },
Expression.Assign(varDest, typeAs),
Expression.Condition(
isNotNull,
Expression.Assign(retVal, Expression.Property(varDest, fieldName)),
Expression.Assign(retVal, nullConst)
),
retVal
);
LambdaExpression lambda = Expression.Lambda(block, new[] { parameter });
return lambda.Compile().DynamicInvoke(source);
}
I've used a somewhat different set of arguments here to simplify my expressions.
The code works when derivedType is, in fact, a Type derived from S. However, if it isn't -- when I'm expecting the code to return retVal = null -- it blows up at the following line:
Expression.Assign(retVal, Expression.Property(varDest, fieldName)),
complaining that fieldName is not a property of varDest. Which is correct in that case...but I was expecting the "if true" arm of the Condtional expression to not be evaluated if the test expression was false. That's clearly not the case.
What I don't know about expression trees would fill (more than) a book. But if someone can point out where I'm going off the rails I'd appreciate it.
Not sure if you ever got this answered but here's what you need
public static object OrderByDerivedProperty<TSource>(TSource source, Type derivedType, string propertyOrFieldName)
{
if (!derivedType.IsClass)
{
throw new Exception("Derived type must be a class.");
}
ParameterExpression sourceParameter = Expression.Parameter(typeof(object), "source");
ParameterExpression typeAsVariable = Expression.Variable(derivedType);
ParameterExpression returnVariable = Expression.Variable(typeof(object));
BlockExpression block = Expression.Block(
new[] { typeAsVariable,returnVariable },
Expression.Assign(
typeAsVariable,
Expression.TypeAs(
sourceParameter,
derivedType
)
),
Expression.Condition(
Expression.NotEqual(
typeAsVariable,
Expression.Constant(
null,
derivedType
)
),
Expression.Assign(
returnVariable,
Expression.Convert(
Expression.PropertyOrField(
typeAsVariable,
propertyOrFieldName
),
typeof(object)
)
),
Expression.Assign(
returnVariable,
Expression.Constant(
null,
typeof(object)
)
)
),
returnVariable
);
var lambda = Expression.Lambda<Func<object,object>>(block, new[] { sourceParameter });
return lambda.Compile().Invoke(source);
}
Related
// Hi everyone
i do this call in Action :
[HttpGet]
public virtual ActionResult JsonGetProvinces(int countryId)
{
//WebSiteContext WbContext = new WebSiteContext();
//UnitOfWork UnitofWork = new UnitOfWork(WbContext);
var provinces =
(
from province in unitofWork.ProvinceRepository.All
where province.CountryId == countryId
select new
{
Id = province.Id,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
}
).ToList();
return Json(provinces, JsonRequestBehavior.AllowGet);
}
something is wrong with my query :
var provinces =
(
from province in unitofWork.ProvinceRepository.All
where province.CountryId == countryId
select new
{
Id = province.Id,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
}
).ToList();
Particulary,
Name = province.GetType().GetProperty("Name_" + CultureManager.GetCurrentCultureShortName()).GetValue(province)
In BDD, there is Name_fr, Name_en columns
and i'm trying to take one dynamically... Is it possible ?
Of course, i can take both and choose dynamically the column in View but i would to know how do...
Thank you for your help
The short answer is you need to change your code a bit and using expression tree inside. Look at this question
EF can not translate function calls to SQL. Using expression trees can be comlicated see this question
Here is a sample with expression trees. The GetQuery2 is the same as GetQuery but with expression tree and a propertyname parameter.
public static IQueryable<Foo> GetQuery(BlogContext context)
{
var query = from x in context.BlogEntries
select new Foo
{
NameX = x.Name
};
return query;
}
public static IQueryable<Foo> GetQuery2(BlogContext context, string propertyName)
{
ConstructorInfo ci = typeof(Foo).GetConstructor(new Type[0]);
MethodInfo miFooGetName = typeof(Foo).GetMethod("set_NameX");
MethodInfo miBlogEntry = typeof(BlogEntry).GetMethod("get_" + propertyName);
ParameterExpression param = Expression.Parameter(typeof(BlogEntry), "x");
IQueryable<Foo> result = Queryable.Select<BlogEntry, Foo>(
context.BlogEntries,
Expression.Lambda<Func<BlogEntry, Foo>>(
Expression.MemberInit(
Expression.New(ci, new Expression[0]),
new MemberBinding[]{
Expression.Bind(miFooGetName,
Expression.Property(param,
miBlogEntry))}
),
param
)
);
return result;
}
It is easier the fetch all all language strings and write an additional Property Name that does the magic.
I'm trying to verify a method call using Moq, but I can't quite get the syntax right. Currently, I've got this as my verify:
repository.Verify(x => x.ExecuteNonQuery("fav_AddFavorites", new
{
fid = 123,
inputStr = "000456"
}), Times.Once());
The code compiles, but the test fails with the error:
Expected invocation on the mock once, but was 0 times:
x => x.ExecuteNonQuery("fav_AddFavorites", new <>f__AnonymousType0<Int32, String>(123, "000456"))
No setups configured.
Performed invocations:
IRepository.ExecuteNonQuery("fav_AddFavorites", { fid = 123, inputStr = 000456 })
How can I verify the method call and match the method parameters for an anonymous type?
UPDATE
To answer the questions:
I am trying to verify both that the method was called and that the parameters are correct.
The signature of the method I'm trying to verify is:
int ExecuteNonQuery(string query, object param = null);
The setup code is simply:
repository = new Mock<IRepository>();
UPDATE 2
It looks like this is a problem with Moq and how it handles anonymous types in .Net. The code posted by Paul Matovich runs fine, however, once the code and the test are in different assemblies the test fails.
This Passes
public class Class1
{
private Class2 _Class2;
public Class1(Class2 class2)
{
_Class2 = class2;
}
public void DoSomething(string s)
{
_Class2.ExecuteNonQuery(s, new { fid = 123, inputStr = "000456" });
}
}
public class Class2
{
public virtual void ExecuteNonQuery(string s, object o)
{
}
}
/// <summary>
///A test for ExecuteNonQuery
///</summary>
[TestMethod()]
public void ExecuteNonQueryTest()
{
string testString = "Hello";
var Class2Stub = new Mock<Class2>();
Class1 target = new Class1(Class2Stub.Object);
target.DoSomething(testString);
Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.Equals(new { fid = 123, inputStr = "000456" }))), Times.Once());
}
##Update##
That is strange, it doesn't work in different assemblies. Someone can give us the long definition about why the object.equals from different assemblies behaves differently, but for different assemblies, this will work, any variance in the object values will return a different hash code.
Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.GetHashCode() == (new { fid = 123, inputStr = "000456" }).GetHashCode())), Times.Once());
One option is to "verify" it in a Callback. Obviously this needs to be done at Setup time, e.g.:
aMock.Setup(x => x.Method(It.IsAny<object>())).Callback<object>(
(p1) =>
{
dynamic o = p1;
Assert.That(o.Name, Is.EqualTo("Bilbo"));
});
None of the answers are great when your test assembly is different than the system under test's assembly (really common). Here's my solution that uses JSON serialization and then strings comparison.
Test Helper Function:
using Newtonsoft.Json;
public static class VerifyHelper
{
public static bool AreEqualObjects(object expected, object actual)
{
var expectedJson = JsonConvert.SerializeObject(expected);
var actualJson = JsonConvert.SerializeObject(actual);
return expectedJson == actualJson;
}
}
Example System Under Test:
public void DoWork(string input)
{
var obj = new { Prop1 = input };
dependency.SomeDependencyFunction(obj);
}
Example Unit Test:
var expectedObject = new { Prop1 = "foo" };
sut.DoWork("foo");
dependency.Verify(x => x.SomeDependencyFunction(It.Is<object>(y => VerifyHelper.AreEqualObjects(expectedObject, y))), Times.Once());
This solution is really simple, and I think makes the unit test easier to understand as opposed to the other answers in this thread. However, because it using simple string comparison, the test's anonymous object has to be set up exactly the same as the system under the test's anonymous object. Ergo, let's say you only cared to verify the value of a single property, but your system under test sets additional properties on the anonymous object, your unit test will need to set all those other properties (and in the same exact order) for the helper function to return true.
I created a reusable method based on Pauls answer:
object ItIsAnonymousObject(object value)
{
return It.Is<object>(o => o.GetHashCode() == value.GetHashCode());
}
...
dependency.Verify(
x => x.SomeDependencyFunction(ItIsAnonymousObject(new { Prop1 = "foo" })),
Times.Once());
Also, this can be used for property name case-insensitive comparison:
protected object ItIsAnonymousObject(object value)
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
return It.Is<object>(o => JsonSerializer.Serialize(o, options) == JsonSerializer.Serialize(value, options));
}
I'm building/updating an EntityFramework EntityObject on runtime. I want to set the properties of the entity class, property names and values are coming from another source.
So I'm doing this;
public static EntityCollection<T> UpdateLocaleEntity<T>(EntityCollection<T> entityCollectionToUpdate, params ILocaleControl[] values) where T : EntityObject
{
foreach (var x in entityCollectionToUpdate)
{
Type t = typeof(T);
dynamic localeEntity = x;
string cultureCode = localeEntity.CultureCode;
for (int j = 0; j < values.Length; j++)
{
var value = values[j].GetLocaleValue(cultureCode);
t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);
}
}
return entityCollectionToUpdate;
}
So, how can I get rid of "t.GetProperty(values[j].EntityPropertyName).SetValue(localeEntity, value, null);" part, is there a dynamic way of doing this?
Something like;
dynamicCastedLocaleEntity.GetProperty(values[j].EntityPropertyName) = value;
Thanks.
Long answer coming up.
Reflection is great in many situations, horrible in some but in almost all cases it's slow.
There are at least 4 different ways to set a property in .NET without having to use reflection.
I thought I demonstrate one of them: Using compiled expression trees. Note that the expression building is rather expensive too so that's why it's very important to cache the delegate one builds with it in a dictionary (for instance):
Expression Trees was introduced in .NET35 and is used for many things. Here I use them to build a property setter expression and then compile it into a delegate.
The example demonstrates different timing for the different cases but here are my numbers:
Control case (hard coded): 0.02s
Reflection: 1.78s
Expression Tree: 0.06s
using System;
using System.Linq.Expressions;
namespace DifferentPropertSetterStrategies
{
class TestClass
{
public string XY
{
get;
set;
}
}
class DelegateFactory
{
public static Action<object, object> GenerateSetPropertyActionForControl(
)
{
return (inst, val) => ((TestClass) inst).XY = (string) val;
}
public static Action<object, object> GenerateSetPropertyActionWithReflection(
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
return (inst, val) => propertyInfo.SetValue (inst, val, null);
}
public static Action<object,object> GenerateSetPropertyActionWithLinqExpression (
Type type,
string property
)
{
var propertyInfo = type.GetProperty(property);
var propertyType = propertyInfo.PropertyType;
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var valueParameter = Expression.Parameter(typeof(object), "value");
var lambda = Expression.Lambda<Action<object, object>> (
Expression.Assign (
Expression.Property (Expression.Convert (instanceParameter, type), propertyInfo),
Expression.Convert(valueParameter, propertyType)),
instanceParameter,
valueParameter
);
return lambda.Compile();
}
}
static class Program
{
static void Time (
string tag,
object instance,
object value,
Action<object, object > action
)
{
// Cold run
action(instance, value);
var then = DateTime.Now;
const int Count = 2000000;
for (var iter = 0; iter < Count; ++iter)
{
action (instance, value);
}
var diff = DateTime.Now - then;
Console.WriteLine ("{0} {1} times - {2:0.00}s", tag, Count, diff.TotalSeconds);
}
static void Main(string[] args)
{
var instance = new TestClass ();
var instanceType = instance.GetType ();
const string TestProperty = "XY";
const string TestValue = "Test";
// Control case which just uses a hard coded delegate
Time(
"Control",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionForControl ()
);
Time(
"Reflection",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithReflection (instanceType, TestProperty)
);
Time(
"Expression Trees",
instance,
TestValue,
DelegateFactory.GenerateSetPropertyActionWithLinqExpression(instanceType, TestProperty)
);
Console.ReadKey();
}
}
}
For FuleSnabel's answer, you can speed it up a lot (sometimes twice as fast in my tests). In some tests, it was just as fast as the Control solution:
public static Action<Object,Object> GenerateSetPropertyActionWithLinqExpression2(Type type, String property) {
PropertyInfo pi = type.GetProperty(property,BindingFlags.Instance|BindingFlags.Public);
MethodInfo mi = pi.GetSetMethod();
Type propertyType = pi.PropertyType;
var instance = Expression.Parameter(typeof(Object), "instance");
var value = Expression.Parameter(typeof(Object), "value");
var instance2 = Expression.Convert(instance, type);
var value2 = Expression.Convert(value, pi.PropertyType);
var callExpr = Expression.Call(instance2, mi, value2);
return Expression.Lambda<Action<Object,Object>>(callExpr, instance, value).Compile();
}
possibly not with EntityObject, but if you've had an ExpandoObject than you can do
dynamic entity = new ExpandoObject();
(entity as IDictionary<String, Object>)[values[j].EntityPropertyName] = value
The open source framework ImpromptuInterface has methods to invoke based on a string using the DLR rather than reflection and runs faster than reflection too.
Impromptu.InvokeSet(localeEntity, values[j].EntityPropertyName,value);
I'm afraid not. Any use of a dynamic object is baked-in at compile time. Any call which could vary at run-time has to be done using reflection.
I'm quite new to flex/actionscript and I was wondering if there is an equivalent for php's (and other languages) FILE and LINE identifiers?
Basicly I want to do some custom error logging and would like to something like:
var mymessage:String = 'Oops, a hiccup occured at ' + __FILE__ + ', line: ' + __LINE__;
Where file and line would ofcourse be substituted for their values at compile time.
Is this possible?
It's not directly possible, but there's a fairly usable workaround for personal testing
var stackTrace:String = new Error().getStackTrace();
if (stackTrace) {
var mymessage:String = "Oops, a hiccup occurred " + stackTrace.split("\n")[1];
}
Adjust your abuse of getStackTrace to taste.
To add to Cory's answer to the above. First add:
-define=CONFIG::debugging,true
to your library's compiler settings (next to the "-locale en_US" in "Additional Compiler Arguments"). Then use this quickie library:
package ddd
{
public class Stack
{
protected static function str(val:*):String
{
if( val == null ) return "<null>";
if( val == undefined ) return "<undefined>";
return val.toString();
}
protected static var removeAt :RegExp = /^\s*at\s*/i;
protected static var matchFile:RegExp = /[(][)][\[][^:]*?:[0-9]+[\]]\s*$/i;
protected static var trimFile :RegExp = /[()\[\]\s]*/ig;
/* Must maintain number of stack levels, so that _stack can assume the 4th line of getStackTrace */
private static function _stack( msg:String="", ...params ):String
{
var s :String = new Error().getStackTrace();
var func:String = "??";
var file:String = "??";
var args:String = null;
if(s)
{
func = s.split("\n")[4];
func = func.replace( removeAt, "" );
var farr:Array = func.match( matchFile );
if( farr != null && farr.length > 0 ) file = farr[0].replace( trimFile, "" );
func = func.replace( matchFile, "" );
}
for each( var param:* in params )
{
args = ( args == null ? "" : args.concat(",") );
args = args.concat( str(param) );
}
return func + "(" + (args==null?"":args) + ")" + ( (msg!=null && msg!="") ? ":"+msg : "" ) + " at " + file;
}
/* Must maintain number of stack levels, so that _stack can assume the 4th line of getStackTrace */
public static function stack( msg:String="", ...params ):String
{
params.unshift( msg );
return _stack.apply( null, params );
}
/* Must maintain number of stack levels, so that _stack can assume the 4th line of getStackTrace */
public static function pstack( msg:String="", ...params ):void
{
CONFIG::debugging {
params.unshift(msg);
trace( _stack.apply( null, params ) );
}
}
}
}
And then you can just call:
Stack.pstack();
inside any function to print the stack location at that point, which looks like this:
package::classname/function() at /wherever/src/package/classname.mxml:999
Just remember to turn debugging to false before compiling for production, and all that will be left is an empty pstack call that does nothing - the guts will be conditional-compiled out.
IMHO the line or file doesn't add to much information in Flex. I usually output class and method name and as my methods tend to be short, it usually is clear where something occurred.
If you find yourself with methods that are hundreds of lines long, you should rethink your coding style.
Using org.as3commons.reflect I can look-up the class name, and instantiate a class at runtime. I also have (non-working) code which invokes a method. However, I really want to set a property value. I'm not sure if properties are realized as methods internally in Flex.
I have a Metadata class which stores 3 pieces of information: name, value, and type (all are strings). I want to be able to loop through an Array of Metadata objects and set the corresponding properties on the instantiated class.
package com.acme.reporting.builders
{
import com.acme.reporting.model.Metadata;
import mx.core.UIComponent;
import org.as3commons.reflect.ClassUtils;
import org.as3commons.reflect.MethodInvoker;
public class UIComponentBuilder implements IUIComponentBuilder
{
public function build(metadata:Array):UIComponent
{
var typeClass:Class = ClassUtils.forName(getTypeName(metadata));
var result:* = ClassUtils.newInstance(typeClass);
for each (var m:Metadata in metadata)
{
if (m.name == "type")
continue;
// Attempting to invoke as method,
// would really like the property though
var methodInvoker:MethodInvoker = new MethodInvoker();
methodInvoker.target = result;
methodInvoker.method = m.name;
methodInvoker.arguments = [m.value];
var returnValue:* = methodInvoker.invoke(); // Fails!
}
return result;
}
private static function getTypeName(metadata:Array):String
{
if (metadata == null || metadata.length == 0)
throw new ArgumentError("metadata is null or empty");
var typeName:String;
// Type is usually the first entry
if (metadata.length > 1 && metadata[0] != null && metadata[0].name == "type")
{
typeName = metadata[0].value;
}
else
{
var typeMetadata:Array = metadata.filter(
function(element:*, index:int, arr:Array):Boolean
{
return element.name == "type";
}
);
if (typeMetadata == null || typeMetadata.length != 1)
throw new ArgumentError("type entry not found in metadata");
typeName = typeMetadata[0].value;
}
if (typeName == null || typeName.length == 0)
throw new Error("typeName is null or blank");
return typeName;
}
}
}
Here's some usage code:
var metadata:Array = new Array();
metadata[0] = new Metadata("type", "mx.controls.Text", null);
metadata[1] = new Metadata("text", "Hello World!", null);
metadata[2] = new Metadata("x", "77", null);
metadata[3] = new Metadata("y", "593", null);
this.addChild(new UIComponentBuilder().build(metadata));
I realize that I have to declare a dummy variable of the type I was to instantiate, or use the -inculde compiler directive. An unfortunate drawback of Flex.
Also, right now there's code to account for typecasting the value to it's specified type.
Dynamic execution in AS3 is much simpler than in other languages. This code:
var methodInvoker:MethodInvoker = new MethodInvoker();
methodInvoker.target = result;
methodInvoker.method = m.name;
methodInvoker.arguments = [m.value];
var returnValue:* = methodInvoker.invoke(); // Fails!
can be simplified to this:
var returnValue:* = result[method](m.value);
EDIT:
Since it's a property, it would be done like this:
result[method] = m.value;
and there is no return value (well, you can call the getter again but it should just return m.value unless the setter/getter do something funky.