How to create properties automatically? - c#

I have a "settings" class, which has some properties for usability and to restrict set accessor. It seems easy while i had within ten items, but then their count was increased. I need some way to create these properties automatically, something like that:
foreach(var property in SettingsList)
{
_settings.AddAutoProperty(property);
}
It may have deal with reflection, but i can't get to efficient solution.
The properties definition:
public bool cbNextExcCount
{
get { return (bool)this.GetValueById("cbNextExcCount"); }
}
public bool cbSaveOnChangeExc
{
get { return (bool)this.GetValueById("cbSaveOnChangeExc"); }
}
public bool cbAutoIncrement
{
get { return (bool)this.GetValueById("cbAutoIncrement"); }
}
public bool cbRememberOnExit
{
get { return (bool)this.GetValueById("cbRememberOnExit"); }
}
...etc.
UPDATE
To summ up, i wrote the next code:
public IDictionary<string, object> Properties = new ExpandoObject();
private List<string> SettingsList = new List<string>
{
"cbNextExcCount",
"cbSaveOnChangeExc",
"cbAutoIncrement",
"cbRememberOnExit"
};
public void CreateProperties()
{
foreach (string SettingName in SettingsList)
{
Properties.Add(SettingName, () => this.GetValueById(SettingName));
}
}
But i have an error on () => this.GetValueById("cbNextExcCount")):
argument type 'lambda expression' is not assignable to parameter type 'object'.
I can store Func<bool>, but settings may have other type than bool and if i use Func, it's get a bit more complicate to call.

You can't create auto-properties, but you can use an ExpandoObject.
I'm not sure if this is what you're looking for, because using expandos means using duck typing (i.e. dynamic programming).
ExpandoObject sample:
dynamic expando = new ExpandoObject();
expando.PropertyA = "Hello";
expando.PropertyB = "world!";
An interesting thing about expandos is that ExpandoObject implements IDictionary<string, object>, meaning that you can upcast any expando to this type and iterate over its added properties, which could be great for storing run-time created settings.
UPDATE
I was thinking more about a good solution and if SettingList is a custom class developed by yourself, maybe you can add a property called Custom to SettingList and add there settings that aren't added during design-time.
UPDATE 2
In your case, instead of storing the actual value of something, you could add Func<bool> to ExpandoObject's run-time settings:
IDictionary<string, object> settings = new ExpandoObject();
settings.Add("cbNextExcCount", () => this.GetValueById("cbNextExcCount"));
Actually, I don't know this scope in your code sample, but change this to anything that could be an instance of SettingList or whatever.
Once you've added run-time settings, you can type settings variable to dynamic typing in order to access properties like this:
dynamic allSettings = (dynamic)settings;
bool cbNextExcCount = allSettings.cbNextExcCount();

You can consider Expando Objects in System.Dynamic namespace. This article can be a good start.

Related

C# How to init property (without setter) by reflection

Task:
Serialize a list of objects into a byte[] using protobuf.
Without reflection all is good
.proto
message MyObject{
int32 id = 1;
int32 value = 2;
}
message MyObjects {
repeated MyObject objects = 1;
}
.cs
public static byte[] ToByteArray(List<MyObject> obj) {
var objects = new MyObjects {
Objects = {obj}
};
return objects.ToByteArray();
}
Since I need to serialize many different types in this way, I want to write a universal method using reflection.
Problem:
Protobuf itself generates entities and properties for them, but it does not create a setter for RepeatedField, which means that I can not set the value using GetProperty("Objects")?.SetValue(objects, obj). System.ArgumentException: Set Method not found for 'Objects'
.cs (protobuf generated)
public pbc::RepeatedField<global::Test.MyObject> Objects {
get { return objects_; }
}
.cs
public static byte[] ToByteArray<T, E>(List<T> obj) where T : IMessage where E : IMessage {
var objects = Activator.CreateInstance<E>();
objects.GetType().GetProperty("Objects")?.SetValue(objects, obj);
return objects.ToByteArray();
}
Question:
How to use reflection to set values ​​for a property during object creation, just as I do it without reflection?
How to write this "new MyObjects {Objects = {obj}}; (where obj: IEnumerable)" using reflection
Various conclusions:
I noticed that filling properties that do not have a setter is only possible for collections and only when creating an object.
Most likely I need an alternative way to instantiate the class. Activator.CreateInstance() is not fulfilling my task.
When we do this:
var x = new Thing
{
SomeProperty = "x",
SomeOtherProperty = 1
}
we aren't setting the values during object creation. This is the equivalent of:
var x = new Thing();
x.SomeProperty = "x";
x.SomeOtherProperty = 1;
In both cases the properties are set after the object is instantiated by setting their properties. An easy way to verify this is to try using the syntax from the first example to set a property that doesn't have a setter. It won't compile. You'll see this error:
Property or indexer 'Thing.SomeProperty' cannot be assigned to -- it is read-only.
In other words, the object, as defined, does not provide a way to set the Objects property.
The question is whether you really need to set the property. Quite likely you only need to add items to the collection.
Doing this with reflection is still really ugly. I don't recommend this at all. This is a crude version. It can fail at runtime for all sorts of reasons.
public static byte[] ToByteArray<T, E>(List<T> itemsToAdd) where T : IMessage where E : IMessage
{
// create an instance of the object
var created = Activator.CreateInstance<E>();
// Find the "Objects" property. It could be null. It could be the wrong type.
var objectsProperty = typeof(E).GetProperty("Objects");
// Get the value of the objects property. Hopefully it's the type you expect it to be.
var collection = objectsProperty.GetValue(created);
// Get the Add method. This might also be null if the method doesn't exist.
var addMethod = collection.GetType().GetMethod("Add");
// invoke the Add method for each item in the collection
foreach(var itemToAdd in itemsToAdd)
{
addMethod.Invoke(collection, new object[] { itemToAdd });
}
return created.ToByteArray();
}
Unless we're forced to, we really don't want to do that. I don't know what your IMessage type look like.
Does it have the Objects property?
In that case you could just do this:
public static byte[] ToByteArray<T, E>(List<T> itemsToAdd)
where T : IMessage
where E : IMessage, new()
{
var created = new E();
foreach (var itemToAdd in itemsToAdd)
{
created.Objects.Add(itemToAdd);
}
// or skip the foreach and just do
// created.Objects.AddRange(itemToAdd);
return created.ToByteArray();
}
I'm guessing about whether your interface has that property. But if at all possible, you're better off doing this with generic constraints than with reflection. This way your code is checked for most possible errors when it compiles, as opposed to running it and having it blow up because this or that property or method doesn't exist, is wrong, etc.
The new() constraint simply means that E must be a type with a default constructor, which means that in order for it to compile, E must be a type you can create without passing anything to the constructor. (Without that constraint, new E() won't compile.)
Without that constraint even Activator.CreateInstance might fail because the the type might not have a default constructor.
Scott's answer solves the problem, but I used a shortened solution in the end
private static byte[] ToByteArray<T, E>(IEnumerable<T> obj) where T : IMessage where E : IMessage, new() {
var objects = new E();
(objects.GetType().GetProperty("Objects")?.GetValue(objects) as RepeatedField<T>)?.AddRange(obj);
return objects.ToByteArray();
}

Generic function that takes properties as parameters

I want to write a generic function that takes an object and a series of properties of this object. Inside the function I would like to select a new anonymous object that is simply just those properties of the passed in object.
I want to do something like this:
public class SimpleClass
{
public DateTime ADate {get; set;}
public string StringHere {get; set;}
public int ANumber {get; set;}
}
var testObj = new SimpleClass();
// set values here on testObj properties
DoStuffHere(testObj, StringHere, ANumber);
I could pass in the properties as strings and then use reflection to get the properties from the passed in object, but I wanted to know if there was some way I could pass in the properties themselves so I could have intellisense and compile time checking to prevent bad property names. I would like my getNewClass function to take any type of object, and such, be generic.
Edit: I am not returning a new anonymous type. I think my function name was making it sound that way. I am going to be selecting a new anonymous type internally from a list of that specified testObj and generating a PDF from those properties.
Defining an anonymous type is actually very complicated, and trying to do it just with the names is somewhat challenging. Essentially what you want already exists, but in regular C# - so for a single object:
var obj = new { testObj.StringHere, testObj.ANumber };
Or for multiple objects:
var projection = from obj in sequence
select new { obj.StringHere, obj.ANumber };
That's about as succinct as you'll get. You could add a generic method that took a Func<,> of some kind, but it wouldn't be any cleaner than the above.
It isn't useful to have:
var obj = SomeMagicMethod(obj, "StringHere", "ANumber");
because SomeMagicMethod could only usefully return object - our obj variable would be largely unusable.
If you don't need to return the object from the method, then you could use either of:
SomeMagicMethod<T>(T value) {
...
}
...
SomeMagicMethod(new {testObj.StringHere, testObj.ANumber });
or:
SomeMagicMethod<TFrom, TTo>(TFrom value, Func<TFrom, TTo> selector)
{
TTo actualVal = selector(value);
...
}
...
SomeMagicMethod(testObj, x => new {x.StringHere, x.ANumber });
Personally, I think the first is easier - the func in the second is overkill.
You could also just use reflection...
SomeMagicMethod(object obj, params string[] names)
{
foreach(var name in names) {
object val = obj.GetType().GetProperty(name).GetValue(obj);
// ...
}
}
//...
SomeMagicMethod(testObj, "StringHere", "ANumber");
you can pass them as lambda:
GetNewClass (testObj, ()=>StringHere, ()=> ANumber);
and have a signature for GetNewClass like
void GetNewClass (object, Expression<Func<object>> expr0, Expression<Func<object>> expr1);
You can then get the property quite easily.
You can use Linq expressions for that.
(note: it's possible you need to modify a few things in the snippet below, this is of the top of my hat):
public void getNewClass(Object testObj, params MemberExpression Fields[])
{
foreach(MemberExpression field in Fields)
{
// Get the name
var name = field.Member.Name;
// get the value
var member= Expression.Convert(field, typeof(object));
var lambda= Expression.Lambda<Func<object>>(member);
var fnc= lambda.Compile();
var value = fnc();
}
}
This snippet show how to get the name of the property and the value. It can be called like this:
getClass(someObj, obj => obj.SomeProperty, obj.SomeOtherProperty);

Treat Object Like Dictionary of Properties in C#

I want to be able to access property values in an object like a dictionary, using the name of the property as a key. I don't really care if the values are returned as objects, so Dictionary<string, object> is fine. This is the intended usage:
object person = new { Name: "Bob", Age: 45 };
IDictionary<string, object> lookup = new PropertyDictionary(person);
string name = (string)person["Name"];
person["Age"] = (int)person["Age"] + 1; // potentially editable
I was about to implement my own class for this, but then I started noticing classes like DynamicObject implement the IDictionary interface, which made think this was already being done for me somewhere.
What I want is similar to the functionality used by ASP.NET MVC that allows using anonymous types to set HTML tag attributes. I have a lot of classes that use dictionaries as data sources, but most of the time I should be able to pass in objects as well.
Since this is for a general-purpose library, I thought I would create a reusable class that simply decorated an object with the IDictionary interface. It will save me from creating an explosion of overloads.
I don't believe there is a built-in .Net type like this already in the .Net framework. It seems like you really want to create an object that behaves a lot like a Javascript object. If so then deriving from DynamicObject may be the right choice. It allows you to create an object which when wrapped with dynamic allows you to bind directly obj.Name or via the indexer obj["Name"].
public class PropertyBag : DynamicObject {
private object _source;
public PropertyBag(object source) {
_source = source;
}
public object GetProperty(string name) {
var type = _source.GetType();
var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
return property.GetValue(_source, null);
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
result = GetProperty(binder.Name);
return true;
}
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
result = GetProperty((string)indexes[0]);
return true;
}
}
You can use this to wrap any type and use both the indexer and name syntax to get the properties
var student = new Student() { FirstName = "John", LastName = "Doe" };
dynamic bag = new PropertyBag(student);
Console.WriteLine(bag["FirstName"]); // Prints: John
Console.WriteLine(bag.FirstName); // Prints: John
I have this extension method, probably the simplest it can get:
public static Dictionary<string, object> ToPropertyDictionary(this object obj)
{
var dictionary = new Dictionary<string, object>();
foreach (var propertyInfo in obj.GetType().GetProperties())
if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0)
dictionary[propertyInfo.Name] = propertyInfo.GetValue(obj, null);
return dictionary;
}
Now you can do:
object person = new { Name = "Bob", Age = 45 };
var lookup = person.ToPropertyDictionary();
string name = (string)lookup["Name"];
lookup["Age"] = (int)lookup["Age"] + 1; // indeed editable
Note:
that this dictionary is case-sensitive (you can trivially extend it passing the right StringComparer).
that it ignores indexers (which are also properties) but it's up to you to work on it.
that the method is not generic considering it doesn't help boxing because internally it calls obj.GetType, so it boxes anyway at that point.
that you get only the "readable" properties (otherwise you dont get the values held in it). Since you want it to be "writable" as well then you should use CanWrite flag as well.
dynamic keyword may be one option for you. it uses dynamic language runtime. At runtime, it tries to match the closest available type in the program. If it cant, then it converts the dynamic type to dictionay object, where key is the name of property and value is the value of property.
follow these links of MSDN:
Using dynamic keyword in C#
dynamic (C# Reference)
DLR Overview
usage of dynamic sample walkthough page

Using LINQ expression to assign to an object's property

So I'm working with an old data model, and I kind of have to work within what I've been handed.
When I perform a database query, the model returns data as a
List<Dictionary<string, object>>
Where for each dictionary, the key is the column name and the value is the column value. As you can imagine, working with this is a nightmare of foreach loops and type casting
I'm hoping to define some POCO viewmodels and then making something that uses LINQ/reflection, and an "assignment binding map" to go from hideous return value to my nice clean POCO. So I could define "maps" with the column names and lambdas to the properties on my POCO, similar to this...
var Map; // type???
Map.Add("Id", p => p.Id);
Map.Add("Code", p => p.Code);
Map.Add("Description", p => p.Description);
Map.Add("Active", p => p.Active);
Then convert like this...
List<Dictionary<string, object>> Results = MyModel.Query(...);
List<ProductViewModel> POCOs = new List<ProductViewModel>();
foreach (var Result in Results) // Foreach row
{
ProductViewModel POCO = new ProductViewModel();
foreach (var i in Result) // Foreach column in this row
{
// This is where I need help.
// i.Key is the string name of my column.
// I can get the lambda for this property from my map using this column name.
// For example, need to assign to POCO.Id using the lambda expression p => p.Id
// Or, assign to POCO.Code using the lambda expression p => p.Code
}
POCOs.Add(POCO);
}
return POCOs;
Can this be done using some sort of reflection, and if so, how?
Here is an approach using expression trees. First, define the API of the map:
public class PropertyMap<T> where T : new()
{
public void Add(string sourceName, Expression<Func<T, object>> getProperty);
public T CreateObject(IDictionary<string, object> values);
}
You would use it like this:
var map = new PropertyMap<ProductViewModel>();
map.Add("Id", p => p.Id);
map.Add("Code", p => p.Code);
map.Add("Description", p => p.Description);
map.Add("Active", p => p.Active);
var productViewModel = map.CreateObject(values);
To implement it, first you would declare a dictionary to associate names from the data source to properties:
private readonly IDictionary<string, PropertyInfo> _properties = new Dictionary<string, PropertyInfo>();
Next, you would implement the Add method in terms of that dictionary (all error handling left as an exercise for the reader):
public void Add(string sourceName, Expression<Func<T, object>> getProperty)
{
_properties[sourceName] = (PropertyInfo) ((MemberExpression) getProperty.Body).Member;
}
Then, you would dynamically compile a method, using expression trees, which does the assignments (it sounds scarier than it is). The easiest way to visualize this process is to look at an example of what we're building. What we want is some code which does this:
new ProductViewModel
{
Id = ...,
Code = ...,
Description = ...,
Active = ...
}
But, we can't know that at compile-time because of the dynamic mappings. So, we'll build a function which is that exact code, but compiled at runtime. Expression trees are just runtime data that represents the same code you could write at compile-time.
First, we need to get a set of bindings (assignments) for the properties:
private IEnumerable<MemberBinding> GetPropertyBindings(IDictionary<string, object> values)
{
return
from sourceName in _properties.Keys
select Expression.Bind(_properties[sourceName], Expression.Constant(values[sourceName]));
}
What we're saying here is, for each property in the mapped properties, look up the value and make it a constant (for Id, this might be the value 7) and bind the corresponding property to it. This gives us the expression Id = 7. We repeat this for all of the properties, giving us all of the assignments.
Once we have those bindings, we can create the full member initialization, which includes the constructor call:
private MemberInitExpression GetMemberInit(IDictionary<string, object> values)
{
return Expression.MemberInit(Expression.New(typeof(T)), GetPropertyBindings(values));
}
Because we specified where T : new() in the class declaration, we are guaranteed to have a parameterless constructor to call here. We pass in the property bindings we created before, giving us a data structure that represents the initialization expression we wanted to build.
So what do we do know? We have this data structure, but how do we call the code? To do that, we have to wrap that expression in a function that we can call, because the only thing you can actually invoke is a method. This means we are really building code that looks like this:
() => new ProductViewModel
{
Id = ...,
Code = ...,
Description = ...,
Active = ...
}
That is a parameterless function which, when invoked, will return the initialized object. This is also called a lambda expression. We can get the data structure for this like so:
private Func<T> GetInitializationFunction(IDictionary<string, object> values)
{
var initializationLambda = Expression.Lambda<Func<T>>(GetMemberInit(values));
return initializationLambda.Compile();
}
We create a lambda expression whose body is the member initialization, which is exactly the code we wrote above. We specify the delegate type Func<T> because it takes no parameters and returns an object of the mapped type.
Then, we compile it. This call generates a method with the signature Func<T> that we can call, and which has as its body the code we created as a data structure. This is a neat way of doing reflection without using reflection directly.
Finally, we implement the CreateObject method we defined earlier by creating the function and invoking it, giving us an instance of T (ProductViewModel here):
public T CreateObject(IDictionary<string, object> values)
{
var initializationFunction = GetInitializationFunction(values);
return initializationFunction();
}
What you could do is to extract the property name from a linq expression of the kind p => p.Id using something like this
public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
..and then use plain old reflection to actually assign the value to the object instance. For instance create a method
private void Assign(object objInstance, Expression<Func<T>> propertyExpression, object value)
{
string propertyNameToAssign = GetPropertyName(propertyExpression);
//TODO use reflection to assign "value" to the property "propertyNameToAssign" of "objInstance"
}
(didn't compile the code; for the reflection part, there are numerous articles on the web. Hope this helps)
This seems like a perfect match for dynamic . You can create a dynamic class that has the properties based on the keys in the dictionary. Check the DynamicObject class.

How can be possible to use anonymous type fields without know them?

It is really looks so cool to me how GridView's DataSource property gets anonymous type and shows results in Grid .
Simply
Grid.DataSource = from order in db.OrdersSet
select new { order.PersonSet.Name,order.PersonSet.SurName};
For example how can i write a propery or method which takes anonymous type and write field values to console output ?
The compiler actually creates (auto-generates) a class when it encounters syntax which use anonymous types, e.g.
var anonymousType = new { Name = "chibacity", Age = 21 };
This mechanism is automated by the compiler, but using a tool like Reflector you can disassemble the compiled code where you will see that a class has been generated to represent this anonymous type, e.g.:
[CompilerGenerated]
[DebuggerDisplay(#"\{ Name = {Name}, Age = {Age} }", Type="<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<<Name>j__TPar, <Age>j__TPar>
{
// Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <Age>j__TPar <Age>i__Field;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <Name>j__TPar <Name>i__Field;
// Methods
[DebuggerHidden]
public <>f__AnonymousType0(<Name>j__TPar Name, <Age>j__TPar Age);
[DebuggerHidden]
public override bool Equals(object value);
[DebuggerHidden]
public override int GetHashCode();
[DebuggerHidden]
public override string ToString();
// Properties
public <Age>j__TPar Age { get; }
public <Name>j__TPar Name { get; }
}
Update
Now that you have edited your question...
I am assuming that the question is that you desire to access the anonymous types outside of the scope it was declared in. This question is a duplicate of:
Accessing C# Anonymous Type Objects
Accessing C# Anonymous Type Objects
With reflection...
If you have an instance of an anonymous type, you can hold it in a variable of type object, call GetType() on it, and then GetFields, GetProperties, etc. to find out what columns are associated with it. Each PropertyInfo or FieldInfo you see has the capability to retrieve the value from any instance of the type.
Anonymous types are syntactic sugar in a way. The compiler analyses the output of such operations and creates classes on the fly with the properties you request. It simply takes work from you - before anonymous types, you had to write classes or structs for every type you used, even though they were just temporary information. With anonymous classes/methods/lambdas you don't have to do this anymore and save a lot of time.
You can do something like this:
private void button2_Click(object sender, EventArgs e)
{
var p = new { a = 10, b = 20 };
TestMethod(p);
}
private void TestMethod(object p)
{
Type t = p.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
System.Diagnostics.Debug.WriteLine(string.Format("{0} = {1}", pi.Name,
t.InvokeMember(pi.Name, BindingFlags.GetProperty, null, p, null)));
}
}

Categories

Resources