question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Loom.Fody: Tricky but cool Fody Add-In idea

See original GitHub issue

There is a really cool way of allowing for a range of property modifications similar to the Add-Ins PropertyChanged, PropertyChanging and probably AutoDependencyProperty - built with one, very generic Fody Add-In.

The idea is to allow any property implementation defined in the modified assembly be woven in to replace the existing one by writing them as value types implementing interfaces.

As is perhaps well-known among you folks, C# interfaces, C# value type and C# generics come together in a positive twist of .NET goodness: If a value type is used as a type parameter in some generic type, method calls to methods on the value type (through an interface) are not virtual and there’s no boxing involved.

Let me give an example. The class below defines a concrete property implementation.

    public interface IPropertyImplementation<ValueInterface, Value>
        where Value : ValueInterface
    {
        Value Get(Object self);
        void Set(Object self, Value value);
    }

    public struct MyPropertyImplementation<Value, OriginalImplementation>
        : IPropertyImplementation<IComparable<Value>, Value>

        where Value : IComparable<Value>
        where OriginalImplementation : IPropertyImplementation<IComparable<Value>, Value>
    {
        public OriginalImplementation originalImplementation;

        public Value Get(Object self)
        {
            Logger.Log($"Object {self} providing a value.");
            return originalImplementation.Get(self);
        }

        public void Set(Object self, Value newValue)
        {
            var oldValue = originalImplementation.Get(self);
            Logger.Log($"Object {self} receiving new value, which is {(oldValue.CompareTo(newValue) < 0 ? "greater" : "less or equal")}.");
            originalImplementation.Set(self, newValue);
        }
    }

Our yet-to-be-written Add-In would take MyPropertyImplementation and use it to actually implement the properties of certain types (exactly which is a matter of configuration and taste and should not matter here).

The cool thing here is that the call to originalImplementation.Get(self) will in fact not be late-bound (and it’s not boxed either), but an early-bound direct call - the fastest there is. The original implementation is probably even inlined when the optimizer is on.

It’s one trick Java can’t do.

(It works that way even when one creates types at run-time, although not any more with .NET native. But I’m digressing…)

Above implementation can only be used on properties of specific type though: We decided that they all have to be IComparable. That’s why we can use that in above implementation.

Now let’s say this is the type to be rewoven:

    public class ClassToHaveItsPropertiesModified
    {
        public Decimal Decimal { get; set; }

        public Int32 Int32 {
            get {
                return (Int32)Decimal;
            }
            set {
                Decimal = Int32;
            }
        }
    }

Then this would be what the weaver makes of it:

    public class ClassThatHadItsPropertiesModified
    {
        TheImplementationWrappingDecimalAccessors decimalAccessors; // explained below

        public MyPropertyImplementation<
            Decimal,
            TheImplementationWrappingDecimalAccessors
            >
            decimalImplementation;

        public ClassThatHadItsPropertiesModified()
        {
            decimalImplementation.originalImplementation = decimalAccessors;
        }

        public Decimal Decimal {
            get {
                return decimalImplementation.Get(this);
            }
            set {
                decimalImplementation.Set(this, value);
            }
        }

        // same for int
        // ...

The TheImplementationWrappingDecimalAccessors type is created by the weaver and provides access to the previous getter and setter methods so the new implementation can call down to them.

This gives a way to sort-of “weave IL without explicitly doing IL”.

I’m a bit in love with this idea.

(The sample here is a bit too simple though. For a PropertyChanged, for example, we also need to mix in a part that has the event implementation and can be accessed by the property implementations. I put up a more complete picture as a gist, although I think it’s fairly straight-forward how that would go.)

Alas, I’m not at all familiar with Cecil and fear this gets me too much off on a tangent. So I wanted to at least put it up for debate.

(Background: I was toying with the idea to bring a dependency tracking implementation, Moldinium, to Fody to allow for dependency-tracked properties. And since I’m me, I can’t help getting distracted on every step.)

I also apologize for being off-topic here, I’m not sure where else I would raise this.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:10 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
distantcamcommented, Jun 5, 2017

I won’t mature this much further, but it’s a proof-of-concept and a starting point for all that would like to build on it.

Oooh, be very careful about that. I have a number of Fody plugins that were just ideas I had that people now use, and want me to support, even if I never used them myself.

0reactions
jtheisencommented, Sep 26, 2017

No worries.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Creating a Fody Add-in
Fody is a fantastic framework for creating IL weavers. This blog walks through creating a library that can modify an existing .NET assembly....
Read more >
F# is gaining independence from .NET
Because F# is based on OCAML and an extremely popular ... F# doesn't force you to do that even when it is a...
Read more >
Low FODMAP grocery list
I'm working w/ a client now and have her following a FODMAPs diet. She's doing great, but has some problems when she's eating...
Read more >
Untitled
Bincs cage code, K&f drill press, Sejarah utankayu, X2i qmobile hard reset, ... Porto's bakery wikipedia, Body and mind fitness studio, Beylerbeyi palace ......
Read more >
Untitled
#mlb Party city nyc address, Pablo fanque, Union flag stars and stripes, ... Cs na tablet download, Mauritius fody, Clear health communication!
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found