I need to get the property name of a static property dynamically called as a parameter.
Here is my Portable Class Library code:
public partial class Test
{
public Test()
{
string staticPropName = Test.GetPropName(Test.Row); // result must be "Row" without additional string
System.Diagnostics.Debug.WriteLine("propName=" + staticPropName);
}
public static int Row { get; set; }
public static string GetPropName(object Property)
{
return "Row"; // using reflection
}
}
I don't know the name of the property and I don't want to define it with an additional string.
You can't do that - when function is called it gets value of the property and have no idea where this value come from. Your sample is equivalent of
string staticPropName = Test.GetPropName(42);
which nobody would expect to return name.
You can try to require Expression as argument so you can actually inspect what method get called with like following staring point (https://stackoverflow.com/questions/1011109/how-do-you-get-the-name-of-the-property):
public static string GetPropName<TResult>(Expression<Func<TResult>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
string staticPropName = Test.GetPropName(()=> Test.Prop);
Note that you need checks to make sure expression is just one you expect and not something like () => Test + 42 or more complex one and report nice error.
Related
I need to mark some properties as passwords so that they could be automatically screened. I found a standard attribute for that:
[PasswordPropertyText]
public string ThePassword { get; set; }
Following method checks if the attribute is there:
private static bool _isPassword(PropertyInfo p)
{
PasswordPropertyTextAttribute passProp = (PasswordPropertyTextAttribute)p.GetCustomAttribute(typeof(PasswordPropertyTextAttribute));
return (passProp != null); // Additional condition should go here
}
Now I would like to have my own logic here:
[PasswordPropertyText] should result in true.
[PasswordPropertyText(true)] should result in true.
[PasswordPropertyText(false)] should result in false.
but the default value of PasswordPropertyTextAttribute.Password is false when the argument is omitted.
Is there any way to get the raw attribute value?
Since attribute constructor information are stored as metadata as well you can get the required information by calling the GetCustomAttributesData method. Have a look at this simple example:
class Program
{
[PasswordPropertyText]
public string Password1 { get; set; }
[PasswordPropertyText(true)]
public string Password2 { get; set; }
[PasswordPropertyText(false)]
public string Password3 { get; set; }
static void Main(string[] args)
{
var props = typeof(Program).GetProperties();
foreach(var prop in props)
{
var attributeData = prop.GetCustomAttributesData().First(x => x.AttributeType == typeof(PasswordPropertyTextAttribute));
Console.WriteLine($"{prop.Name}: {(attributeData.ConstructorArguments.Cast<CustomAttributeTypedArgument?>().FirstOrDefault()?.Value ?? true)}");
}
Console.ReadLine();
}
}
Output:
Password1: True
Password2: True
Password3: False
What you're describing cannot be done using reflection.
Reflection is not looking at the code as it was written: it is looking at the model that results from that code. Since the default constructor for PasswordPropertyTextAttribute passes a false value to another constructor, the model that it produces is indistinguishable from using [PasswordPropertyText(false)].
If you want different behavior from the built-in attribute, I'd recommend creating your own attribute that has the behavior you're looking for instead.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding the Variable Name passed to a Function in C#
The class below contains the field city.
I need to dynamically determine the field's name as it is typed in the class declaration
i.e. I need to get the string "city" from an instance of the object city.
I have tried to do this by examining its Type in DoSomething() but can't find it when examining the contents of the Type in the debugger.
Is it possible?
public class Person
{
public string city = "New York";
public Person()
{
}
public void DoSomething()
{
Type t = city.GetType();
string field_name = t.SomeUnkownFunction();
//would return the string "city" if it existed!
}
}
Some people in their answers below have asked me why I want to do this.
Here's why.
In my real world situation, there is a custom attribute above city.
[MyCustomAttribute("param1", "param2", etc)]
public string city = "New York";
I need this attribute in other code.
To get the attribute, I use reflection.
And in the reflection code I need to type the string "city"
MyCustomAttribute attr;
Type t = typeof(Person);
foreach (FieldInfo field in t.GetFields())
{
if (field.Name == "city")
{
//do stuff when we find the field that has the attribute we need
}
}
Now this isn't type safe.
If I changed the variable "city" to "workCity" in my field declaration in Person this line would fail unless I knew to update the string
if (field.Name == "workCity")
//I have to make this change in another file for this to still work, yuk!
{
}
So I am trying to find some way to pass the string to this code without physically typing it.
Yes, I could declare it as a string constant in Person (or something like that) but that would still be typing it twice.
Phew! That was tough to explain!!
Thanks
Thanks to all who answered this * a lot*. It sent me on a new path to better understand lambda expressions. And it created a new question.
Maybe you need this. Works fine.
I found this here.
static void Main(string[] args)
{
var domain = "matrix";
Check(() => domain);
Console.ReadLine();
}
static void Check<T>(Expression<Func<T>> expr)
{
var body = ((MemberExpression)expr.Body);
Console.WriteLine("Name is: {0}", body.Member.Name);
Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member)
.GetValue(((ConstantExpression)body.Expression).Value));
}
Output will be:
Name is: 'domain'
Value is: 'matrix'
I know this is old question, but I was trying to achieve the same and google sent me here. After many hours I finally found a way. I hope somebody else will find this useful.
There are actually more ways to accomplish this:
static void Main(string[] args)
{
GetName(new { var1 });
GetName2(() => var1);
GetName3(() => var1);
}
static string GetName<T>(T item) where T : class
{
return typeof(T).GetProperties()[0].Name;
}
static string GetName2<T>(Expression<Func<T>> expr)
{
return ((MemberExpression)expr.Body).Member.Name;
}
static string GetName3<T>(Func<T> expr)
{
return expr.Target.GetType().Module.ResolveField(BitConverter.ToInt32(expr.Method.GetMethodBody().GetILAsByteArray(), 2)).Name;
}
The first is fastest. The last 2 are approx 20 times slower than the 1st one.
http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
city in this case is an instance of type string. When you call .GetType() you return the actual string type, which has no knowledge at all of your particular city instance.
I'm having a hard time seeing why you can't just type "city" in the code as a string literal here, if that's what you need. Perhaps it would help if you shared what you want to use this value for and in what circumstances you will call your DoSomething() function.
At the moment, my best guess is that what you really want to do is reflect the entire Person class to get a list of the fields in that class:
public void DoSomething()
{
MemberInfo[] members = this.GetType().GetMembers();
// now you can do whatever you want with each of the members,
// including checking their .Name properties.
}
Okay, based on your edit I have some more for you.
You can find the name of fields that are decorated with your attribute at run-time like this:
Type t = typeof(Person);
foreach (MemberInfo member in t.GetMembers()
.Where(m =>
m.GetCustomAttributes(typeof(MyCustomAttribute)).Any() ) )
{
// "member" is a MemberInfo object for a Peson member that is
// decorated with your attribute
}
You can also use binding flags in the first GetMembers() call to limit it to just fields, if you want.
You mentioned "i.e. I need to get the string "city" from an instance of the object city."
Are you looking to get the field name from the value of the field.
For example:If there are 2 Person object one with city "New York" and the other with city "London", are you looking for the function to return "city". Is this what you mean by dynamic?
With your current design you will always need to compare the name of the field from the FieldInfo against a string.
What if you instead decouple this so that you hold the identifier to use for comparison purposes during reflection as part of the attribute.
Something like this:
public enum ReflectionFields
{
CITY = 0,
STATE,
ZIP,
COUNTRY
}
[AttributeUsage(AttributeTargets.Field,AllowMultiple=false)]
public class CustomFieldAttr : Attribute
{
public ReflectionFields Field { get; private set; }
public string MiscInfo { get; private set; }
public CustomFieldAttr(ReflectionFields field, string miscInfo)
{
Field = field;
MiscInfo = miscInfo;
}
}
public class Person
{
[CustomFieldAttr(ReflectionFields.CITY, "This is the primary city")]
public string _city = "New York";
public Person()
{
}
public Person(string city)
{
_city = city;
}
}
public static class AttributeReader<T> where T:class
{
public static void Read(T t)
{
//get all fields which have the "CustomFieldAttribute applied to it"
var fields = t.GetType().GetFields().Where(f => f.GetCustomAttributes(typeof(CustomFieldAttr), true).Length == 1);
foreach (var field in fields)
{
var attr = field.GetCustomAttributes(typeof(CustomFieldAttr), true).First() as CustomFieldAttr;
if (attr.Field == ReflectionFields.CITY)
{
//You have the field and you know its the City,do whatever processing you need.
Console.WriteLine(field.Name);
}
}
}
}
public class Program
{
public static void Main(string[] args)
{
PPerson p1 = new PPerson("NewYork");
PPerson p2 = new PPerson("London");
AttributeReader<PPerson>.Read(p1);
AttributeReader<PPerson>.Read(p2);
}
}
You can now freely rename _city field of Person to something else and your calling code will still work since the code using reflection is trying to identify the field using the ReflectionFields enum value set as part of initialization of the attribute set on the field.
Yes its possible !!!
Try this out...
public string DoSomething(object city)
{
return city.GetType().GetProperty("Name",typeof(string)).GetValue(city,null);
}
Two things here.
Number one, as someone above pointed out, you're getting the Type for string, not for Person. So typeof(Person).GetMembers() will get you the list of members.
Number two, and more importantly, it looks like you're misunderstanding the purpose of attributes. In general attributes are used to mark a member for specific processing or to add additional information. Here you're using the name to indicate what processing you want, and the attribute to specify parameters, which is mixing of metaphors, or something.
Abhijeet's answer is more appropriate, you mark the field as a city field, then do what you like with it. Where I disagree is that I would use different attribute classes, rather than an enumeration.
Something like:
public class MyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Field)]
public class MyCityAttribute : MyAttribute
{
}
[AttributeUsage(AttributeTargets.Field]
public class MyNameAttribute: MyAttribute
{
}
public class Person
{
[MyCity]
public string city = "New York";
[MyCity]
public string workCity = "Chicago";
[MyName]
public string fullName = "John Doe";
public Person()
{
}
public void DoSomething()
{
Type t = typeof(Person);
FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var field in fields)
{
MyAttribute[] attributes = field.GetCustomAttributes(typeof(MyAttribute));
if (attributes.Count > 0)
{
if (attributes[0] is MyCityAttribute)
{
//Dosomething for city
break;
}
if (attributes[0] is MyNameAttribute)
{
//Dosomething for names
break;
}
}
}
}
}
This would allow you to use different parameters for MyCity vs MyName that would make more sense in the context of processing each.
I think with your 'yuk' comment above, you hit the nail on the head. That you would have to change a string constant if you rename your variable is an indicator that you're doing something wrong.
t.GetField("city", BindingFlags.Public | BindingFlags.Instance);
or you can call GetFields() to get all fields
You need to call get type on the class Person. The iterate the fields of the class as in the answer below
This is not possible (I think it actually is but involes several hacks and using lambdas). If you want to store attributes about a Person and be able to get the name of the attribute easily, I suggest using a Dictionary<TKey, TValue> from the System.Collections.Generic namespace.
And you can always make public properties that wrap the dictionary.
public class Person
{
Dictionary<string, string> attributes = new Dictionary<string, string();
public string City
{
get { return attributes["city"]; }
set { attributes["city"] = value; }
}
public Person()
{
City = "New York";
}
}
And you can get a list of all attributes with attributes.Keys.
Have a look at this post as it looks similar to what you're trying to do:
Finding the variable name passed to a function
(especially Konrad Rudolph's answer) Another approach could be to just add "city" as one of the parameters in the attribute and fish that out later.
You are already looping through the collection of FieldInfo objects. Look for your attribute on those and when you find the FieldInfo that contains your attribute, you have the one you want. Then call .Name on it.
system.reflection.fieldinfo.attributes
How can I get the name of the original property name which is passed as a parameter to a method?
class TestA
{
public string Foo { get; set; }
public TestA()
{
Foo = "Bar";
TestB.RegisterString(Foo);
}
}
class TestB
{
public static void RegisterString(string inputString)
{
// Here I want to receive the property name that was used
// to assign the parameter input string
// I want to get the property name "Foo"
}
}
You can add an argument with the nameof keyword. Not sure why you would want that anyway:
TestB.RegisterString(Foo, nameof(Foo));
This will pass in "Foo" as the second argument. There is no way to automate this, so you don't need to call nameof yourself, which makes doing this quite useless.
If you would call this from the Foo property, you could use the CallerMemberNameAttribute, which will put in the caller's name. The compiler will set the correct value, so you don't have to supply this yourself in the calling method.
public static void RegisterString( string inputString
, [CallerMemberName] string caller = null
)
{
// use caller here
}
That makes more sense to me.
I want to slap a simple class together to pick out QueryString variables from an HTTP request that gets sent to my application. The variables are not always in the same order, but they're always there. I want to assign the variables in my class the values of the corresponding variables from the request, but I have no idea how to do this.
Code snippets:
MyHTTPRequest ar = new MyHTTPRequest("GET /submit.php?variableOne=value&variableTwo=someothervalue HTTP/1.1"); // Leaving out the rest for now
class MyHTTPRequest
{
public string variableOne;
public string variableTwo;
public string variableThree;
private string[] properties = { "variableOne", "variableTwo", "variableThree" }; // I know they're not actually properties
public MyHTTPRequest(string request)
{
string[] variablePars = request.Substring(16, request.Length - 24).Split('&'); // variablePars now contains "variableOne=value" & "variableTwo=someothervalue"
foreach (string variablePar in variablePars)
{
if (properties.Contains(variablePar.Split('=')[0])) // variableOne, variableTwo, variableThree
{
// Assign the correct variable the value
<???> = variablePar.Split('=')[1]; // I don't know how to pull this one off. variablePar.Split('=')[0] should contain the name of the variable.
}
}
}
}
Any input?
I'm sure a similar question already exists, but I did not know what to titel or tag this with.
Use the System.Web.HttpUtilityClass.ParseQueryString. It returns a NameValueCollection just like you get in ASP.NET with Request.QueryString.
// assuming you can parse your string to get your string to this format.
string queryStringText = "variableOne=value&variableTwo=someothervalue";
NameValueCollection queryString =
HttpUtility.ParseQueryString(queryStringText);
string variable1 = queryString["variableOne"];
string variable2 = queryString["variableTwo"];
Why not turn it around?
class MyHTTPRequest {
public string variableOne { get { return _values["variableOne"]; } }
public string variableTwo { get { return _values["variableTwo"]; } }
public string variableThree { get { return _values["variableThree"]; } }
NameValueCollection _values;
public MyHTTPRequest(string queryStringText) {
_values = HttpUtility.ParseQueryString(queryStringText);
}
}
You could use reflection to do this as follows:
PropertyInfo property = YourDtoClass.GetType().GetProperty("ThePropertyName");
if (property != null)
{
property.SetValue(theTargetObject, theValue);
}
Here we first get the property of the class where your properties are defined (via reflection and the property name). If a property is found with the desired name, we then set the property value on the target object.
Or using fields instead of properties:
FieldInfo field = YourDtoClass.GetType().GetField("theFieldName");
if (field != null)
{
field.SetValue(theTargetObject, theValue);
}
Update
This technique is only really safe (from a security perspective as others commented) if the target object that you are setting values on is purely a DTO, where all fields\properties are intended to be populated by query string values. This was the original viewpoint of my answer. If the target object contains fields that should not be set from query string values, then do not use this technique, as fields\properties that are not intended to be set from query string values, could be.
If your target object is a DTO, then the above is fine. I am assuming that this is the case.
http://msdn.microsoft.com/en-us/library/system.web.httprequest.querystring.aspx
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?
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;
}
}
Link to the presentation and code samples.
Also in SVN (more likely to be updated): http://gim-projects.googlecode.com/svn/presentations/CantDanceTheLambda
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
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.
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
}
Since you already have an explicit handle to the specific property you want, you know the name - can you just type it?
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);
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).