this is my code for example:
var output = new
{
NetSessionId = string.Empty
};
foreach (var property in output.GetType().GetProperties())
{
property.SetValue(output, "Test", null);
}
It occurs an exception: "Property set method not found". I want to know how to create an anonymous type with properties which can be set.
Thanks.
Anonymous type properties are read only and they cannot be set.
Anonymous types provide a convenient way to encapsulate a set of
read-only properties into a single object without having to explicitly
define a type first. The type name is generated by the compiler and is
not available at the source code level. The type of each property is
inferred by the compiler.
Anonymous Types (C# Programming Guide)
How to set value for property of an anonymous object?
Because I was reminded today that nothing is truly immutable when using reflection in combination with knowledge on how certain things are implemented (backing fields for the read-only properties of anonymous types in this case), I thought it wise to add an answer illustrating how the property values of an anonymous object can be changed, by mapping them to their backing fields.
This method relies on a specific convention used by the compiler for naming these backing fields: <xxxxx>i__Field in .NET and <xxxxx> on Mono, with the xxxxx representing the property name. If this convention were to change, the code below will fail (note: it will also fail if you try to feed it something that is not an anonymous type).
public static class AnonymousObjectMutator
{
private const BindingFlags FieldFlags = BindingFlags.NonPublic | BindingFlags.Instance;
private static readonly string[] BackingFieldFormats = { "<{0}>i__Field", "<{0}>" };
public static T Set<T, TProperty>(
this T instance,
Expression<Func<T, TProperty>> propExpression,
TProperty newValue) where T : class
{
var pi = (propExpression.Body as MemberExpression).Member;
var backingFieldNames = BackingFieldFormats.Select(x => string.Format(x, pi.Name)).ToList();
var fi = typeof(T)
.GetFields(FieldFlags)
.FirstOrDefault(f => backingFieldNames.Contains(f.Name));
if (fi == null)
throw new NotSupportedException(string.Format("Cannot find backing field for {0}", pi.Name));
fi.SetValue(instance, newValue);
return instance;
}
}
Sample:
public static void Main(params string[] args)
{
var myAnonInstance = new {
FirstField = "Hello",
AnotherField = 30,
};
Console.WriteLine(myAnonInstance);
myAnonInstance
.Set(x => x.FirstField, "Hello SO")
.Set(x => x.AnotherField, 42);
Console.WriteLine(myAnonInstance);
}
With output:
{ FirstField = Hello, AnotherField = 30 }
{ FirstField = Hello SO, AnotherField = 42 }
A slightly more elaborate version can be found here
If you ever come across a situation where you need a mutable type, instead of messing around with the Anonymous type, you can just use the ExpandoObject:
Example:
var people = new List<Person>
{
new Person { FirstName = "John", LastName = "Doe" },
new Person { FirstName = "Jane", LastName = "Doe" },
new Person { FirstName = "Bob", LastName = "Saget" },
new Person { FirstName = "William", LastName = "Drag" },
new Person { FirstName = "Richard", LastName = "Johnson" },
new Person { FirstName = "Robert", LastName = "Frost" }
};
// Method syntax.
var query = people.Select(p =>
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}); // or people.Select(p => GetExpandoObject(p))
// Query syntax.
var query2 = from p in people
select GetExpandoObject(p);
foreach (dynamic person in query2) // query2 or query
{
person.FirstName = "Changed";
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
// Used with the query syntax in this example, but may also be used
// with the method syntax just as easily.
private ExpandoObject GetExpandoObject(Person p)
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}
I came here being curious about Anonymous Types, and turned out learning a lot from the answers given.
In my answer i will try to synthesize some valuable information i found, and provide information that i did not see in the other answers and that i think will also worth to read for future visitors.
Why is not possible to re-set (out of the box) the values of an anonymously type object?
To better understand the why, it is worth to read what #EricLippert said in a comment to another question about Anonymous Types:
Note that anonymous types in VB are allowed to be partially mutated. In VB you get to state which parts of the anonymous type are mutable; the generated code will not use mutable bits as part of a hash code / equality, so you don't get the "lost in the dictionary" problem. We decided to not implement these extensions in C#.
Plus the text cited by the Accepted Answer from the official C# documentation:
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
And just to justify a bit the why it is not possible (out of the box) to set the value of a anonymously typed object, let's see what C# in a Nutshell says:
[If you define]
var dude = new { Name = "Bob", Age = 23 };
The compiler translates this to (approximately) the following:
internal class AnonymousGeneratedTypeName
{
private string name; // Actual field name is irrelevant
private int age; // Actual field name is irrelevant
public AnonymousGeneratedTypeName(string name, int age)
{
this.name = name; this.age = age;
}
public string Name { get { return name; } }
public int Age { get { return age; } }
// The Equals and GetHashCode methods are overriden...
// The ToString method is also overriden.
}
...
var dude = AnonymousGeneratedTypeName ("Bob", 23);
But, is it true that once you set the value of an Anonymous Type it is not possible to modify it?
Well, as we can learn from the answer given by #Alex:
nothing is truly immutable when using reflection in combination with knowledge on how certain things are implemented (backing fields for the read-only properties of anonymous types in this case).
If you are curious to see HOW you can modify the value of an anonymously typed object, go and read his answer, it is really worth!
If at the end, you what to stick with the simplicity in the one liner
var dude = new { Name = "Bob", Age = 23 };
and want to be able to modify latter one of dude's properties, you can (in many cases) simply change the var keyword by dynamic. Then you can do
dynamic dude = new { Name = "Bob", Age = 23 };
dude.Name = "John"; // Compiles correctly.
But watch out! var and dynamic are not as similar as they seem at a first look. As already noted in a comment to #B.K. by #MikeBeaton
this doesn't work in the case where you need a typed null value? (i.e. an ExpandoObject can't support that, but an anonymous type can)
There are some SO posts about dynamic vs var.
A suggestion: you can set all properties at once.
The other answers correctly suggest that they are immutable objects (although Alex's answer does show how to get at the backing fields, which is a good, yet messy answer) but they do have constructors exposed, so you can create new instances.
Below, the example takes a template instance and creates new instances of it in the CreateFromAnonymousTemplate function. There are downsides, but the biggest benefit (aside from being able to create these objects!) is that you are sticking to the convention that anonymous types should be immutable.
class Program
{
static void Main(string[] args)
{
// Create a template that defines the anonymous type properties.
var personTemplate = new { Name = "", Age = 0 };
var sam = CreateFromAnonymousTemplate(personTemplate, "Sam", 43);
var sally = CreateFromAnonymousTemplate(personTemplate, "Sally", 24);
}
private static Dictionary<Type, ConstructorInfo> _constructors = new Dictionary<Type, ConstructorInfo>();
// By using T, we get intellisense for our returned objects.
static T CreateFromAnonymousTemplate<T>(T templateReference, params object[] propertyValues)
{
// This is the type of the template. In this case, the anonymous type.
Type anonymousType = templateReference.GetType();
ConstructorInfo anonymousTypeConstructor;
if (_constructors.ContainsKey(anonymousType))
{
anonymousTypeConstructor = _constructors[anonymousType];
if(anonymousTypeConstructor.GetParameters().Length != propertyValues.Length)
throw new ArgumentException("Invalid initialisation properties. Parameters must match type and order of type constructor.", "propertyValues");
}
else
{
PropertyInfo[] properties = anonymousType.GetProperties();
if (properties.Count() != propertyValues.Length)
throw new ArgumentException("Invalid initialisation properties. Parameters must match type and order of type constructor.", "propertyValues");
// Retrieve the property types in order to find the correct constructor (which is the one with all properties as parameters).
Type[] propertyTypes = properties.Select(p => p.PropertyType).ToArray();
// The constructor has parameters for each property on the type.
anonymousTypeConstructor = anonymousType.GetConstructor(propertyTypes);
// We cache the constructor to avoid the overhead of creating it with reflection in the future.
_constructors.Add(anonymousType, anonymousTypeConstructor);
}
return (T)anonymousTypeConstructor.Invoke(propertyValues);
}
}
I had a similar scenario where I needed to assign an error code and message to numerous object types that all SHARE specific nested properties so I don't have to duplicate my methods for reference hoping it helps someone else:
public T AssignErrorMessage<T>(T response, string errorDescription, int errorCode)
{
PropertyInfo ErrorMessagesProperty = response.GetType().GetProperty("ErrorMessage");
if (ErrorMessagesProperty.GetValue(response, null) == null)
ErrorMessagesProperty.SetValue(response, new ErrorMessage());
PropertyInfo ErrorCodeProperty = ErrorMessagesProperty.GetType().GetProperty("code");
ErrorCodeProperty.SetValue(response, errorCode);
PropertyInfo ErrorMessageDescription = ErrorMessagesProperty.GetType().GetProperty("description");
ErrorMessageDescription.SetValue(response, errorDescription);
return response;
}
public class ErrorMessage
{
public int code { get; set; }
public string description { get; set; }
}
An easy way could be to serialize the anonymous object in a Json with NewtonSoft'JsonConverter (JsonConvert.SerializeObject(anonObject)). Then you can change the Json via string manipulation and reserialize it into a new anonymous object that you can assign to the old variable.
A little convolute but really easy to understand for beginners!
Anonymous types are immutable in C#. I don't think you can change the property there.
Related
this is my code for example:
var output = new
{
NetSessionId = string.Empty
};
foreach (var property in output.GetType().GetProperties())
{
property.SetValue(output, "Test", null);
}
It occurs an exception: "Property set method not found". I want to know how to create an anonymous type with properties which can be set.
Thanks.
Anonymous type properties are read only and they cannot be set.
Anonymous types provide a convenient way to encapsulate a set of
read-only properties into a single object without having to explicitly
define a type first. The type name is generated by the compiler and is
not available at the source code level. The type of each property is
inferred by the compiler.
Anonymous Types (C# Programming Guide)
How to set value for property of an anonymous object?
Because I was reminded today that nothing is truly immutable when using reflection in combination with knowledge on how certain things are implemented (backing fields for the read-only properties of anonymous types in this case), I thought it wise to add an answer illustrating how the property values of an anonymous object can be changed, by mapping them to their backing fields.
This method relies on a specific convention used by the compiler for naming these backing fields: <xxxxx>i__Field in .NET and <xxxxx> on Mono, with the xxxxx representing the property name. If this convention were to change, the code below will fail (note: it will also fail if you try to feed it something that is not an anonymous type).
public static class AnonymousObjectMutator
{
private const BindingFlags FieldFlags = BindingFlags.NonPublic | BindingFlags.Instance;
private static readonly string[] BackingFieldFormats = { "<{0}>i__Field", "<{0}>" };
public static T Set<T, TProperty>(
this T instance,
Expression<Func<T, TProperty>> propExpression,
TProperty newValue) where T : class
{
var pi = (propExpression.Body as MemberExpression).Member;
var backingFieldNames = BackingFieldFormats.Select(x => string.Format(x, pi.Name)).ToList();
var fi = typeof(T)
.GetFields(FieldFlags)
.FirstOrDefault(f => backingFieldNames.Contains(f.Name));
if (fi == null)
throw new NotSupportedException(string.Format("Cannot find backing field for {0}", pi.Name));
fi.SetValue(instance, newValue);
return instance;
}
}
Sample:
public static void Main(params string[] args)
{
var myAnonInstance = new {
FirstField = "Hello",
AnotherField = 30,
};
Console.WriteLine(myAnonInstance);
myAnonInstance
.Set(x => x.FirstField, "Hello SO")
.Set(x => x.AnotherField, 42);
Console.WriteLine(myAnonInstance);
}
With output:
{ FirstField = Hello, AnotherField = 30 }
{ FirstField = Hello SO, AnotherField = 42 }
A slightly more elaborate version can be found here
If you ever come across a situation where you need a mutable type, instead of messing around with the Anonymous type, you can just use the ExpandoObject:
Example:
var people = new List<Person>
{
new Person { FirstName = "John", LastName = "Doe" },
new Person { FirstName = "Jane", LastName = "Doe" },
new Person { FirstName = "Bob", LastName = "Saget" },
new Person { FirstName = "William", LastName = "Drag" },
new Person { FirstName = "Richard", LastName = "Johnson" },
new Person { FirstName = "Robert", LastName = "Frost" }
};
// Method syntax.
var query = people.Select(p =>
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}); // or people.Select(p => GetExpandoObject(p))
// Query syntax.
var query2 = from p in people
select GetExpandoObject(p);
foreach (dynamic person in query2) // query2 or query
{
person.FirstName = "Changed";
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
// Used with the query syntax in this example, but may also be used
// with the method syntax just as easily.
private ExpandoObject GetExpandoObject(Person p)
{
dynamic exp = new ExpandoObject();
exp.FirstName = p.FirstName;
exp.LastName = p.LastName;
return exp;
}
I came here being curious about Anonymous Types, and turned out learning a lot from the answers given.
In my answer i will try to synthesize some valuable information i found, and provide information that i did not see in the other answers and that i think will also worth to read for future visitors.
Why is not possible to re-set (out of the box) the values of an anonymously type object?
To better understand the why, it is worth to read what #EricLippert said in a comment to another question about Anonymous Types:
Note that anonymous types in VB are allowed to be partially mutated. In VB you get to state which parts of the anonymous type are mutable; the generated code will not use mutable bits as part of a hash code / equality, so you don't get the "lost in the dictionary" problem. We decided to not implement these extensions in C#.
Plus the text cited by the Accepted Answer from the official C# documentation:
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
And just to justify a bit the why it is not possible (out of the box) to set the value of a anonymously typed object, let's see what C# in a Nutshell says:
[If you define]
var dude = new { Name = "Bob", Age = 23 };
The compiler translates this to (approximately) the following:
internal class AnonymousGeneratedTypeName
{
private string name; // Actual field name is irrelevant
private int age; // Actual field name is irrelevant
public AnonymousGeneratedTypeName(string name, int age)
{
this.name = name; this.age = age;
}
public string Name { get { return name; } }
public int Age { get { return age; } }
// The Equals and GetHashCode methods are overriden...
// The ToString method is also overriden.
}
...
var dude = AnonymousGeneratedTypeName ("Bob", 23);
But, is it true that once you set the value of an Anonymous Type it is not possible to modify it?
Well, as we can learn from the answer given by #Alex:
nothing is truly immutable when using reflection in combination with knowledge on how certain things are implemented (backing fields for the read-only properties of anonymous types in this case).
If you are curious to see HOW you can modify the value of an anonymously typed object, go and read his answer, it is really worth!
If at the end, you what to stick with the simplicity in the one liner
var dude = new { Name = "Bob", Age = 23 };
and want to be able to modify latter one of dude's properties, you can (in many cases) simply change the var keyword by dynamic. Then you can do
dynamic dude = new { Name = "Bob", Age = 23 };
dude.Name = "John"; // Compiles correctly.
But watch out! var and dynamic are not as similar as they seem at a first look. As already noted in a comment to #B.K. by #MikeBeaton
this doesn't work in the case where you need a typed null value? (i.e. an ExpandoObject can't support that, but an anonymous type can)
There are some SO posts about dynamic vs var.
A suggestion: you can set all properties at once.
The other answers correctly suggest that they are immutable objects (although Alex's answer does show how to get at the backing fields, which is a good, yet messy answer) but they do have constructors exposed, so you can create new instances.
Below, the example takes a template instance and creates new instances of it in the CreateFromAnonymousTemplate function. There are downsides, but the biggest benefit (aside from being able to create these objects!) is that you are sticking to the convention that anonymous types should be immutable.
class Program
{
static void Main(string[] args)
{
// Create a template that defines the anonymous type properties.
var personTemplate = new { Name = "", Age = 0 };
var sam = CreateFromAnonymousTemplate(personTemplate, "Sam", 43);
var sally = CreateFromAnonymousTemplate(personTemplate, "Sally", 24);
}
private static Dictionary<Type, ConstructorInfo> _constructors = new Dictionary<Type, ConstructorInfo>();
// By using T, we get intellisense for our returned objects.
static T CreateFromAnonymousTemplate<T>(T templateReference, params object[] propertyValues)
{
// This is the type of the template. In this case, the anonymous type.
Type anonymousType = templateReference.GetType();
ConstructorInfo anonymousTypeConstructor;
if (_constructors.ContainsKey(anonymousType))
{
anonymousTypeConstructor = _constructors[anonymousType];
if(anonymousTypeConstructor.GetParameters().Length != propertyValues.Length)
throw new ArgumentException("Invalid initialisation properties. Parameters must match type and order of type constructor.", "propertyValues");
}
else
{
PropertyInfo[] properties = anonymousType.GetProperties();
if (properties.Count() != propertyValues.Length)
throw new ArgumentException("Invalid initialisation properties. Parameters must match type and order of type constructor.", "propertyValues");
// Retrieve the property types in order to find the correct constructor (which is the one with all properties as parameters).
Type[] propertyTypes = properties.Select(p => p.PropertyType).ToArray();
// The constructor has parameters for each property on the type.
anonymousTypeConstructor = anonymousType.GetConstructor(propertyTypes);
// We cache the constructor to avoid the overhead of creating it with reflection in the future.
_constructors.Add(anonymousType, anonymousTypeConstructor);
}
return (T)anonymousTypeConstructor.Invoke(propertyValues);
}
}
I had a similar scenario where I needed to assign an error code and message to numerous object types that all SHARE specific nested properties so I don't have to duplicate my methods for reference hoping it helps someone else:
public T AssignErrorMessage<T>(T response, string errorDescription, int errorCode)
{
PropertyInfo ErrorMessagesProperty = response.GetType().GetProperty("ErrorMessage");
if (ErrorMessagesProperty.GetValue(response, null) == null)
ErrorMessagesProperty.SetValue(response, new ErrorMessage());
PropertyInfo ErrorCodeProperty = ErrorMessagesProperty.GetType().GetProperty("code");
ErrorCodeProperty.SetValue(response, errorCode);
PropertyInfo ErrorMessageDescription = ErrorMessagesProperty.GetType().GetProperty("description");
ErrorMessageDescription.SetValue(response, errorDescription);
return response;
}
public class ErrorMessage
{
public int code { get; set; }
public string description { get; set; }
}
An easy way could be to serialize the anonymous object in a Json with NewtonSoft'JsonConverter (JsonConvert.SerializeObject(anonObject)). Then you can change the Json via string manipulation and reserialize it into a new anonymous object that you can assign to the old variable.
A little convolute but really easy to understand for beginners!
Anonymous types are immutable in C#. I don't think you can change the property there.
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
I have an ICollection with objects:
private ObservableCollection<ViewItem> items;
The viewItems have no properties. The data will be accessed via an index with
public object this[int index] {
get{ .... }
set {....}
}
I have a geneal class for filtering. The linq with properies will work fine. I use (the important code only):
Queryable = CreateQueryable((IEnumerable<object>)mItemsSource.SourceCollection, ItemType);
mQuery = Queryable.Where(filterString).Cast<object>();
ilteredCollection = mQuery.ToList();
with:
private static IQueryable CreateQueryable(IEnumerable<object> collection, Type itemType)
{
if (itemType == null) return null;
var queryableList = collection.AsQueryable();
return queryableList.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Cast",
new Type[] { itemType },
queryableList.Expression));
}
So I can use a filter string like: Id>10 or Name="abc"
where Id and Name are property names.
But I have also Object in another collection which only have access via index. so I have an where string like:
[0]>10 or [1]="abc"
I didn't find any solution. The only hint I could find is to use:
new(it([idx] as Type)
where idx is element index and Type is a type of this element
e.g.
[0]>10 --> new(it[0] as object)>10
But than I get the error:
{"Operator '=' incompatible with operand types 'DynamicClass1' and 'Int32'"}
Useing a string in my filter like:
new(it[0] as object)>"10"
than the error is:
{"Operator '=' incompatible with operand types 'DynamicClass1' and 'string'"}
So - how can I solve this problem. Because this is a general Filterclass I also don't know the type. So in the as statement I can only use object or something like this.
I hope anyone can help me. Perhaps the dynamic keyword of C# 4.0 will help??
BTW a workaround will be to impement a wrapper in each class with indexer, but this will be a lot of stupid work. And that is something a real programmer don't like ;). I am sure there is a solution!
Cheer up !!
First of all -- How to access Current Instance ?
When parsing a lambda expression with a single unnamed parameter, the members of the unnamed parameter are automatically in scope in the expression string, and the current instance given by the unnamed parameter can be referenced in whole using the keyword it. For example,
customers.Where("Country = #0", country);
is equivalent to
customers.Where("it.Country = #0", country);
Above concept has been explained here.
From above explanation, we can now access the indexer property as it[#0] where #0 is value of index to be passed, as explained below.
//Consider below class
public class Product
{
private NameValueCollection collection = new NameValueCollection();
public string Company { get; set; }
public string Distributor { get; set; }
public int ID { get; set; }
...
public string this[string index]
{
get { return collection[index]; }
set { if(!string.IsNullOrEmpty(value)) collection[index]=value; }
}
}
//Main Code
List<Product> list = new List<Product>();
Product product = new Product() { Company = "Nestle", Distributor = "xyz", ID = 1 };
product["Name"] = "Maggi";
list.Add(product);
var filteredList = list.AsQueryable().Where("it[#0]=#1", "Name", "Maggi"); //Accessing the current item by indexer property
foreach (Product productItem in filteredList)
{
Console.WriteLine(productItem.Company);
}
Hope this helps you !! :)
Your usage of new keyword is wrong.
It does not cast object (nor does as).
Keyword new is used to create new object of anonymous class with the specified properties.
Thus new(it[idx] as Type) will create new object with property Type having the value it[idx]. It is equivalent to C#'s: new { Type = this[idx] }.
As I have already pointed out in Dynamic linq: Is there a way to access object data by index?, you need to cast it in the following manner: Int32(it[0]) > 10 for your pseudo-query [0] > 10.
I have a class that used to have a string return type. Now I find I need to return more than a string. I was thinking to return something like below:
public string Test()
{
return ( new { ID = 5, Name= "Dave" } );
}
Is this even possible and if so then what would be the return type? I know it's not string ..
As others have said, the best thing to do here is to make a nominal type. I would suggest that the nominal type have the same characteristics as an anonymous type; that is, you should consider making the type immutable and consider making it exhibit value equality.
It is possible to return an anonymous type as object and then use the instance returned elsewhere using a variety of sneaky techniques. You can cast the object to "dynamic" (in C# 4) and then use the properties of the anonymous type, but this is slow and lacks compile-time type checking.
You can also use the "cast by example" trick, which does get you compile-time type checking. However, that trick only works when the anonymous source object and the anonymous example object come from the same assembly.
static T CastByExample<T>(object source, T example) where T : class
{
return source as T;
}
static object ReturnsAnonymous() { return new { X = 123 }; }
static void DoIt()
{
object obj = ReturnsAnonymous();
var example = new { X = 0 };
var anon = CastByExample(obj, example);
Console.WriteLine(anon.X); // 123
}
See how sneaky that is? We use method type inference and local variable type inference to tell the compiler "these two things are the same type". This lets you export an anonymous type as object and cast it back to anonymous type.
But you probably should not do this; if you're resorting to such sneaky tricks then you should simply be defining a nominal type in the first place. Also, like I said, the trick only works if the example and the source objects were created in code in the same assembly; two "identical" anonymous types in two different assemblies do not unify to be the same type.
The object that you return does have a class, but it's anonymous so you can't specify it in the code. You just have to return it as an object reference:
public object Test() {
return new { ID = 5, Name= "Dave" };
}
Note that the anonymous type is unknown outside the scope of the method, so reflection is the only way to access its properties.
If you want to be able to use the returned object conveniently, you should declare a class:
public class TestResult
{
public int ID { get; set; }
public string Name { get; set; }
}
public TestResult Test() {
return new TestResult() { ID = 5, Name= "Dave" };
}
Another alternative is to use an existing class, if it fits your purpose. A KeyValuePair is close to what you use, but then the properties will of course be named Key and Value instead of ID and Name:
public KeyValuePair<int, string> Test() {
return new KeyValuePair<int, string>(5, "Dave");
}
This isn't possible as the anonymous class is only valid within the current context. If you need to return an object then you'll need to create a real class.
I'm assuming you left string as the return type by accident.
Anonymous type are class type that are derived directly from object.
You can return it from method as object as return type.
Have a look at this.
No, it's not possible. Your options are:
Define a real class for the return value,
Use System.Tuple, or
Use out parameters (probably the least good option).
You can make a struct (or class) for this.
public struct IdAndName
{
public int Id;
public string Name;
public IdAndName(int id, string name)
{
ID = id;
Name = name;
}
}
You could also use a Tuple<T1, T2>, (but that's not recommended as the properties aren't named.
class NewString
{
public int ID { get; set; }
public string Name { get; set; }
}
public NewString Test()
{
return ( new NewString() { ID = 5, Name = "Dave" } );
}
:)
Consider this:
var me = new { FirstName = "John", LastName = "Smith" };
This is fine as we can then do this:
Console.WriteLine("{0} {1}", me.FirstName, me.LastName);
However we can't do this:
public T GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
because we don't know the type of T.
We could do this:
public object GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
but then we'd have to inspect the properties of the object using reflection in order to access them:
var p = new Prog();
object o = p.GetMe();
Type t = o.GetType();
foreach (var prop in t.GetProperties())
{
Console.WriteLine(prop.Name + ": " + prop.GetValue(o, null));
}
However what about if we could name an anonymous type as we define it? Of course it would no longer be anonymous, however it would be more succinct and maintainable than a normal class definition.
Consider this:
public Person GetMe()
{
return new public class Person { FirstName = "John", LastName = "Smith" };
}
The benefit being it would then be possible to return the result of a complicated Linq query from a method without having to define the class explicitly.
Consider this relatively complex Linq query:
List<int> list = new List<int>();
var query = from number in list
select
new
{
Number = number,
Square = number*number,
Absolute = Math.Abs(number),
Range = Enumerable.Range(0, number)
};
Instead of defining a class like so:
public class MyNumbers
{
public int Number { get; set; }
public int Square { get; set; }
public int Absolute { get; set; }
public IEnumerable<int> Range { get; set; }
}
in order to return the query variable from a method we could instead just do this:
List<int> list = new List<int>();
return from number in list
select new public class MyNumbers
{
Number = number,
Square = number*number,
Absolute = Math.Abs(number),
Range = Enumerable.Range(0, number)
};
Actually, there's a "hack" that you can do to get an anonymous type back from a method. Consider this:
public object MyMethod()
{
var myNewObject = new
{
stringProperty = "Hello, World!",
intProperty = 1337,
boolProperty = false
};
return myNewObject;
}
public T Cast<T>(object obj, T type)
{
return (T)obj;
}
You can now do this:
var obj = MyMethod();
var myNewObj = Cast(obj, new { stringProperty = "", intProperty = 0, boolProperty = false });
The myNewObj will now be an object of the same Type as the anonymous type.
The language feature you need is:
public var GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
That is, var would be valid as a method return type, and the compiler would infer the actual type from whatever is returned. You would then have to do this at the call site:
var me = GetMe();
Any two anonymous types with members of the same type would be the same type, so if you wrote other functions returning the same pattern, they would have the same type. For any types A and B where B has a subset of the members of A, then A is assignment-compatible with B (B is like a base class of A). If you wrote:
public var GetMeFrom(var names)
{
return new { FirstName = names["First"], LastName = names["Last"] };
}
The compiler would effectively define this as a generic method with two type parameters, T1 being the type of names and T2 being the type returned by the indexer on T1 that accepts a string. T1 would be constrained so that it must have an indexer that accepts a string. And at the call site you would just pass anything that had an indexer that accepted a string and returned any type you like, and that would determine the type of FirstName and LastName in the type returned by GetMeFrom.
So type inference would figure all this out for you, automatically capturing whatever type constraints are discoverable from the code.
IMHO the root problem is nothing to do with anonymous types, but that declaring a class is too verbose.
Option 1:
If you could declare a class like this:
public class MyClass
{ properties={ int Number, int Square, int Absolute, IEnumerable<int> Range } }
or some other similarly quick way (like the tuple example) then you wouldn't feel the need to do hacky things with anonymous types just to save some code.
When 'compiler as a service' arrives in C#5, hopefully they'll do a good job of integrating it and we'll be able to use metaprogramming to solve these kinds of problems cleanly. Party like it's 1958!
Option 2:
Alternatively, in C#4, you could just pass an anonymous type around as dynamic and avoid all the casting. Of course this opens you up to runtime errors if you rename a variable, etc.
Option 3:
If C# would implement generics in the same way as C++, then you could pass the anonymous type into a method, and so long as it had the right members, it would just compile. You'd get all the benefits of static type safety, and none of the downsides. Every time I have to type where T : ISomething in C# I get annoyed that they didn't do this!
What you are describing (named anonymous types) are basically "tuple types".
I think they would be a nice addition to C#.
If I were designing such a feature for C#, I would expose it using syntax like this:
tuple<int x, int y>
so that you could do:
public tuple<int x, int y> GetStuff()
{
}
I would then change the definition of anonymous types, so that:
new { x = 2, y = 2}
had tuple<int x, int y> as it's type, rather than an anonymous type.
Getting this to work with the current CLR is a little tricky, because once you can name an anonymous type in public signatures you need to be able to unify them across separately compiled assemblies. It can be accomplished by embedding a "module constructor" inside any assembly that uses a tuple type. See this post for an example.
The only downside to that approach is that it doesn't respect the CLR's "lazy" model for type generation. That means that assemblies that use many distinct tuple types might experience slightly slower load types. A better approach would be to add support for tuple types directly to the CLR.
But, apart from changing the CLR, I think the module constructor approach is the best way of doing something like this.
I would love this feature, there have been many times I've wanted this.
A good example is processing XML. You parse them get back an object, but then you need to make a concrete version of the object to send back to a caller. Many times you get XML that changes quite considerably and requires you make many classes to handle it. Wouldn't it be wonderful if you could just build the object using LinqToXml as a var, then just return that?
I think this would be a nice compiler magic for tuples:
Creating a tuple:
(int, string, Person) tuple = (8, "hello", new Person());
equivalent to:
Tuple<int,string,Person> tuple = new Tuple<int,string,Person>(8 ,"hello", new Person());
In a function:
public (int, string, Person) GetTuple(){
return ...
}
Getting values:
int number = tuple[1];
string text = tuple[2];
Person person = tuple[3];
Could you create an Interface with the properties FirstName and LastName and use that?