14

I would like to automatically generate SQL statements from a class instance. The method should look like Update(object[] Properties, object PrimaryKeyProperty). The method is part of an instance (class, base method - generic for any child). Array of properties is an array of class properties, that will be used in update statement. Property names are equal to table field names.

The problem is that I can't get property names.

Is there any option to get a property name inside class instance? sample:

public class MyClass {
public int iMyProperty { get; set; }
public string cMyProperty2 { get; set; }
{

main() {
 MyClass _main = new MyClass();

_main.iMyProperty.*PropertyName* // should return string "iMyProperty"

{

I am aware of PropertyInfo, but I don't know hot to get the ID of a property from GetProperties() array.

Any suggestion?

Alfred Myers
  • 6,384
  • 1
  • 40
  • 68
FrenkR
  • 327
  • 1
  • 3
  • 11

7 Answers7

28

Just wrote an implementation of this for a presentation on lambdas for our usergroup last Tuesday.

  • You can do

    MembersOf<Animal>.GetName(x => x.Status)

  • Or

    var a = new Animal() a.MemberName(x => x.Status)

the code:

public static class MembersOf<T> {
    public static string GetName<R>(Expression<Func<T,R>> expr) {
        var node = expr.Body as MemberExpression;
        if (object.ReferenceEquals(null, node)) 
            throw new InvalidOperationException("Expression must be of member access");
        return node.Member.Name;
    }
}
George Mauer
  • 117,483
  • 131
  • 382
  • 612
  • Hi George, your solution does not work for nested Lambda's like MembersOf.GetName(x => x.Gender.Text) should give "Gender.Text", not just "Text". – Stef Heyenrath Jul 25 '11 at 10:18
  • @Stef, that is correct. x.Gender.Text is not a member accessor. Check the implementation though, it should be relatively easy to make it detect a whole syntax tree and recurse repeatedly – George Mauer Jul 25 '11 at 17:56
  • the answer from LukeH at http://stackoverflow.com/questions/3049825/given-a-member-access-lambda-expression-convert-it-to-a-specific-string-represen is exactly what I need. – Stef Heyenrath Jul 25 '11 at 19:17
  • @GeorgeMauer Why don't you replace `MembersOf.GetName(Expression> expr)` with **`MembersOf.GetName(Expression> expr)`**, it's easier and you don't need a specific R type (even it's inferred at compilation). – Yves M. Mar 17 '14 at 16:45
  • @YvesM. what advantage would that hold? – George Mauer Mar 17 '14 at 18:48
  • @GeorgeMauer Types T and R are separated: **MembersOf** and **GetName** instead of GetName. This has been done only to have type R isolated so **R can be inferred**. The problem is when I need to use MembersOf in another function I will have to specify T and R without being able to separate them. For example: `public string MyFunction(Expression> expr){return new MembersOf().GetName()}`. T and R are no longer separated and R cannot be inferred when using MyFunction. But if you replace R with Object, you don't have to do tricks to facilitate inferrance – Yves M. Mar 18 '14 at 08:51
  • @GeorgeMauer and it will be semantically more accurate. Nobody cares about type R. We only need the expression to returns something.. anything.. Object! – Yves M. Mar 18 '14 at 08:53
  • Good point on the type inference, I'm less inclined to agree to the latter though. `` with no constraints means "any T and any R", whereas `` could potentially mean "any T and a downcast/boxed object". Your point might be carried better by a `` signature. Either way, these are all very minor considerations - I probably wouldn't even mention them in a code review. – George Mauer Mar 18 '14 at 12:50
10

I found a perfect solution in This Post

public static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
{
   return (propertyExpression.Body as MemberExpression).Member.Name;
}

And then for the usage :

var propertyName = GetPropertyName(
() => myObject.AProperty); // returns "AProperty"

Works like a charm

Community
  • 1
  • 1
Mehdi LAMRANI
  • 11,289
  • 14
  • 88
  • 130
6

You can do something like this:

Type t = someInstance.getType();

foreach (MemberInfo mi in t.GetMembers())
{
    if (mi.MemberType == MemberTypes.Property)
    {
        Console.WriteLine(mi.Name);
    }
}

to get all the property names for instance's type.

Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
  • 1
    He doesn't want all property names, just specific ones – George Mauer Sep 10 '09 at 21:03
  • 1
    Not sure that merits a downvote. The question says, "is there any option to get property name inside class instance?" I've shown a loop which goes through printing *all* the property names in a class instance, but he can all get the ones he wants to update into an array which he passes to the Update procedure. I don't see what the problem is. – Vinay Sajip Sep 10 '09 at 21:45
2

You can get the name (I assume that's what you meant by ID) of a property using PropertyInfo.Name. Just loop through the PropertyInfo[] returned from typeof(className).GetProperties()

foreach (PropertyInfo info in typeof(MyClass).GetProperties())
{
    string name = info.Name;
    // use name here
}
Zach Johnson
  • 23,678
  • 6
  • 69
  • 86
1

Since you already have an explicit handle to the specific property you want, you know the name - can you just type it?

Rex M
  • 142,167
  • 33
  • 283
  • 313
  • I think he wants the code to work for derived classes as well, so he needs to use reflection. – Zach Johnson Sep 10 '09 at 20:49
  • The main idea is not to duplicate names. So when a class (with attributes) is written I get an automatic table generation, CRUD statements and *Intellisense*. – FrenkR Sep 11 '09 at 10:32
1

Let's say (from the first sample, method update of a class MyClass):

public class MyClass {

public int iMyStatusProperty { get; set; }
public int iMyKey { get; set; }

public int UpdateStatusProperty(int iValue){
this.iMyStatusProperty = iValue;
return _Update( new[iMyStatusProperty ], iMyKey); // this should generate SQL: "UPDATE MyClass set iMyStatusProperty = {iMyStatusProperty} where iMyKey = {iMyKey}"
}

{iMyStatusProperty} and {iMyKey} are property values of a class instance.

So, the problem is how to get property name (reflection) from a property without using names of properties as strings (to avoid field name typos).

Jason Plank
  • 2,336
  • 5
  • 31
  • 40
FrenkR
  • 327
  • 1
  • 3
  • 11
1

Not 100% sure if this will get you what you're looking for, this will fetch all properties with [Column] attribute inside your class: In the datacontext I have:

 public ReadOnlyCollection<MetaDataMember> ColumnNames<TEntity>( )
    {
        return this.Mapping.MappingSource.GetModel(typeof(DataContext)).GetMetaType(typeof(TEntity)).DataMembers;
    }

Fetching the table column-names that are properties inside the class:

       MyDataContext db = GetDataContext(); 
       var allColumnPropertyNames =   db.ColumnNames<Animal>().Where(n => n.Member.GetCustomAttributes(typeof(System.Data.Linq.Mapping.ColumnAttribute), false).FirstOrDefault() != null).Select(n => n.Name);
Contra
  • 2,754
  • 4
  • 20
  • 18