I have an assembly and some classes. What I'm trying to do is create an instance of a class and fill its properties in a generic way, something like:
public T FillObject(IDictionary<string,object> values)
{
/// CREATE INSTANCE
/// FILL THE PROPERTIES WITH THE VALUES
}
Reflection is the best way but its too slow, instead I've heard that Reflection.Emit is faster, so, is there a way to instantiate the class and fill its properties with Reflection.Emit?
Thanks in advance for any help.
On this occasion, I suggest HyperDescriptor; it is like reflection, but with IL generation thrown in the middle for performance; then, you just use regular component-model code:
object obj = Activator.CreateInstance(typeof(T));
var props = TypeDescriptor.GetProperties(typeof(T));
foreach(var pair in data)
{
props[pair.Key].SetValue(obj, pair.Value);
}
Edit; for a bit of a 2012 update, FastMember involves less abstraction:
var accessor = TypeAccessor.Create(typeof(T));
foreach(var pair in data)
{
accessor[obj, pair.Key] = pair.Value;
}
In addition to being more direct, FastMember will work with properly dynamic types, too - not just reflection.
If you're on .Net 4, you could use the new Expression types (that were added to support dynamic), to create an expression that assigns the properties, compile it to a delegate once, and call that repeatedly. The performance should be comparable with using Reflection.Emit.
class ObjectFiller<T>
{
private static Func<IDictionary<string, object>, T> FillerDelegate;
private static void Init()
{
var obj = Expression.Parameter(typeof(T), "obj");
var valuesDictionary = Expression.Parameter(typeof(IDictionary<string, object>), "values");
var create = Expression.Assign(
obj, Expression.Call(typeof(Activator), "CreateInstance", new[] { typeof(T) }));
var properties = typeof(T).GetProperties();
var setters = Expression.Block(properties.Select(p => CreateSetter(p, obj, valuesDictionary)));
var methodBody = Expression.Block(typeof(T), new[] { obj }, create, setters, obj);
var fillerExpression = Expression.Lambda<Func<IDictionary<string, object>, T>>(methodBody, valuesDictionary);
FillerDelegate = fillerExpression.Compile();
}
static Expression CreateSetter(PropertyInfo property, Expression obj, Expression valuesDictionary)
{
var indexer = Expression.MakeIndex(
valuesDictionary,
typeof(IDictionary<string, object>).GetProperty("Item", new[] { typeof(string) }),
new[] { Expression.Constant(property.Name) });
var setter = Expression.Assign(
Expression.Property(obj, property),
Expression.Convert(indexer, property.PropertyType));
var valuesContainsProperty = Expression.Call(
valuesDictionary, "ContainsKey", null, Expression.Constant(property.Name));
var condition = Expression.IfThen(valuesContainsProperty, setter);
return condition;
}
public T FillObject(IDictionary<string, object> values)
{
if (FillerDelegate == null)
Init();
return FillerDelegate(values);
}
}
You could do something very similar in .Net 3 too, using the Expression version of object initializers.
Dapper.NET does this. It's a Micro-ORM made to power stackoverflow. The whole ORM is just one C# file.
http://code.google.com/p/dapper-dot-net/source/browse/Dapper/SqlMapper.cs
The relevant code that creates the dynamic method is this:
var method = new DynamicMethod(commandType.Name + "_BindByName", null, new Type[] { typeof(IDbCommand), typeof(bool) });
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, commandType);
il.Emit(OpCodes.Ldarg_1);
il.EmitCall(OpCodes.Callvirt, setter, null);
il.Emit(OpCodes.Ret);
action = (Action<IDbCommand, bool>)method.CreateDelegate(typeof(Action<IDbCommand, bool>));
Also note that the IKVM.NET project provides their own implementation of IKVM.Reflection.Emit with a number of enhancements. If you're starting from scratch it might be good to look at that as an alternative.
Here is an example article on how to do mapping from a database IDatarecord.
Its easy to adapt this to most scenarios
Dynamic... But Fast: The Tale of Three Monkeys, A Wolf and the DynamicMethod and ILGenerator Classes
http://www.codeproject.com/KB/database/DynamicMethod_ILGenerator.aspx
Related
My use case can have thousands of instances of a class. One of the properties in that class is also of the same type as that of a class and this can go on and on.
So I basically have a collection of nested classes. Now if I were to search a property's value, what would my options be.
I am finding recurssion as one(Getting Nested Object Property Value Using Reflection) and an exhaustive use of GetNestedTypes(https://msdn.microsoft.com/en-us/library/493t6h7t(v=vs.110).aspx) as other.
I read that reflection is expensive, so my question is, are there other ways to search the property without using reflection concept?
You can use expression trees to create an abstract syntax tree that you can then compile to a dynamic method. This performs very closely to regularly written code (from my testing it is many times faster then reflection). The creation of the dynamic method is expensive, so create once, use many times.
static Func<object,object> CreateDelegate(PropertyInfo[] path)
{
var rootType = path.First().DeclaringType;
var param = Expression.Parameter(typeof(object));
Expression access = Expression.Convert(param, rootType);
foreach (var prop in path)
{
access = Expression.MakeMemberAccess(access, prop);
}
var lambda = Expression.Lambda<Func<object, object>>(
Expression.Convert(access, typeof(object)),
param
).Compile();
return lambda;
}
static void Main(string[] args)
{
var path = new[]
{
typeof(Root).GetProperty("Level1"),
typeof(Level1).GetProperty("Level2"),
typeof(Level2).GetProperty("Name")
};
var method = CreateDelegate(path);
var data = new Root { Level1 = new Level1 { Level2 = new Level2 { Name = "Test" } } };
var result = method(data);
}
References: Dynamic Methods, Expression Tree-Compile
I have the following class, for which usage is not important. What is important is method SetCacheItemSelector which takes one parameter, a select expression that projects Account entity to AccountCacheDTO:
public class AccountRepositoryCache : RepositoryCache<Account, AccountCacheDTO>
{
public AccountRepositoryCache()
{
SetCacheItemSelector(x => new AccountCacheDTO
{
Id = x.Id,
Login = x.Login
});
}
}
So signature for this method is:
public void SetCacheItemSelector(Expression<Func<TEntity, TCacheItem>> selector)
In this case, TEntity is Account class, and TCacheItem is AccountCacheDTO class.
Is there a way to use reflection to build select expression dynamically for all the properties that are matching for both Account class and AccountCacheDTO class?
Goal is to have method that would look like this:
public Expression<Func<TEntity, TCacheItem>> BuildSelector<TEntity, TCacheItem>()
{
... // implementation with reflection goes here
}
EDIT:
Here is final implementation (pretty much the same as the accepted answer):
public static Expression<Func<TSource, TTarget>> BuildSelector<TSource, TTarget>()
{
Type targetType = typeof(TTarget);
Type sourceType = typeof(TSource);
ParameterExpression parameterExpression = Expression.Parameter(sourceType, "source");
List<MemberBinding> bindings = new List<MemberBinding>();
foreach (PropertyInfo sourceProperty in sourceType.GetProperties().Where(x => x.CanRead))
{
PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name);
if (targetProperty != null && targetProperty.CanWrite && targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
MemberExpression propertyExpression = Expression.Property(parameterExpression, sourceProperty);
bindings.Add(Expression.Bind(targetProperty, propertyExpression));
}
}
NewExpression newExpression = Expression.New(targetType);
Expression initializer = Expression.MemberInit(newExpression, bindings);
return Expression.Lambda<Func<TSource, TTarget>>(initializer, parameterExpression);
}
I didn't test it, but you should be able to do something like: This is just to convey a general idea and you should be able to tweak it for your requirements.
public Expression<Func<TEntity, TCacheItem>> BuildSelector<TEntity, TCacheItem>(TEntity entity)
{
List<MemberBinding> memberBindings = new List<MemberBinding>();
MemberInitExpression body = null;
foreach (var entityPropertyInfo in typeof(TEntity).GetProperties())
{
foreach (var cachePropertyInfo in typeof(TCacheItem).GetProperties())
{
if (entityPropertyInfo.PropertyType == cachePropertyInfo.PropertyType && entityPropertyInfo.Name == cachePropertyInfo.Name)
{
var fieldExpressoin = Expression.Field(Expression.Constant(entity), entityPropertyInfo.Name);
memberBindings.Add(Expression.Bind(cachePropertyInfo, fieldExpressoin));
}
}
}
var parameterExpression = Expression.Parameter(typeof(TEntity), "x");
var newExpr = Expression.New(typeof(TCacheItem));
body = Expression.MemberInit(newExpr, memberBindings);
return Expression.Lambda<Func<TEntity, TCacheItem>>(body, parameterExpression);
}
Of course, the #Aravol's answer can make sense, but it is a little different which required in OP. Here is the solution which is more suitable to OP requirement.
public Expression<Func<TEntity, TCacheItem>> BuildSelector<TEntity, TCacheItem>()
{
Type type = typeof(TEntity);
Type typeDto = typeof(TCacheItem);
var ctor = Expression.New(typeDto);
ParameterExpression parameter = Expression.Parameter(type, "p");
var propertiesDto = typeDto.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var memberAssignments = propertiesDto.Select(p =>
{
PropertyInfo propertyInfo = type.GetProperty(p.Name, BindingFlags.Public | BindingFlags.Instance);
MemberExpression memberExpression = Expression.Property(parameter, propertyInfo);
return Expression.Bind(p, memberExpression);
});
var memberInit = Expression.MemberInit(ctor, memberAssignments);
return Expression.Lambda<Func<TEntity, TCacheItem>>(memberInit, parameter);
}
Your best bet is to get very comfortable with the System.Linq.Expressions namespace, which contains all of the methods you'll need to dynamically metacode your method calls and compile them into delegates. See especially Expression.Call and Lambda.Compile methods. Note that using Lambda.Compile, you can also have a true, compiled Delegate, instead of an expression tree (Expression) wrapping the call to your desired method. (NOTE: You can also forgo the Compile step if you really want that expression tree for later)
As for building your set, that's Assembly scanning, and is going to be a matter of iterating over all classes in your Assembly. I highly recommend you utilize, at the very least, a custom Attribute on your assembly or future assemblies to mark them for this scan, lest this process end up much more costly. At the most, you should consider using a custom Attribute to mark which properties you want scanned for this expression build.
the actual code to this tends to start with
AppDomain.CurrentDomain // Necessary to get all available Assemblies
.GetAssemblies() // Gets all the assemblies currently loaded in memory that this code can work with
.AsParallel() // Highly recommended to make the attribute-checking steps run asynchronously
// Also gives you a handy .ForAll Method at the end
// TODO: .Where Assembly contains Attribute
.SelectMany(assembly => assembly.GetTypes())
// TODO: .Where Type contains Attribute
.SelectMany(type => type.GetProperties)
// TODO: Make sure Property has the right data...
.Select(CompileFromProperty)
Where CompileFromProperty is a method taking PropertyInfo and returning the desired Expression.
Look into ToList() and ToDictionary after that, as you may need to break out of the parallelization once you start pushing values to your cache
Addendum: you also have .MakeGenericType on the Type class, which will allow you to specify Generic parameters from other Type variables, which will prove invaluable when building the Expressions. Don't forget about Contravariance when you define the generic types!
This is best explained using code. I have a generic class that has a method that returns an integer. Here is a simple version for the purposes of explaining...
public class Gen<T>
{
public int DoSomething(T instance)
{
// Real code does something more interesting!
return 1;
}
}
At runtime I use reflection to discover the type of something and then want to create an instance of my Gen class for that specific type. That is easy enough and done like this...
Type fieldType = // This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);
I now want to create an Expression that will take as a parameter an instance of the generic type and then calls the DoSomething method of that type. So I want the Expression to effectively perform this...
int answer = genericInstance.DoSomething(instance);
...except I do not have the 'instance' until some point later at runtime and the genericInstance is the generated type as can be seen above. My attempt at creating the Lambda for this is as follows...
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var x = Expression.Lambda<Func<genericType, fieldType, int>>
(Expression.Call(p1, mi, p2),
new[] { p1, p2 }).Compile();
...so that later on I can call it with something like this...
int answer = x(genericInstance, instance);
Of course, you cannot provide Func with instance parameters and so I have no idea how to parameterize the Lambda generation. Any ideas?
I think you would just use the Expression.Lambda that takes the delegate type as a type rather then as a generic, and create your Func on the fly like you are with Gen<>:
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var func = typeof (Func<,,>);
var genericFunc = func.MakeGenericType(genericType, fieldType, typeof(int));
var x = Expression.Lambda(genericFunc, Expression.Call(p1, mi, p2),
new[] { p1, p2 }).Compile();
This will return a Delegate rather than a strongly typed Func, but you can of course cast it if needed (and seemingly difficult if you don't know what you are casting to), or dynamically invoke it using DynamicInvoke on it.
int answer = (int) x.DynamicInvoke(genericInstance, instance);
EDIT:
A good idea that does indeed work. Unfortunately the reason I want to use a strongly typed compiled Lambda is performance. Using DynamicInvoke is prettty slow compared to a typed Lambda.
This seems to work without the need of a dynamic invoke.
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var func = typeof(Func<,,>);
var genericFunc = func.MakeGenericType(genericType, fieldType, typeof(int));
var x = Expression.Lambda(genericFunc, Expression.Call(p1, mi, p2), new[] { p1, p2 });
var invoke = Expression.Invoke(x, Expression.Constant(genericInstance), Expression.Constant(instance));
var answer = Expression.Lambda<Func<int>>(invoke).Compile()();
EDIT 2:
A greatly simplified version:
Type fieldType = ;// This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var value = Expression.Constant(instance, fieldType);
var lambda = Expression.Lambda<Func<int>>(Expression.Call(Expression.Constant(genericInstance), mi, value));
var answer = lambda.Compile()();
This answer only applies if you are using .NET 4.0.
If you make genericInstance dynamic instead of object, you can then call the DoSomething method on it directly, and the dynamic language runtime will take care of everything for you.
class Type1 {
public int DoSomething() { return 1; }
}
class Type2 {
public int DoSomething() { return 2; }
}
static void TestDynamic() {
dynamic t1 = Activator.CreateInstance(typeof(Type1));
int answer1 = t1.DoSomething(); // returns 1
dynamic t2 = Activator.CreateInstance(typeof(Type2));
int answer2 = t2.DoSomething(); // returns 2
}
If you need to keep this class structure (Gen<T>), then I don't see an easy way around the fact that you don't know the type T at compile time. If you want to call the delegate, you either have to know its full type at compile time, or you need to pass in the parameters as objects.
Using dynamic gets you to hide the complexity of getting the MethodInfo, etc., and gives you excellent performance. The one drawback vs. DynamicInvoke that I see is that I believe you get the initial overhead of resolving the dynamic call once for every call site. The bindings are cached so that they run very fast from the second time onwards if you call it on objects with the same type.
It's better to to accept an object and use convert to a known type.
Here is an example, how to build access to a property by name on unknown depth:
var model = new { A = new { B = 10L } };
string prop = "A.B";
var parameter = Expression.Parameter(typeof(object));
Func<object, long> expr = (Func<object, long>) Expression.Lambda(prop.Split('.').Aggregate<string, Expression>(Expression.Convert(parameter, model.GetType()), Expression.Property), parameter).Compile();
expr(model).Dump();
It avoids extra costs of DynamicInvoke when type of delegate is unknown at compile time.
I'm using JB Evain's Mono.Cecil to perform some byte-code manipulation on compiled DLL's. Part of this project is to inject properties into TypeDefinitions, effectively turning compiled getters/setters into the C# Properties pattern using PropertyDefinitions. This part is working well.
However, I would like to add an indexer to the TypeDefinition but I cannot find any documentation or advice on how best to achieve this. The methods which will be used to process the index requests are already in place:
Object getObjectViaIndexer(String str);
void setObjectViaIndexer(String str, object obj);
All i need to do is add the metadata to convert these into indexers....
Any ideas / thoughts would be greatly apprecaited!
Indexers, metadata wise, are simple properties. Only the type is decorated with a special attribute to tell that the property is an indexer. Here's a sample implementation which adds a new Item property that is recognized as an indexer, and delegates to the existing methods.
TypeDefinition type = ...;
// public object get_Item (string str) { ... }
var get_item = new MethodDefinition ("get_Item", MethodAttributes.Public, module.TypeSystem.Object);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
type.Methods.Add (get_item);
var il = get_item.Body.GetILProcessor ();
il.Emit (...); // emit call to getObjectViaIndexer
// public void set_Item (string str, object obj) { ... }
var set_item = new MethodDefinition ("set_Item", MethodAttributes.Public, module.TypeSystem.Void);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
set_item.Parameters.Add (new ParameterDefinition ("obj", ParameterAttributes.None, module.TypeSystem.Object));
type.Methods.Add (set_item);
il = set_item.Body.GetILProcessor ();
il.Emit (...); // emit call to setObjectViaIndexer
// public object this [string str] { ... }
var item = new PropertyDefinition ("Item", PropertyAttributes.None, module.TypeSystem.Object) {
HasThis = true,
GetMethod = get_item,
SetMethod = set_item,
};
type.Properties.Add (item);
// [DefaultMemberAttribute("Item")]
var default_member = new CustomAttribute (module.Import (typeof (System.Reflection.DefaultMemberAttribute).GetConstructor (new [] { typeof (string) })));
default_member.ConstructorArguments.Add (new CustomAttributeArgument(module.TypeSystem.String, "Item"));
type.CustomAttributes.Add (default_member);
Of course you could also just create a property which points to the existing methods, as long as you have the proper attribute.
I'm writing a file generic block for my application and started with using Lambda expressions for managing my rule sets for block generation to avoid the pitfalls of magic strings, configuration hell etc.
Inside my mapping class I have lines similar to:
Map(x => x.Name).Length(20).PadLeft(true).PaddingChar("#");
This works fine and isn't where my question dwells, where I setup saving my information about the expression is in the Map method:
public override IPropertyMap Map(Expression<Func<T, object>> expression)
{
var propertyMap = new FixedLengthPropertyMap
{
//Length = 20,
//PaddingCharacter = " ",
PadLeft = false,
PropertyInfo = ReflectionHelper.GetProperty(expression)
};
_properties.Add(propertyMap);
return propertyMap;
}
_properties is just a List<IPropertyMap> that stores my info where my question from what is the best way to have a real object's data be read from the properties currently I came up with something similar to this:
var map = new AgentMap();
var agent = new Agent {Name = "Bob"};
string output = map.Write(agent);
public override string Write<T>(T agent)
{
var initial = _properties[0];
return initial.PropertyInfo.GetValue(agent, null) as string;
}
Is there a better way than using the GetValue method since earlier on I'm using an expression tree?
I don't see why you really need to use expression trees at all. Just make the Map method take a Func<T, object> and store that:
public override IPropertyMap Map(Func<T, string> fetcher)
{
var propertyMap = new FixedLengthPropertyMap
{
//Length = 20,
//PaddingCharacter = " ",
PadLeft = false,
Delegate = fetcher // Delegate is of type Delegate
};
_properties.Add(propertyMap);
return propertyMap;
}
Then:
public override string Write<T>(T agent)
{
var initial = _properties[0];
Func<T, string> fetcher = (Func<T, string>) initial.Delegate;
return fetcher(agent);
}
Is there any reason you particularly wanted to know the property and use an expression tree?
In part, it depends on what your scenario is. The "simple" answer is to just compile the expression and invoke it, but that has a potential performance impact if you are doing it in a tight loop (passing a delegate would be a lot quicker).
I'm not sure whether if would apply in this particular case (because of the agent), but to avoid doing too much expression compilation, you can look for simple scenarios and read the value directly from the expression tree; a little bit of PropertyInfo/FieldInfo is going to be quicker than compiling it...
For more, look at TryEvaluate here, and how it is used with Compile as a backup strategy (although you have the advantage of a known delegate type).