tags:

views:

101

answers:

5

How would you create an extension method which enables me to do the following (warning: exteme pseudo-code)...

class FooBar
{
    Int32 Foo { get; set; }
    String Bar { get; set; }
}

new FooBar().With(fb => new Func<FooBar, Object>(instance =>
{
    // VB With magic
    // NOTE: The instance parameter HAS to be by reference
    instance.Foo = 10;
    instance.Bar;

    return new Object();
}));

If you could specify anonymous functions without a return type (void), the above would look much cleaner...

new FooBar().With(fb => new Func<FooBar, void>(instance =>
{
    instance.Foo = 10;
    instance.Bar;
}));

This is pseudo-code of the worst kind. But I hope you get the idea.

+1  A: 

How about just

return new FooBar{ Foo=10; };
Paul Hadfield
Updated my question. I need the instance by reference.
roosteronacid
To who ever did, it's a bit harsh to vote my answer down when it prompted an update in the question. It may not be relevant now with more information but at the time it was.
Paul Hadfield
+4  A: 

To specify anonymous methods without return type, use Action<T> instead of Func<T, TResult>:

new FooBar().With(new Action<FooBar>(instance =>
{
    instance.Foo = 10;
    instance.Bar;
}));

(I don't quite see the point in this particular case, but I take your word on the pseudo code part...)

Update
Full example for being complete:

The extension method:

public static void With<T>(this T input, Action<T> action)
{
    action(input);
}

Sample usage

new FooBar().With(fb =>
{
    fb.Foo = 10;
    fb.Bar = "some string";
});

Note that you don't need to explicitly declare the Action<FooBar>, the compiler figures that out. Should you wish to, for clarity, the call would look like this:

new FooBar().With<FooBar>(new Action<FooBar>(fb =>
{
    fb.Foo = 10;
    fb.Bar = "some string";
}));
Fredrik Mörk
+1 You were a couple of seconds faster
Albin Sunnanbo
How would the extension method look like?
roosteronacid
@roosteronacid: See updated answer.
Fredrik Mörk
+2  A: 

Maybe this will help:

new FooBar().With( fb=> {
    fb.Foo = 10;
    fb.Bar = fb.Foo.ToString();
} );

// ... somewhere else ...
public static void With<T>( this T target, Action<T> action ) {
    action( target );
}
TcKs
oh snap! you got there first.
Jamiec
So `fb` is by reference, and not by value, yes?
roosteronacid
@roosteronacid - assuming `T` is a class then yes. If you want to enforce this put a constraint on the method `where T : class`. See answer below.
Jamiec
Awesome! Exactly what I was looking for!
roosteronacid
+2  A: 

As you asked how to write the extension, here goes

public static void With<T>(this T target, Action<T> action) where T : class
{
   action(target);
}

Personally dont see what benefit this has, but fill yer boots!

Jamiec
+1  A: 

How would you like this:

FooBar instance = new FooBar();

instance.With(new
{
    Foo = 1,
    Bar = "B"
});

This can be made to work with below extension method:

using System.Reflection;

public static class WithExtension
{
    public static T With<T>(this T target, object values)
    {
        Type targetType = typeof(T);

        foreach (PropertyInfo prop in values.GetType().GetProperties())
        {
            PropertyInfo targetProp = targetType.GetProperty(prop.Name);

            if (targetProp != null && targetProp.PropertyType==prop.PropertyType)
            {
                targetProp.SetValue(target, prop.GetValue(values, null), null );
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
        return target;
    }
}

What this essentially does is copying over properties' values from an anonymous object to the target object. (The above code only works with properties, not with fields, but could easily be extended to being capable of dealing with both.)

Note that this has less clutter than working with lambdas. The drawback is that static type checking doesn't work.

stakx