-
-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache boxed value type values in ModelBase #1438
Conversation
|
||
/// <summary> | ||
/// Caches boxed objects to minimize the memory footprint for boxed value types. | ||
/// </summary> | ||
public class BoxingCache<T> | ||
where T : struct |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just more of a curiosity. I see you removed the type constraint but would have it made more sense to constrain it against IConvertible? It's supported on all the platforms Catel is targeting and makes more sense than struct for what this is being used for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, was not aware of this interface. Will investigate, I want to enforce value types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's perfect for when you want to enforce only primitive types (or anything that implements IConvertible) in an generic since struct can introduce a whole can of worms (also avoids having to do ValueType or IsPrimitive checks elsewhere).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does support reference values as well (e.g. a string), and that's something we definitely don't want to cache). But we can enforce that simply by checking for value type first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And now I remember why I didn't enforce it to anything. We use this in this method:
protected static object GetObjectValue<TValue>(TValue value)
{
object objectValue = null;
if (typeof(TValue).IsValueTypeEx())
{
objectValue = BoxingCache<TValue>.Default.GetBoxedValue(value);
}
else
{
objectValue = value;
}
return objectValue;
}
Then we would have to add the constraint there as well, but we want to support reference types there as well (and at runtime check which path to take).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this may be better then?
public static bool IsValueTypeEx(this Type type)
{
return (type is IConvertible);
}
Since all primitive types derive from this interface that should be all you'd need. There is the obvious side effect that if someone actually goes through the trouble of implementing IConvertible it ends up returning true but I've never seen anyone actually do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, IsAssignableFrom is an extension method, I wonder whether it does this under the hood anyway:
public static bool IsAssignableFromEx(this Type type, Type typeToCheck)
{
Argument.IsNotNull("type", type);
Argument.IsNotNull("typeToCheck", typeToCheck);
#if UAP_DEFAULT
return type.IsAssignableFrom(typeToCheck);
//return type.GetTypeInfo().IsAssignableFrom(typeToCheck.GetTypeInfo());
#else
return type.IsAssignableFrom(typeToCheck);
#endif
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this may be better then?
public static bool IsValueTypeEx(this Type type) { return (type is IConvertible); }
Since all primitive types derive from this interface that should be all you'd need. There is the obvious side effect that if someone actually goes through the trouble of implementing IConvertible it ends up returning true but I've never seen anyone actually do that.
This definitely makes sense for UAP, but I think it's still faster to read a property value than to check for type (but not sure, and we are talking nano-optimizations here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, if there’s serious concerns about performance here (doubtful) dotTrace can be used later.
} | ||
|
||
if (!set) | ||
{ | ||
var memberMetadata = modelInfo.PropertiesByName[member.Name]; | ||
if (memberMetadata != null) | ||
{ | ||
((PropertyInfo)memberMetadata.Tag).SetValue(model, member.Value, null); | ||
((PropertyInfo)memberMetadata.Tag).SetValue(model, finalValue, null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good example of what would benefit from the expression tree setter and would speed up serialization.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Description of Change
Cache boxed values.
Issues Resolved
API Changes
Platforms Affected
Behavioral Changes
None
Testing Procedure
PR Checklist