Is there a way for me to read a property value I defined already in an anonymous object while creating the object?
here is an example
var a = new { PropA = "something", PropB = this.PropA + " and another thing"}
Perhaps defining it in a variable right before the declaration of a would work?
var somethingValue = "something";
var a = new { PropA = somethingValue , PropB = somethingValue + " and another thing"}
Otherwise, I don't think you would be able to. You have yet to instantiate the object so this.PropA wouldn't work. To further elaborate, your question was "Is there a way for me to read a property value I defined already in an anonymous object while creating the object?" which doesn't entirely make sense, because you are creating the anonymous object, so the value isn't already defined in the object.
Using dynamic binding can be helpful:
dynamic myObject = a;
myObject.PropB = ... //you can access any property that you know it exists
Related
In PHP we can remove one property and its value from the object simply with this code:
$foo->bar = "Something";
unset($foo->bar);
I want to do this in C#.
Imagine that the object is:
var a = new {foo = bar, one = "one"}
How I can remove foo from the object?
Types are defined at compile-time, so there's no removing of properties, not in c#. An anonymous type is a type just like classes that you create; it's just that the name is hidden from you.
The closest you can get to your answer is to define a new type that omits the property you wish to remove:
var b = new { one = a.one };
Supose that I have this:
CustomObject myCO1 = new CustomObject();
CustomObject myCO2 = myCO1;
CustomObject myCO3 = new CustomObject();
myCO1 = myCO3;
I would like that myCO2 has the same reference than myCO1, to myCO3. Is there any way to do that?
Thank so much.
No, assigning a new reference just copies the reference value into the new variable. When you change it's reference the other variables that references the same place are not affected.
So in your case, myCO2 references the old location of myCO1. And myCO1 and myCO3 are referencing to same location.
It sounds a little bit like you could use a primer on references and values in C#. Specifically: "If x is a variable and its type is a reference type, then changing the value of x is not the same as changing the data in the object which the value of x refers to"
However, let me edit your example for a bit of clarity:-
CustomObject myCO1 = new CustomObject("A");
CustomObject myCO2 = myCO1;
CustomObject myCO3 = new CustomObject("B");
myCO1 = myCO3;
You can see clearly that myCO2 refers to "A", even after you change myCO1 to refer to "B". This is because while a reference refers to another object, it is itself a value.
There are largely two ways you can achieve the outcome you desire.
The first option is using a reference type (rather than a value) to refer to your CustomObject:-
public sealed class Reference<T>
{
public T Value { get; set; }
}
...
Reference<CustomObject> myCO1 = new Reference<CustomObject>()
{
Value = new CustomObject("A");
};
Reference<CustomObject> myCO2 = myCO1;
CustomObject myCO3 = new CustomObject("B");
myCO1.Value = myCO3;
The second option you have is to encapsulate the logic you require in a method and use the ref keyword
In want to add dynamically the properties or methods of a user control from the code behind like this:
foreach (DataRow drModuleSettings in dsModuleSettings.Tables[0].Rows)
{
if (!string.IsNullOrEmpty(dsModuleSettings.Tables[0].Rows[0]["SettingValue"].ToString()))
userControl.Title = dsModuleSettings.Tables[0].Rows[0]["SettingValue"].ToString();
}
The "userControl.Title" is a sample, in fact it should be replaced by such a code:
userControl.drModuleSettings["SettingName"] = dsModuleSettings.Tables[0].Rows[0]["SettingValue"].ToString();
The problem is I don't know how to do this.
Please someone help me.
Thanks!
You will need to use Reflection.
Have a look at the following code and references:
See here: Set object property using reflection
Also, here: http://www.dotnetspider.com/resources/19232-Set-Property-value-dynamically-using-Reflection.aspx:
This code is from the above reference:
// will load the assembly
Assembly myAssembly = Assembly.LoadFile(Environment.CurrentDirectory + "\\MyClassLibrary.dll");
// get the class. Always give fully qualified name.
Type ReflectionObject = myAssembly.GetType("MyClassLibrary.ReflectionClass");
// create an instance of the class
object classObject = Activator.CreateInstance(ReflectionObject);
// set the property of Age to 10. last parameter null is for index. If you want to send any value for collection type
// then you can specify the index here. Here we are not using the collection. So we pass it as null
ReflectionObject.GetProperty("Age").SetValue(classObject, 10,null);
// get the value from the property Age which we set it in our previous example
object age = ReflectionObject.GetProperty("Age").GetValue(classObject,null);
// write the age.
Console.WriteLine(age.ToString());
You could use dynamic properties. Which would mean that, userControl.drModuleSettings will be of type dynamic.
You can then assign it a value at runtime like
userControl.drModuleSettings = new {SomeProperty = "foo", AnotherProperty = "bar"};
More about dynamic keyword and DynamicObject here and here.
Note - Requires C# 4.0 or above.
If I have this string list:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
in which:
- MyObject: the object class
- SetWidth: the property of the object
- int: type of the SetWidth is int
- 10: default value
- 0: object order
- 1: property order
Then how can I construct an object like this:
[ObjectOrder(0)]
public class MyObject:
{
private int _SetWidth = 10;
[PropertyOrder(1)]
public int SetWidth
{
set{_SetWidth=value;}
get{return _SetWidth;}
}
}
So, I would like have something like this:
Object myObject = ConstructAnObject(myObjectString);
and the myObject is an instance of MyObject. Could it be possible in C#?
Thanks in advance.
I think you better use the Object Serialization/Deserialization instead of creating a custom method that basically needs to do the same thing
more info at:
http://msdn.microsoft.com/en-us/library/ms233843.aspx
Here is some quick and dirty code to get you started:
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
var info = myObjectString.Split(',');
string objectName = info[0].Trim();
string propertyName = info[1].Trim();
string defaultValue = info[3].Trim();
//find the type
Type objectType = Assembly.GetExecutingAssembly().GetTypes().Where(t=>t.Name.EndsWith(objectName)).Single();//might want to redirect to proper assembly
//create an instance
object theObject = Activator.CreateInstance(objectType);
//set the property
PropertyInfo pi = objectType.GetProperty(propertyName);
object valueToBeSet = Convert.ChangeType(defaultValue, pi.PropertyType);
pi.SetValue(theObject, valueToBeSet, null);
return theObject;
This will find the MyObject, create an object of the proper propertytype, and set the matching property.
If you use C# 4.0, you can use the new dynamic feature.
string myObjectString = "MyObject, SetWidth, int, 10, 0, 1";
String[] properties = myObjectString.Split(',');
dynamic myObj;
myObj.MyObject = (objtect)properties[0];
myObj.SetWidth = Int32.Parse(properties[1]);
// cast dynamic to your object. Exception may be thrown.
MyObject result = (MyObject)myObj;
I don't quite understand why do you need ObjectOrder and PropertyOrder... Once you have their names you probably don't need them, at least for "deserialization"...
Or please advice what is their role?
You definitely can simply do it via reflection:
Split the string by comma (using myString.Split)
Use reflection to find an object within your application:
Find the type with name = splittedString[0] (enumerate all the assemblies within the domain and all the types within each assembly);
Instantiate the type found (using Activator.CreateInstance)
Find the property by name (Using objectType.GetProperty)
Set the property value (using propertyInfo.SetValue)
Return the object
Assuming you need to generate new types there are two possible ways to do so:
Using Reflection Emit
Using CodeDom provider
I think the simpler solution is CodeDom provider. All needed is to generate the source as a string in memory, and then compile the code and instantiate a new instance with Activator. This is a nice example I just found.
The reason I think that CodeDom provider is simpler is that it has shorter setup - no need to generate dynamic module and assembly and then work with type builder and members builder. In addition, it doesn't require working with IL to generate the getter and setter bodies.
An advantage that reflection emit has is performance - dynamic module can add more types to itself even after one of the types was used. CodeDom provider requires creating all the types at once, otherwise it creates a new assembly each time.
Can I somehow get a reference to the instance I am creating using object initialiser
var x = new TestClass
{
Id = 1,
SomeProperty = SomeMethod(this)
}
"this" should point to the new TestClass instance I'm creating. But it obviously refers the the instance of the class in which this code resides.
I'm not asking if this is a good way to do this.
I'm aware that I can do this like this:
var x = new TestClass {Id= x};
x.SomeProperty = SomeMethod(this);
I have a complicated scenario, in which a reference to the new instance in the object initialiser would make life easier.
Is this possible in any way?
There's no way around it, the C# specification explicitly says that "It is not possible for an object or collection initializer to refer to the object instance being initialized."
As for why it's impossible, I suspect that there's just no nice way to implement it. We want some syntactic sugar equivalent to
var temp = new TestClass();
temp.Id = 1;
temp.SomeProperty = SomeMethod(temp);
x = temp;
We just need a keyword to refer to temp within the initializer, but none is easily available. We can't use this because it already means something outside the initializer. Should SomeProperty = this.SomeMethod(this) be equivalent to temp.SomeProperty = this.SomeMethod(temp) or temp.SomeProperty = temp.SomeMethod(temp)? The second is consistent, but then what happens if we need the first?
We could try to use x, though we can only pick a name if the new object is immediately assigned to a variable. However, we now can't refer to the old value of x inside the initializer, doing the equivalent of temp.SomeProperty = SomeMethod(x).
We could reuse the value keyword from property setters. This sounds good since value already stands in for the missing parameter if you consider a property getter to be syntactic sugar for a set_SomeProperty(value) method. Using it to also refer to the missing variable in the object initializer looks promising. However, we could be creating this object inside a property setter, in which case value is already being used, and we need to be able to do temp.SomeProperty = SomeMethod(value).
It looks like we'll have to create a new keyword just for this purpose, maybe newthis. However, this is a breaking change to the language because any code that has a variable called newthis doesn't work any more. Microsoft generally needs a really good reason to introduce breaking changes, so it's better to forbid access to the object being initialized.
No, you can't use the object initializer to assign the object you're creating somewhere else - that defeats the whole point of the object initializer. The x variable doesn't get assigned until after the object initializer is completed. You'll need to assign the object, then use it in a separate statement.
var x = new TestClass {
Id = 1
};
x.SomeProperty = SomeMethod(x);
Exposing or using an object that hasn't been fully constructed is usually a very bad idea. Consider the following:
class Connection
{
internal string connectionString;
public Connection(ConnectionPool pool, string connectionString) {
this.pool = pool;
//this.connectionString = connectionString; // I moved it because I could.
this.pool.Register(this);
this.connectionString = connectionString;
this.Init();
}
private void Init() { //blah }
}
class ConnectionPool
{
public void Register(Connection c)
{
if ( this.connStrings.Contains( c.connectionString ) ) // BOOM
}
}
This is an extremely contrived example. Things can get a whole lot worse than this. The following was quite an interesting link regarding this issue:
Partially Constructed Objects
var x = new TestClass
{
Id = 1,
SomeProperty = SomeMethod(this)
}
Before the right part of this initialization is evaluated and executed, the reference to the new object is not yet made available to the code. That is done for security purposes, otherwise you could create some deadlock or endless loop with you code.