Let's say I have an object of Type User that looks like this:
User {
Name = "Bob",
Email = "Bob#gmail.com",
Class = NULL
}
Can anyone think of a way to take that object and create an object like this:
User {
Name = "Bob",
Email = "Bob#gmail.com"
}
Using entirely generic code? Meaning, I don't want to hard code anything to do with the Type, or the Properties because this code would need to be applied to every Entity on my site. (the "User" type is an Entity by the way, so use that if it helps you code this better).
I'm just trying to come up with a solution to a problem I have and I BELIEVE that Stub Entities may fix the problem, but I need to do it without hard coding any Types or Properties.
Use reflection to achieve this:
public void CopyValues<TSource, TTarget>(TSource source, TTarget target)
{
var sourceProperties = typeof(TSource).GetProperties().Where(p => p.CanRead);
foreach (var property in sourceProperties)
{
var targetProperty = typeof(TTarget).GetProperty(property.Name);
if (targetProperty != null && targetProperty.CanWrite && targetProperty.PropertyType.IsAssignableFrom(property.PropertyType))
{
var value = property.GetValue(source, null);
targetProperty.SetValue(target, value, null);
}
}
}
Generics are not gonna help you for this case. There might be some option in the Entity Framework but i am not really known with that.
It would however be possible using Reflection. You could try something like this:
public static void CopyProperties(object a, object b)
{
if (a.GetType() != b.GetType())
throw new ArgumentException("Types of object a and b should be the same", "b")
foreach (PropertyInfo property in a.GetType().GetProperties())
{
if (!property.CanRead || !property.CanWrite || (property.GetIndexParameters().Length > 0))
continue;
property.SetValue(b, property.GetValue(a, null), null);
}
}
Keep in mind tough that this requires all the properties you want to copy to have both a public setter and getter. Also there is the difference between "deep copy" vs "shallow copy" wich means if sub-objects are also copied or only referenced. This example will only reference them so it would be a "shallow copy"
This looks like a problem for reflection rather than generics (although generics can be used as a sneaky way of caching the strategy for reflection). Unless I misread it, you want to create a new instance and copy most of the members... Which reflection is good at, albeit relatively slow. You can improve the speed by using meta-programming; on the first run (per-type) generate an optimised version, perhaps using DynamicMethod or Expression, and store a typed delegate from that. Then just use the delegate.
Related
I am trying to improve performance in the code below and kinda know how but not sure which is the best approach.
The first hit will take longer but subsequent hits should be quicker. Now, I could cache T (where T is a class) and then check the cache to see if "T" exists, if so - go ahead and get its related information (NamedArguments) and go through each of the NamedArguments and finally if the criteria matches, go ahead and set the value of the current property.
I just want to make it more efficient and performant. Any ideas?
var myProps = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Where(prop => Attribute.IsDefined(prop, typeof(MyCustomAttribute)) && prop.CanWrite && prop.GetSetMethod() != null);
foreach (var currentProperty in myProps)
{
foreach (var currentAttributeForProperty in currentProperty.GetCustomAttributesData())
{
foreach (var currentNamedArgument in currentAttributeForProperty.NamedArguments)
{
if (string.Equals(currentNamedArgument.MemberInfo.Name, "PropName", StringComparison.OrdinalIgnoreCase))
{
currentAttribParamValue = currentNamedArgument.TypedValue.Value == null ? null : currentNamedArgument.TypedValue.Value.ToString();
// read the reader for the currentAttribute value
if (reader.DoesFieldExist(currentAttribParamValue))
{
var dbRecordValue = reader[currentAttribParamValue] == DBNull.Value ? null : reader[currentAttribParamValue];
// set it in the property
currentProperty.SetValue(val, dbRecordValue, null);
}
break;
}
}
}
}
DynamicMethods or ExpressionTrees will be much* faster than reflection. You could build a cache of all property getter/setters for a type, and then cache that information in a Dictionary (or ConcurrentDictionary) with type as the key.
Expression Tree Basics
Dynamic Methods
Flow
Discover type information (e.g. on app startup).
Compile dynamic methods for each property (do all properties at once).
Store those methods in a metadata class (example follows).
Cache the metadata somewhere (even a static field is fine, as long as access is synchronized). Use the type as the key.
Get the metadata for the type when needed.
Find the appropriate getter/setter.
Invoke, passing the instance on which you wish to act.
// Metadata for a type
public sealed class TypeMetadata<T> {
// The compiled getters for the type; the property name is the key
public Dictionary<string, Func<T, object>> Getters {
get;
set;
}
// The compiled setters for the type; the property name is the key
public Dictionary<string, Action<T, object>> Setters {
get;
set;
}
}
// rough invocation flow
var type = typeof( T);
var metadata = _cache[type];
var propertyName = "MyProperty";
var setter = metadata[propertyName];
var instance = new T();
var value = 12345;
setter( instance, value );
Example Setter
Excerpted from Dynamic Method Implementation (good article on the subject).
I can't vouch that this exact code works, but I've written very similar code myself. If you aren't comfortable with IL, definitely consider an expression tree instead.
public static LateBoundPropertySet CreateSet(PropertyInfo property)
{
var method = new DynamicMethod("Set" + property.Name, null, new[] { typeof(object), typeof(object) }, true);
var gen = method.GetILGenerator();
var sourceType = property.DeclaringType;
var setter = property.GetSetMethod(true);
gen.Emit(OpCodes.Ldarg_0); // Load input to stack
gen.Emit(OpCodes.Castclass, sourceType); // Cast to source type
gen.Emit(OpCodes.Ldarg_1); // Load value to stack
gen.Emit(OpCodes.Unbox_Any, property.PropertyType); // Unbox the value to its proper value type
gen.Emit(OpCodes.Callvirt, setter); // Call the setter method
gen.Emit(OpCodes.Ret);
var result = (LateBoundPropertySet)method.CreateDelegate(typeof(LateBoundPropertySet));
return result;
}
*25-100x faster in my experience
Reflection is notoriously slow in loops, so some kind of caching would probably help. But to decide what to cache, you should measure. As the famous saying goes: "premature optimization is the root of all evil"; you should make sure that you really need to optimize and what exactly to optimize.
For a more concrete advice, attributes are attached at compile time, so you could cache a type and a list of its propertyInfos for example.
I also had similar problem once - reflection is extreemely slow.
I used caching, like you are planning and performance grow more than 10 times. It was never again be a bottleneck in performance.
I've created similar logic before where I've cached an 'execution plan' for each type encountered. It was definitely faster for subsequent runs but you would have to profile your scenario to see whether it's worth the extra code complexity and memory usage.
EDIT: Updated example to what I'm actually doing.
EDIT 2: The why:
My class "takes hold" of a property setter (or method, anonymous or not) and "controls" it for a period of time. The user could try and attach another instance of my class and attach that to a property that is already "controlled." I need a way to detect these conflicts reliably. I could forego the () => { property } method but that requires the user to wrap the target property in a method and, if he/she wants conflict detection, to pass in the object containing the property. Doing it that way introduces higher risk of bugs as they may type in the wrong object and the class wouldn't have any means to check for them.
I am unable to utilize the Lambda Compile() because I am targeting AOT in addition to JIT.
I have a method that takes an
Expression<Func<T>>
as an argument. The Expression always evaluates to a property with a setter of Type T.
private static TargetInfo GetTargetInfo<T>(Expression<Func<T>> _propertyExpression, out Action<T> _setter)
{
//Get Property info
var propInfo = ((MemberExpression)_propertyExpression.Body).Member as PropertyInfo;
if (propInfo == null)
throw new ArgumentException("_propertyExpression must be a property.");
var declType = propInfo.DeclaringType;
var methodInfo = propInfo.GetSetMethod(true) ?? declType.GetProperty(propInfo.Name).GetSetMethod(true);
if (methodInfo == null)
throw new Exception("Could not create setter from property '" + _propertyExpression + "'");
var isStaticProp = methodInfo.IsStatic;
//Get Target Object
object targetObject = null;
var memberExp = _propertyExpression.Body as MemberExpression;
var bodyExp = memberExp.Expression;
if (bodyExp != null)
// PROBLEM LINE BELOW - Can't use Compile() *********************************
targetObject = Expression.Lambda<Func<object>>(bodyExp).Compile()();
// PROBLEM LINE ABOVE *******************************************************
else if (isStaticProp)
targetObject = memberExp.Member.DeclaringType;
else
throw new Exception("Could not determine target object. Use Action<T> overload. (no conflict detection)");
//Cache setter of property
if (isStaticProp)
_setter = (Action<T>) Delegate.CreateDelegate(typeof (Action<T>), methodInfo);
else
_setter = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), targetObject, methodInfo);
return new TargetInfo(methodInfo, targetObject);
}
The expression (_propertyExpression) is always of a property. And the property always has a setter.
I need to extract the property's setter as Action (which I can do
no problem)
I also need the instance of the object containing this
property without using Compile() as it is not available on some of
the target platforms I am targeting.
The reason I need the instance is to determine whether or not another object instance of my class is currently utilizing that property SETTER on THAT object. (No Threading, just usage over a span of time) I store the object Instance and property setter info together as a key, if two keys that are equal that exist then there is a conflict and it is handled based on the user's configuration settings of my class.
I am able to get the object instance for simple expressions like:
() => MyProperty
or
() => MyObjectInst.PropertyFoo
or
() => MyStaticClass.PropertyFooBar
No Sweat!
But what if the user does this:
//Need instance of 'someObject' here.
() => SomeArray[idx].someObject.propertyA
or blow my top:
//Need instance of 'someField[4]' here
() => SomeStaticClass.somePropertyList[5].SomeDictionary[objKey].SomeProperty.someFieldArray[4].propertyB
AAAK!
I've been looking at this for a while and I BELIEVE that I need to traverse the tree BACK to the base object (ConstantExpression) then start evaluating back UP the tree using the info collected walking to the front. Given the examples above I decided that I need "bigger guns".
Is there an easier way to get the property's caller's instance other than completely walking the tree WITHOUT using Compile()? Please explain if so!
If not 1. If anyone could point me in the right direction on how to traverse the tree and handle stuff like the above. That would be great. I'm not finding a whole lot of info on traversing Expression Trees, expression types, etc. Even a reference to a recommended book specific to the subject would be helpful.
sigh Should I just give up and force the user to use simple expressions.
ie. Do not allow the user to type in lengthy property access lines.
Clarification:
The setter is being cached for use by a mechanism class "FOO" that will be setting this value an UNKNOWN range of values of type T over some defined period of time. The object instance is cached and used as a key to detect the case that another instance of FOO tries to attach and set values to the same property on that same object. The object instance is used to detect these conflicts and also to keep track of all of the "FOO"s attached to any particular object. The user can attach multiple "FOO"s to the same object, to different properties. In the case that the user attaches an instance of FOO to a property on an object that already has a FOO attached for that property, a conflict event occurs. FOO can be configured on how to handle when that happens.
Here's the problems with your suggested approaches:
Is there an easier way to get the property's caller's instance other
than completely walking the tree WITHOUT using Compile()? Please
explain if so!
Short answer, no. Expressions are meant to be compiled. Either into .NET Funcs/Actions or some other platform (LINQ-to-Entities essentially compiles them into SQL). If you don't want to compile it, you're probably using the wrong tool.
If not 1. If anyone could point me in the right direction on how to
traverse the tree and handle stuff like the above. That would be
great. I'm not finding a whole lot of info on traversing Expression
Trees, expression types, etc. Even a reference to a recommended book
specific to the subject would be helpful.
The best way to traverse an Expression tree is by inheriting from ExpressionVisitor. A good blog to start with would be Matt Warren's blog http://blogs.msdn.com/b/mattwar/, read the series on implementing IQueryable. But no, it's not easy.
One could (theoretically) inherit from ExpressionVisitor to walk down/up the chain to the original instance. But you would then have to walk back up/down the chain somehow, and the easiest way to do that would be by compiling the child Expressions. You could, theoretically, use Reflection to walk back, as your answer tries, but I hope you're distinctly getting the impression you have chosen the wrong tool if your No-Compiling stance is iron-clad.
sigh Should I just give up and force the user to use simple expressions.
You haven't outlined the benefits/drawbacks of this.
I have confirmed that the below works on for MONO -> iOS... At least with the basics and arrays. Haven't been able to get the Dictionary/List rolling. It seems AOT doesn't like MethodInfo.Invoke.
EDIT:
I found this answer on MSDN:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/af305a45-36e4-4607-9190-f1b33a0bea57/get-class-instance-from-lambda-expression
It traverses the Expression tree, evaluating each part of the tree as necessary and finally returns the containing object of the property specified.
Put in this (along with adding the method code below in):
targetObject = GetContainer(_propertyExpression);
instead of this:
targetObject = Expression.Lambda<Func<object>>(bodyExp).Compile()();
in the code above.
I have yet to do full testing on it on other platforms and I'm sure I'll run into other cases where I need to add more cases but this might be enough to help someone else and enough to keep me going and I'll try and keep this updated as I run into more:
public static object GetContainer<T>(Expression<Func<T>> propertyLambdaExpression)
{
return Evaluate((propertyLambdaExpression.Body as MemberExpression).Expression);
}
public static object Evaluate(Expression e)
{
switch (e.NodeType)
{
case ExpressionType.Constant:
return (e as ConstantExpression).Value;
case ExpressionType.MemberAccess:
{
var propertyExpression = e as MemberExpression;
var field = propertyExpression.Member as FieldInfo;
var property = propertyExpression.Member as PropertyInfo;
var container = propertyExpression.Expression == null ? null : Evaluate(propertyExpression.Expression);
if (field != null)
return field.GetValue(container);
else if (property != null)
return property.GetValue(container, null);
else
return null;
}
case ExpressionType.ArrayIndex: //Arrays
{
var arrayIndex = e as BinaryExpression;
var idx = (int)Evaluate(arrayIndex.Right);
var array = (object[])Evaluate(arrayIndex.Left);
return array[idx];
}
case ExpressionType.Call: //Generic Lists and Dictionaries
{
var call = e as MethodCallExpression;
var callingObj = Evaluate(call.Object);
object[] args = new object[call.Arguments.Count];
for (var idx = 0; idx < call.Arguments.Count; ++idx)
args[idx] = Evaluate(call.Arguments[idx]);
return call.Method.Invoke(callingObj, args);
}
default:
return null;
}
}
I am trying to improve performance in the code below and kinda know how but not sure which is the best approach.
The first hit will take longer but subsequent hits should be quicker. Now, I could cache T (where T is a class) and then check the cache to see if "T" exists, if so - go ahead and get its related information (NamedArguments) and go through each of the NamedArguments and finally if the criteria matches, go ahead and set the value of the current property.
I just want to make it more efficient and performant. Any ideas?
var myProps = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static).Where(prop => Attribute.IsDefined(prop, typeof(MyCustomAttribute)) && prop.CanWrite && prop.GetSetMethod() != null);
foreach (var currentProperty in myProps)
{
foreach (var currentAttributeForProperty in currentProperty.GetCustomAttributesData())
{
foreach (var currentNamedArgument in currentAttributeForProperty.NamedArguments)
{
if (string.Equals(currentNamedArgument.MemberInfo.Name, "PropName", StringComparison.OrdinalIgnoreCase))
{
currentAttribParamValue = currentNamedArgument.TypedValue.Value == null ? null : currentNamedArgument.TypedValue.Value.ToString();
// read the reader for the currentAttribute value
if (reader.DoesFieldExist(currentAttribParamValue))
{
var dbRecordValue = reader[currentAttribParamValue] == DBNull.Value ? null : reader[currentAttribParamValue];
// set it in the property
currentProperty.SetValue(val, dbRecordValue, null);
}
break;
}
}
}
}
DynamicMethods or ExpressionTrees will be much* faster than reflection. You could build a cache of all property getter/setters for a type, and then cache that information in a Dictionary (or ConcurrentDictionary) with type as the key.
Expression Tree Basics
Dynamic Methods
Flow
Discover type information (e.g. on app startup).
Compile dynamic methods for each property (do all properties at once).
Store those methods in a metadata class (example follows).
Cache the metadata somewhere (even a static field is fine, as long as access is synchronized). Use the type as the key.
Get the metadata for the type when needed.
Find the appropriate getter/setter.
Invoke, passing the instance on which you wish to act.
// Metadata for a type
public sealed class TypeMetadata<T> {
// The compiled getters for the type; the property name is the key
public Dictionary<string, Func<T, object>> Getters {
get;
set;
}
// The compiled setters for the type; the property name is the key
public Dictionary<string, Action<T, object>> Setters {
get;
set;
}
}
// rough invocation flow
var type = typeof( T);
var metadata = _cache[type];
var propertyName = "MyProperty";
var setter = metadata[propertyName];
var instance = new T();
var value = 12345;
setter( instance, value );
Example Setter
Excerpted from Dynamic Method Implementation (good article on the subject).
I can't vouch that this exact code works, but I've written very similar code myself. If you aren't comfortable with IL, definitely consider an expression tree instead.
public static LateBoundPropertySet CreateSet(PropertyInfo property)
{
var method = new DynamicMethod("Set" + property.Name, null, new[] { typeof(object), typeof(object) }, true);
var gen = method.GetILGenerator();
var sourceType = property.DeclaringType;
var setter = property.GetSetMethod(true);
gen.Emit(OpCodes.Ldarg_0); // Load input to stack
gen.Emit(OpCodes.Castclass, sourceType); // Cast to source type
gen.Emit(OpCodes.Ldarg_1); // Load value to stack
gen.Emit(OpCodes.Unbox_Any, property.PropertyType); // Unbox the value to its proper value type
gen.Emit(OpCodes.Callvirt, setter); // Call the setter method
gen.Emit(OpCodes.Ret);
var result = (LateBoundPropertySet)method.CreateDelegate(typeof(LateBoundPropertySet));
return result;
}
*25-100x faster in my experience
Reflection is notoriously slow in loops, so some kind of caching would probably help. But to decide what to cache, you should measure. As the famous saying goes: "premature optimization is the root of all evil"; you should make sure that you really need to optimize and what exactly to optimize.
For a more concrete advice, attributes are attached at compile time, so you could cache a type and a list of its propertyInfos for example.
I also had similar problem once - reflection is extreemely slow.
I used caching, like you are planning and performance grow more than 10 times. It was never again be a bottleneck in performance.
I've created similar logic before where I've cached an 'execution plan' for each type encountered. It was definitely faster for subsequent runs but you would have to profile your scenario to see whether it's worth the extra code complexity and memory usage.
I have a series of methods to write, but I think there is some commonality (well, I know there is). The method I'd like to see will take two things, an object and... well, I'm not so sure about the second one, but probably a string.
The object should be generic, although it can only be from a set list (in this case, that commonality seems to be that they inherit from both INotifyPropertyChanging and INotifyPropertyChanged interfaces).
The string should be the name of a property within the generic object. It should be checked to see if that property exists within that object before being put into use (it would be used as a way to compare the objects by that given property).
So I guess the process would be... generic object gets passed into method (along with property name string). A check to see if the object contains the property. If it does, continue and somehow have access to 'object.PropertyName' where 'PropertyName' was the supplied string.
I don't know if it's easy or possible or even wise, but I know that it would save me some time.
Thanks in advance for any advice you might be able to offer with this.
Edit: Thanks for the all the replies so far guys. Let me clarify some things:
Clarification of 'access'
When I said, "... and somehow have access to 'object.PropertyName'", what I meant was that the method should be able to use that property name as if it were just a property of that object. So, let's say the string passed in was "ClientName", there would be the ability to read (possibly write, although at the moment I don't think so as it's just a check) object.ClientName, if it was determined that existed.
What I'm trying to do
I have a WCF service which accesses an SQL database using Linq. The objects I spoke of are entities, generated from the program SQLMetal.exe, so my objects are things like 'Client', 'User' and this sort of thing. I wrote a method which took a List of entities. This method added only those entities which did not exist within the collection (some could have been duplicates). It figured out which ones were duplicates by checking a property within the entity (which corresponds to data in a column of the database). It's that property which I figured might be variable.
It sounds like you don't really want to check if it's a certain type, and if that is so then you don't have to and its actually easier not to check the type. This shows how to check if the property exists and if it is readable and writeable and shows how to use it after it's found:
private void Form1_Load(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder();
PropertyInfo info = GetProperty(sb, "Capacity");
//To get the value of the property, call GetValue on the PropertyInfo with the object and null parameters:
info.GetValue(sb, null);
//To set the value of the property, call SetValue on the PropertyInfo with the object, value, and null parameters:
info.SetValue(sb, 20, null);
}
private PropertyInfo GetProperty(object obj, string property)
{
PropertyInfo info = obj.GetType().GetProperty(property);
if (info != null && info.CanRead && info.CanWrite)
return info;
return null;
}
I think only indexer properties can take parameters in C#. And I believe if you wrote properties in VB that take parameters and tried to reference that assembly in C# they would show up as methods instead of properties.
You could also write a function like this that would take 2 objects and a string for a property name and return the result of those properties matching:
private bool DoObjectsMatch(object obj1, object obj2, string propetyName)
{
PropertyInfo info1 = obj1.GetType().GetProperty(propertyName);
PropertyInfo info2 = obj2.GetType().GetProperty(propertyName);
if (info1 != null && info1.CanRead && info2 != null && info2.CanRead)
return info1.GetValue(obj1, null).ToString() == info2.GetValue(obj2, null).ToString();
return false;
}
Comparing the values of the properties might be tricky because it would compare them as objects and who knows how equality will be handled for them. But converting the values to strings should work for you in this case.
If you know the 2 objects are the same type then you can simplify it:
private bool DoObjectsMatch(object obj1, object obj2, string propetyName)
{
PropertyInfo info = obj1.GetType().GetProperty(propertyName);
if (info != null && info.CanRead)
return info.GetValue(obj1, null).ToString() == info.GetValue(obj2, null).ToString();
return false;
}
I think you're looking for something like:
public void SomeMethod<T>(T object, string propName)
where T : INotifyPropertyChanging, INotifyPropertyChanged
(
var type = typeof(T);
var property = type.GetProperty(propName);
if(property == null)
throw new ArgumentException("Property doesn't exist", "propName");
var value = property.GetValue(object, null);
)
I have the following interface in my project.
public interface Setting<T>
{
T Value { get; set; }
}
Using reflection, I would like to examine properties that implement this interface and extract Value.
So far I have written this, which successfully creates a list of properties that implement Setting.
var properties = from p in obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)
where p.PropertyType.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IAplSetting<>))
select p;
Next I would like to do this: (Please ignore the undefined variables, you can assume that they really do exist in my actual code.)
foreach (var property in properties)
{
dictionary.Add(property.Name, property.GetValue(_theObject, null).Value);
}
The problem is that GetValue returns an object. In order to access Value, I need to be able to cast to Setting<T>. How would I get Value and store it, without needing to know the exact type of T?
You could continue this approach with one more level of indirection:
object settingsObject = property.GetValue(_theObject, null);
dictionary.Add(
property.Name,
settingsObject.GetType().GetProperty("Value")
.GetValue(settingsObject, null));
If you're using dynamic (re: your comment about ExpandoObject), this can be much simpler:
dynamic settingsObject = property.GetValue(_theObject, null);
dictionary.Add(property.Name, settingsObject.Value);