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?

7 답변


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;
    }
}


  • Hi George, your solution does not work for nested Lambda's like MembersOf<Animal>.GetName(x => x.Gender.Text) should give "Gender.Text", not just "Text". - Stef Heyenrath
  • @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
  • the answer from LukeH at stackoverflow.com/questions/3049825/… is exactly what I need. - Stef Heyenrath
  • @GeorgeMauer Why don't you replace MembersOf<T>.GetName<R>(Expression<Func<T,R>> expr) with MembersOf.GetName<T>(Expression<Func<T,Object>> expr), it's easier and you don't need a specific R type (even it's inferred at compilation). - Yves M.
  • @YvesM. what advantage would that hold? - George Mauer

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


7

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.


  • He doesn't want all property names, just specific ones - George Mauer
  • 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

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
}



1

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


  • I think he wants the code to work for derived classes as well, so he needs to use reflection. - Zach Johnson
  • 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

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);


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).

Linked


Related

Latest