Matas Vaitkevicius
Matas Vaitkevicius

Reputation: 61391

Extension method that accepts Expression<Func<T>> expression as parameter

I am using .NET4.5 and C# I fancied creating extension method that would allow me to pass property of object and if Id of that object is 0 then return null otherwise return that property value.

I could do it no problem with reflection so consider this more of training exercise and not me trying to solve the actual problem.

Currently extension method is sitting in static class looking like this:

    public static object GetNullIfNotSet(this WillAnswer answer, Expression<Func<WillAnswer>> expression)
    {
        if (answer.Id == 0) return null;
        return expression.Compile()();
    }

The way I want to be able to use it is following (answer is of type WillAnswer):

var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets)

However it gives me compilation error:

Error 1 Delegate 'System.Func' does not take 1 arguments C:\hg\Website\Areas\Wills\ViewModel\Answers.cs 38 59 Website enter image description here

Which makes me frown since I don't think I am passing any arguments (am I?). Could please someone smarter than myself explain which of my expectations is wrong.

Just in case I wasn't clear I will reiterate. What I want is to be able to call var emptyIfNewObject = answer.GetNullIfNotSet(o => o.HasBusinessAssets) and get null if Id of answer is 0.

Upvotes: 12

Views: 4132

Answers (3)

Elektro Umut
Elektro Umut

Reputation: 1

Yes you can:

public static void LoadProperty<T>(this T t, Func<T, object> func) where T: Entity
{       

}

and you can use :

contact.LoadProperty(p => p.LogicalName);

Upvotes: 0

haim770
haim770

Reputation: 49095

No need for Expression at all, just use Func<WillAnswer, TProp>:

public static TProp GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
    if (answer.Id == 0) return default(TProp);
    return func(answer);
}

Please note, that this will not always return null but the default value (in case the property is a value-type).

Update (as per your request):

In order to be able to return null for all passed properties, the method signature was changed to return object instead:

public static object GetNullIfNotSet<TProp>(this WillAnswer answer, Func<WillAnswer, TProp> func)
{
    if (answer.Id == 0) return null;
    return func(answer);
}

But, you'll lose the benefits of generics and you'll end up with explicit casts to Nullable<T>:

var emptyIfNewObject = (bool?)answer.GetNullIfNotSet(o => o.HasBusinessAssets)

Which is less ideal.

Upvotes: 14

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

It seems that you need a Func<WillAnswer, T> not an expression:

  public static T GetDefaultIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) {
    if (null == answer)   
      throw new ArgumentNullException("answer");
    else if (null == func)   
      throw new ArgumentNullException("func");

    return answer.Id == 0 ? return default(T) : func(answer);
  }

EDIT: if you want to ensure null you can restrict generic T:

     public static T GetNullIfNotSet<T>(this WillAnswer answer, Func<WillAnswer, T> func) 
       where T: class { // no structs here
         if (null == answer)   
           throw new ArgumentNullException("answer");
         else if (null == func)   
           throw new ArgumentNullException("func");

         return answer.Id == 0 ? return null : func(answer);
     } 

Upvotes: 7

Related Questions