I am new to C# and reflection in specific and I am trying to solve a very specific problem. I want to implement the following code using reflection (since in some machines the System.Windows.Forms.DataVisualization.dlls might not be present, in those case i will skip generating charts).
Chart chart1 = new Chart();
string chartTitle = "Chart Title";
chart1.Titles.Add(chartTitle);
I figured out how to load a dll, get its class type, get/set its static/non-static properties, use constructors to create objects etc via Reflections. But I am quite lost about how to invoke "add" method on a collection.
Say, i have object Chart1 and chartTitle via Reflection, how do i implement the 3rd line of code using Reflection.
Appreciate your help. Thanks in advance.
Green Apple
If you already have the object chart1 instance then you can use
object titles = typeof(chart1).GetProperty("Titles").GetValue(chart1);
or
object titles = chart1.GetType().GetProperty("Titles").GetValue(chart1);
to get the chart1.Titles instance.
Then use titles.GetMethod("Add").Invoke(titles, chartTitle); to add the new title.
Related
I am attempting to add multiple flags of similar types (arrows) to a live chart using a C# windows forms project. This is to provide a label when a value falls out of a pre-defined specification.
I am currently stuck in how to create new instances of the ArrowAnnotation class so if multiple events happen there will be multiple flags for the people checking the chart. I am able to create one instance and manipulate the position to the latest data point in the series (it shouldn't be a stretch to lock it to a historical point, I just haven't done that yet.)
I have an understanding of creating multiple instances of other classes and keeping track of them with lists/ dictionaries but this one has me stumped (or maybe I don't have as good an understanding as I think?)
I can't share the code I have directly but I think I can write some example code if needed.
edit-
I am looking into using a memberwise clone to copy common attributes of each arrow and add those objects to a dictionary.
Thanks
Okay, I have managed to figure out how to do this for my use case.
When updating the live chart I can call a method if a parameter falls out of specification. In that method I create a new instance of the annotation, and the properties that I want to use as a template. (these values can also be changed with conditional logic if you want slight variation, and can be passed in with the argument) than add that newly made annotation to the annotation group. I am still looking for improvements to the code. I am still wanting a way to assign a name to the arrow, than recall that one and modify it (if I wanted to). And change the pass/fail criteria than apply annotations for the new failure points (but that is going into new territory)
// This is not the full method just the part that counts for this question.
private ArrowAnnotation floatArrow;
private void UpdateChart()
{
GenerateArrows(dateTime, sensorValue);
this.chart1.Annotations.Add(floatArrow);enter code here
}
private void GenerateArrows(DateTime x, double y)
{
floatArrow = new ArrowAnnotation();
floatArrow.Name = Convert.ToString(x);
floatArrow.ToolTip = Convert.ToString(x);
floatArrow.AxisXName = "ChartArea1\\rX";
floatArrow.AxisYName = "ChartArea1\\rY";
floatArrow.X = x.ToOADate();
floatArrow.Y = y;
floatArrow.Height = 5;
floatArrow.Width = 0;
floatArrow.BackColor = Color.Red;
}
I am trying to dynamically add field properties to a record class that I am also building dynamically using FileHelpers.Dynamic.DelimitedClassBuilder. I have no issues creating the class object and I currently add a field using the AddField(String) method.
As my apps grows I now have a need to declare specific field properties in various situations. So in the same sense I wanted to use FileHelpers.Dynamic.DelimitedFieldBuilder to create a field object and then pass that to my DelimitedClassBuilder object using the method AddField(DelimitedFieldBuilder).
However I am unable to instantiate a new object using FileHelpers.Dynamic.DelimitedFieldBuilder. When I issue the following code I get an error stating that DelimitedFieldBuilder does not contain a constructor that takes two arguments.
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder("ClassName", "Type");
Looking at the documentation it appears that this class does only have properties associated with it, so I am kind of stuck on how to actually implement this. It seems like it should be fairly easy but I cant seem to figure it out. Thanks for any help.
Not familiar with that functionality of file helpers; however, in the vast majority of functions/methods across .NET there is usually a way to assign properties after the class is instantiated.
Try something like this:
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder();
fb.Whatever = "ClassName";
fb.otherwhatever = "Type";
Just a stab. I have no idea if it will work or not.
The constructors of DelimitedFieldBuilder are internal so you'll run into difficulty with your approach. However AddField(String) returns a DelimitedFieldBuilder, so you might be able to use that.
It might be easier to make your own class MyFieldBuilder which calls the standard AddField(String).
I'm developing an application which can deal with a MS-ADLDS-Service.
Currently it is possible to create Directory-Entries and assign values to some properties.
Not a realy exciting task until this:
Im my application it's possible (it should be) to configure which properties of a class (for instance: the CN=Person class) should be assigned with values which are evaluated at runtime in my application.
Long story short:
I want to retrieve all (writeable) properties of a class. Without creating and saving a new CN=Person-Object before.
Currently i use my schemaBinding to get the Directory-classSchema-Entry of the Person-Class (CN=Person) from where i read some property-values (like "AllowedAttributesEffective", "mayContain", "AllowedAttributes") - i get the most properties by this way - but some Properties are missing! For instance the "telephoneNumber"-Property (attributeSchema: CN=Telephone-Number)
Does anybody know how to get these properties of a class? ADSI-Edit does this: when i create a new object with adsi-edit i can assign values to all possible properties before committing the new entry.
thanks a lot for any hint!
(.net code is welcome)
I have found the solution for my task!
Some of these properties are "calculated" and not persistent at the directoryentry.
So its meant to call the RefreshCache() Method and pass the needed property names as an string array.
directoryEntry.RefreshCache(new string[] { "allowedAttributesEffective",
"allowedAttributes",
"systemMayContain",
"systemMustContain" });
After that call, the properties have values....
if (directoryEntry.Properties["systemMayContain"]).Value != null)
{
/// Success
}
I'm trying to create objects dynamically but I don't know how to. What I need is, I have a class for that object, and objects properties are stored in the database. Then I'll need to compare the properties of each object to get the desired result.
So I need to dynamically create objects on the fly with the properties loaded from database.
I don't think you need to create objects dynamically, just create one statically that matches your db schema with the property details, then you can compare the values of the properties across rows, or within an instance of your object.
I have been working on something similar to this. There are several things:
Include the System.Reflection namespace
Create an object dynamically using Activator
Get the object properties using the myObjectType.GetProperties() method
Here is an example of a generic object creation function using the above methods:
using System.Reflection;
public static Item CreateItem<Item>(object[] constructorArgs, object[] propertyVals)
{
//Get the object type
Type t = typeof(Item);
//Create object instance
Item myItem = (Item)Activator.CreateInstance(t, constructorArgs);
//Get and fill the properties
PropertyInfo[] pInfoArr = t.GetProperties();
for (int i = 0; i < pInfoArr.Length; ++i)
pInfo.SetValue(myItem, propertyVals[i], null); //The last argument is for indexed properties
return myItem;
}
Of course the above example assumes that the values in the property value array are arranged correctly, which is not necessarily the case, but you get the idea.
With the PropertyInfo class you can get properties, get property names, get attributes associated with the properties, etc. Powerful technology. You should be able to do what you need with the above info, but if not let me know and I will add more info.
If you have a number of objects you want to instantiate from database values it can be done something like this.
//database code goes here, results go in results
List<ClassName> l = new List<ClassName>()
foreach(Row r in results){
l.Add(new ClassName(){ClassProperty1 = r.Property1,ClassProperty2 = r.Property2});
}
Are you talking about Dictionary?
var dict=new Dictionary<string, string>();
dict.Add("property1", "val1");
dict.Add("property2", "val2");
var prop2val=dict["property2"];
Maybe Activator is what your looking for?
http://msdn.microsoft.com/en-us/library/system.activator.aspx
Check this class, compile in the realtime. But it's performance is not quite good.
http://msdn.microsoft.com/zh-cn/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx
You could use reflection to dynamically build your objects:
Reflection msdn reference
I think that you want to retrieve rows from the DB and directly assign them to object given that the properties of the object are equivalent to the columns of DB table. If that what you mean then I believe you can't :)
Rob Conery did a small project called Massive that pretty much does what you're trying to accomplish. It's essentially a small ORM, in 400 lines of Dynamic C# 4.0 code.
Rob has been doing this kind of thing for quite some time with SubSonic, so you might find his approach with Massive quite interesting.
http://blog.wekeroad.com/helpy-stuff/and-i-shall-call-it-massive
Some of the code is explained here, with examples:
http://blog.wekeroad.com/microsoft/the-super-dynamic-massive-freakshow
What ways can you dynamically create controls in C#?
This was objects at first but it would have been more precise to say controls. My terminology was messed up. Thanks Joel.
Edit{
Controls that are created during runtime. And are able to be accessed and edited by the program.
Does this help?
}
I like the idea of Dynamic creation and was wondering what ways there were to do this.
Please only one per answer, I would like to see how people rank them.
eg
private Label _lblCLastName = new Label();
private static List<ChildrenPanel> _ListCP = new List<ChildrenPanel>();
public void CreatePanel(Panel Container)
{
// Created Controls
#region Controls
_pnlStudent.Controls.Add(_lblCLastName);
//
// lblCLastName
//
_lblCLastName.AutoSize = true;
_lblCLastName.Location = new System.Drawing.Point(6, 32);
_lblCLastName.Name = "lblCLastName";
_lblCLastName.Size = new System.Drawing.Size(58, 13);
_lblCLastName.TabIndex = 10;
_lblCLastName.Text = "Last Name";
// Adds controls to selected forms panel
Container.Controls.Add(_pnlStudent);
// Creates a list of created panels inside the class
// So I can access user input
ListCP.Add(this);
}
This is a code snippet from something that is close to what I'm talking about. I made another post but didn't quite post the question right. I will be deleting it but atm it is still viewable.
If there are still problems please be constructive I don't mind negitive input as long as it's helpful.
Edit:
I was able to get some answers I was looking for. Thank you to everyone who replied. I will close this when I am able too. If someone else can close it that would be appreciated.
I use the new keyword to dynamically create objects.
Creating GUI objects dynamically can be extremely useful, however, it can also be a nightmare for maintenance.
A good rule of thumb is to limit the amount of GUI object you dynamically create.
One situation where you may actually want to use a dynamically created GUI object is when you don't know the amount or count of objects you need. For example, one label for each row in a result set (even then you may consider a DataGrid or GridView type object).
This works for both WinForms and ASP.NET. Just be sure to document your code correctly.
My advice would be to stick with the Visual Designer for simpler forms and only create and add objects dynamically when it's absolutely necessary.
(FWIW, the code snippet you posted could probably be simplified and/or refactored as it seems to be going in the wrong direction.)
Anonymous Types, C# 3.x
This is fairly dynamic-esque because you don't have to code a class template to get custom objects.
// An anonymous object with two properties: obj.Name and obj.Age
var obj = new { Name = "Joe", Age = 35 };
The compiler will infer the Types of the properties from the initialization values you provide.
The type is not accessible from your source code, but can be seen in the IL. However if you create multiple anonymous objects with the same properties the C# compiler will use the same type for all of them.
// All objects use the same anonymous type
var obj1 = new { Name = "Joe", Age = 1 };
var obj2 = new { Name = "Art", Age = 30 };
var obj3 = new { Name = "Sally", Age = 25 };
// A different (second) anonymous type
var objDifferent = new { Phone = "555-555-1212", Name = "Joe", Age = 1 };
Stipulations There are more, but these are important.
var can only be used at the method scope (as a local variable), not the class scope.
anonymous objects have read-only properties; you cannot assign data back to them.
Activation (for remote objects too)
Use the System.Activator class' overloaded Activator.CreateInstance methods. This gets into the realm of creating objects locally or remotely.
using System;
/* Create instances of a Random number generator (or any class)
* without using the 'new' operator.
*/
Random rand1 = Activator.CreateInstance<Random>();
Random rand2 = (Random)Activator.CreateInstance(typeof(Random));
//etc...
(MSDN Documentation about Remote Objects.)
Assuming you are talking about the creation of dynamic objects:
You'll obviously need a library to support this, unless you want to get into Reflection.Emit yourself - LinFu supported this in version 1:
http://code.google.com/p/linfu/
However, it's a feature that was dropped before version 2 I seem to remember.