Skip to main content

Posts

Showing posts with the label reflection

Fast Deep Copies in C# using Sasa.Dynamics

I've briefly discussed Sasa.Dynamics in my first announcement for the upcoming Sasa v0.9.4 release. There was some confusion about what Sasa.Dynamics really is though, since the post didn't go into much detail, or wasn't explained clearly enough. In short, Sasa.Dynamics is a framework for type-safe, blazingly fast reflection. It's useful for writing all sorts of algorithms that compute results based on the structure of types. For instance, as mentioned in the above article, Sasa.Dynamics ships with two such algorithms by default: an immutable type test , and a deep copier . Both of these algorithms are fully generic and apply to any type, and they're faster than anything you can do with standard reflection. Here's how you perform a deep copy on an object: var copy = Type<T>.Copy(originalValue); If you don't know anything about the type you're copying, you can just supply T = object. The more specific the static type information you provide t...

Sasa.Func - Type-Safe Delegate Combinators

This is the third post in my series of posts on useful Sasa abstractions: Sasa.Parsing - type-safe, extensible lexing and parsing framework Sasa.Dynamics - type-safe polytypic/reflective programming This post will deal with a the Sasa.Func static class in the stand-alone core Sasa assembly. This core assembly is concerned mainly with addressing limitations in the core .NET base class libraries. For instance, it contains type-safe, null-safe and thread-safe event operations , extensions on IEnumerable, useful extensions to numbers, and so on. Sasa.Func is particularly concerned with providing type-safe extensions on delegates. You can view the whole API online . Sasa.Func is available in the core Sasa.dll. Sasa.Func.Id The simplest starting point is Sasa.Func.Id . Use this method whenever you need a delegate that simply returns its argument. This is fairly common when using the System.Linq API. Usage: int[][] nested = new int[][] { { 0, 1, 2 }, { 3, 4, 5 }, { 6,...

Sasa-v0.9.4-RC2 Released - A Sasa.Dynamics Overview

I've just uploaded the next release candidate for Sasa-v0.9.4 . This features a few changes due to problems I ran into while porting old code to the new codebase. Not bugs per se, but unfortunate limitations of certain Microsoft libraries. There are also a few new extensions written to showcase Sasa.Dynamics, which are detailed below. Sasa.Dynamics The experimental type safe reflection facilities of Sasa v0.9.3 were completely revamped since they weren't general enough to handle all of the CLR's and C#'s constructs. The main problem was that the ref-based callback interface wouldn't integrate well with readonly fields. The only time you can create a reference to a readonly field is in the constructor, so clients couldn't implement the old IReflected interface on any immutable objects. The new approach in Sasa.Dynamics separates two orthogonal concepts: 1. typecase, and 2. folding over an object's fields. Typecase is an operation from the research li...

Managed Data for .NET

Ensō is an interesting new language being developed by Alex Loh, William R. Cook, and Tijs van der Storm. The overarching goal is to significantly raise the level of abstraction, partly via declarative data models. They recently published a paper on this subject for Onwards! 2012 titled Managed Data: Modular Strategies for Data Abstraction . Instead of programmers defining concrete classes, managed data requires the programmer to define a schema describing his data model, consisting of a description of the set of fields and field types. Actual implementations of this schema are provided by "data managers", which interpret the schema and add custom behaviour. This is conceptually similar to aspect-oriented programming, but with a safer, more principled foundation. A data manager can implement any sort of field-like behaviour. The paper describes a few basic variants: BasicRecord: implements a simple record with getters and setters. LockableRecord: implements locking on...

Compact, Declarative Serialization

A few posts back , I hinted at using parameterization as an alternative to metadata. I've just written a serialization interface using this technique, and a binary serializer/deserializer to demonstrate the inherent tradeoffs. You can inspect the pair of interfaces required, and I implemented a binary serializer/deserializer pair as an example. ICompactSerializable is implemented for each serializable object. It's essentially a declarative method, which describes the sequential, internal structure of the object. It's simple and fast, since it provides native speed access to an object's fields without reflection, and no need for metadata. Of course, the obvious downside is that clients must describe the internal structure themselves via ICompactSerializer , and refactoring must be careful about reordering the sequence of calls. The upshot is that serialization and deserialization is insanely fast as compared to ordinary reflection-driven serialization, the binary is f...

Reflection, Attributes and Parameterization

I used to be a big fan of reflection, and C#'s attributes also looked like a significant enhancement. Attributes provide a declarative way to attach metadata to fields, methods, and classes, and this metadata is often used during reflection. The more I learned about functional programming, type systems, and so on, the more I came to realize that reflection isn't all it's cracked up to be. Consider .NET serialization. You can annotate fields you don't want serialized with the attribute [field:NonSerialized]. However, metadata is just data, and every usage of attributes can be replaced with a pair of interfaces. Using [field:NonSerialized] as an example, we can translate this class: class Foo { [field:NonSerialized] object bar; } Into one like this: // these two interfaces take the place of a NonSerializableAttribute declaration interface INonSerialized { void Field<T>(ref T field); } interface IUnserializableMembers { void Unserializable(INonSerialized s); ...