This project has moved. For the latest updates, please go here.
2
Vote

Action<> as property

description

I am playing around with your library and this test is failing. Don't know if it is supported or not. Action assigned to Test seems not to be invoked, but no exception is thrown or anything.

[Test]
    public void test_propoerty_as_Action()
    {
        dynamic x = new Clay(Cat(new PropBehavior()));
        x.Result = 3;

        x.Result = x.Result + 2;

        Assert.IsTrue(x.Result==5);

        x.Test = new Action<int>(n => { x.Result += n ; });

        x.Test(2);

        Assert.AreSame(7,x.Result);


    }

comments

epitka wrote Jan 20, 2011 at 7:29 PM

But this works

x.Test().Invoke(2);

which leads me to believe that in case of Action/Func Invoke is not invoked?

epitka wrote Jan 21, 2011 at 3:30 PM

I keep debugging and trying to figure out what is going on, and I think that PropBehavior needs to override InvokeMember for this to work. Hardcoding args I get it to work, which means that I probably could get it to work maybe with building expression tree or with reflection maybe.

public override object InvokeMember(Func<object> proceed, object self, string name, INamedEnumerable<object>
{
         dynamic value;
         var toReturn = _props.TryGetValue(name, out value) ? value : null;   // this will give me the Action that is stored in the property dictionary

         value.Invoke(2); // hardcoded arguments just to try it, needs to be populated dynamically from the args collection. 

         return proceed; // don't know if I need to return anything here
}

epitka wrote Jan 21, 2011 at 5:45 PM

And to continue my monolog, here is what I have now. This will work for me, for what I need to do, but don't know how it would work in other situations. I am going to extend PropBehavior and add this method

public override object InvokeMember(Func<object> proceed, object self, string name, INamedEnumerable<object> args)
    {
        object obj;
        _props.TryGetValue(name, out obj);

        if (obj == null) return proceed();

        if (obj is MulticastDelegate)
        {
            return obj.GetType().GetMethod("Invoke").Invoke(obj, args.ToArray());
        }

        return proceed;
    }

epitka wrote Jan 22, 2011 at 12:33 AM

I've just committed a fork that includes these changes and also allows definition of getters/setters as well.

dcazzulino wrote Jan 16, 2012 at 8:17 PM

actually x.Test()() also works, but looks weird like hell :)

I think Clay should drop the javascript/java-like syntax for accessing properties with parenthesis (i.e. person.FirstName()) and keep the C#/VB idiom for properties and indexed properties.

This would allow it to disambiguate when you're accessing a property vs trying to invoke a member. This way, any property assigned a delegate, becomes a method you can invoke directly without any extra junk. i.e.

person.Log = new Action(() => Console.WriteLine("Hello"));


person.Log(); // writes "Hello"

Action logger = person.Log; // retrieves the actual Action assigned to the "property"/method.