1

I have created an extension method as per an answer on SO here

public class AcObject
{
    public int Id { get; set; }
}

public static Dictionary<string, string> GetValidationList<AcObject, TProperty>(
    this AcObject source,
    Expression<Func<AcObject, TProperty>> propertyLambda)
{
    // Autocomplete here only shows static members for 'source'
    // I am expecting to be able to do source.Id
}

enter image description here

Anyone able to explain to me why I can't use source.Id in the above scenario and suggest where I can look to come up with a similar solution?

If I set a breakpoint inside the GetValidationList() method I can mouseover source and see the instance and it's properties as one would expect... I just can't use it in VS.

enter image description here

My overall goal is to be able to do the following

public class AcObject
{
    public int Id { get; set; }
    public string Type { get; set; }
}

public class OtherObject : AcObject
{
    public string AssetTag { get; set; }
}

// somewhere else in code
AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Type);

// Along with using the type that inherits it
OtherObject myOtherObject = new OtherObject();
myOtherObject.GetValidationList(a => a.Type);

// In some kind of extension method lambda magic
{
    Console.WriteLine(source.Id);
}

Edit - Updated to include the requirement of it working on base classes as well as those that inherit it.

Community
  • 1
  • 1
Alex.Ritna
  • 1,957
  • 2
  • 16
  • 24

2 Answers2

4

Change the signature of your extension method as follows: (remove the initial "AcObject")

public static Dictionary<string, string> GetValidationList<TProperty>(
    this AcObject source, Expression<Func<AcObject, TProperty>> propertyLambda)

There's a typo in your last bit of code too:

AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Type);  // call the extension method on the instance

Those type parameters you've included (AcObject and TProperty) are placeholders, representing the actual types you specify when you call the method. By naming the first one "AcObject" in your method, you're hiding the actual class also called "AcObject" (so the "AcObject" in this AcObject source is no longer referencing your class).


Given the update to your question, modify your signature like this. You basically had it correct in the beginning, just change the name of the type parameter from "AcObject" to something else that's not your class name, like "T":

public static Dictionary<string, string> GetValidationList<T, TProperty>(
    this T source, Expression<Func<T, TProperty>> propertyLambda)

Then you can call it with your different classes:

AcObject myObject = new AcObject();
myObject.GetValidationList(a => a.Id);

OtherObject myOtherObject = new OtherObject();
myOtherObject.GetValidationList(a => a.AssetTag);
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • It would be great to explain, why OP need to change the signature. Looks like he misunderstanding type parameters concept. – Dennis Sep 24 '14 at 05:28
  • As @Dennis mentioned I think I'm misunderstanding something here. If I make the above change as you mentioned, it then works fine for any objects that are explicitly `AcObject` but fails for something that inherits `AcObject`. I'll amend my OP to include an example. – Alex.Ritna Sep 24 '14 at 05:33
  • To be clear, by "fails" I mean it only lists the properties of `AcObject` in my lamda expresion, not the properties of the current type. `public class AcAsset : AcObject { ... }` then `AcAsset asset = new AcAsset().GetValidationList(a => a.` here it only lists the members of `AcObject` – Alex.Ritna Sep 24 '14 at 05:38
0
public static class stat
    {
        public static void GetValidationList(  this AcObject source )
        {
            Console.WriteLine(source.Id);

        }
    }


    public class AcObject
{
    public int Id { get; set; }
}

Usage :

    AcObject myObject = new AcObject();
    myObject.GetValidationList();
Abdul Rehman Sayed
  • 6,532
  • 7
  • 45
  • 74