This question already has answers here:
Set object property using reflection
(10 answers)
Closed 3 years ago.
In a dynamic way, I'm looking to set the .Value property of the SyncVar property of the Unit class. The following won't compile and I don't want to hardcode SynvVar<int> because it could be a number of base types <int>, <string>, <bool>, etc.
class SyncVar<T>
{
public T Value { get; set; }
}
class Unit
{
public SyncVar<int> Health { get; set; } = new SyncVar<int>();
}
class Program
{
static void Main(string[] args)
{
Unit unit = new Unit();
unit.Health.Value = 100;
var prop = unit.GetType().GetProperty("Health").GetValue(unit);
// compile error as prop object doesn't contain .Value
// I need to dynamically figure out what type was used in this generic property so I can cast to that and set it's value
prop.Value = 50;
}
}
In case of arbitrary T you can try Reflection one time more:
prop.GetType().GetProperty("Value").SetValue(prop, 50);
Related
This question already has answers here:
Associating enums with strings in C#
(38 answers)
Can enums contain strings? [duplicate]
(6 answers)
Closed 1 year ago.
I know enums can't be strings
I would like a data structure with the utility of an enum, but one which returns strings instead of integers. To be clear, I want the return type to be the enum-like type, not string. Basically, I want to be able to force a property to be usable as a string but is only allowed to be set to a value in a defined set of strings. Something like
stringenum Unit {
Pixels = "px",
Inches = "in"
}
class Settings {
public Unit Unit { get; set; }
}
var settings = new Settings() { Unit = Unit.Pixels };
...
unitLabel.Text = settings.Unit;
I've seen some solutions that just create a class with properties that return a certain string. However, I need the return type to be limited to a set, not just any string.
EDIT FOR CLARIFICATION
Consider my previous example in addition to this method:
public void WriteUnit(Unit unit)
{
Console.WriteLine(unit);
}
// Calling
WriteUnit(Unit.Pixels); // Prints "px"
WriteUnit("px"); // ARGUMENT EXCEPTION
This method will throw an ArgumentException if you pass it a string. It only accepts the type. This is specifically what I'm looking for.
As mentioned in the comments, you cannot directly map an enum to a string.
That said, there is nothing preventing you from creating a map of enum to string values, that can only be accessed via the enum. If you maintain the mapping, you can guarantee that the value always exist.
public enum Unit
{
Pixels,
Inches
}
public static class UnitMapper
{
private static readonly Dictionary<Unit, string> _map
= new Dictionary<UserQuery.Unit, string>()
{
{ Unit.Pixels, "px" },
{ Unit.Inches, "in" }
}
public static string GetUnit(Unit unit)
{
return _map[unit];
}
}
Based on your additional comments, this can be combined with a custom user-defined implicit operator to give you the type of functionality you are looking for, although you will still have to call the overridden .ToString() to output a string.
public struct UnitWrapper
{
private readonly string _unitString;
private readonly Unit _unit;
public UnitWrapper(Unit unit)
{
_unit = unit;
_unitString = UnitMapper.GetUnit(_unit);
}
public static implicit operator UnitWrapper(Unit unit)
{
return new UnitWrapper(unit);
}
public override string ToString() => _unitString;
}
This can then be used as follows:
public class Settings
{
public UnitWrapper UnitWrapper { get; set; }
}
var settings = new Settings { UnitWrapper = Unit.Pixels };
string px = settings.UnitWrapper.ToString();
This question already has answers here:
What is difference between Init-Only and ReadOnly in C# 9?
(4 answers)
Closed 1 year ago.
I can define a class like below:
public class MyClass
{
public int Id { get; }
public MyClass(int id) => Id = id;
}
And I have to define the Id from the constructor and it will be read-only.
But if I want to use Init only setters in the C# 9.0, what does it and how can I use it?
public class MyClass
{
public int Id { get; init; }
}
Init only setters provide consistent syntax to initialize members of an object. Property initializers make it clear which value is setting which property. The downside is that those properties must be settable.
With that, you don't need to provide the value at the beginning and the constructor and you can do it afterward:
var myClass = new MyClass
{
Id = 10
}
and it will be sealed and you cannot change it anymore.
myClass.Id = 43; // not allowed
read more info
In a nutshell:
var obj = new MyClass
{
Id = 42 // totally fine
};
obj.Id = 43; // not OK, we're not initializing
Trivial in this case and not much different to using a constructor parameter, but useful in some more complex scenarios where you don't want 200 constructor parameters, but you do want it to be outwardly immutable once constructed.
This question already has answers here:
How to get a property value using reflection
(2 answers)
C# Reflection - Get field values from a simple class
(3 answers)
how to get both fields and properties in single call via reflection?
(6 answers)
Closed 3 years ago.
What I'm trying to do is have a class that I can inherit from and be able to track changes to properties.
I have this base class called TrackedEntity.
I then create another class TestEntity that inherits from TrackedEntity.
On my TestEntity class I have marked one of my fields with an attribute that I called CompareValues.
TrackedEntity
public class TrackedEntity {
public void GetCompareValues<T> () {
var type = typeof (T);
var properties = type.GetProperties ();
foreach (var property in properties) {
var attribute = (CompareValues[]) property.GetCustomAttributes
(typeof(CompareValues), false);
var hasAttribute = Attribute.IsDefined (property, typeof
(CompareValues));
}
}
}
TestEntity
public class TestEntity : TrackedEntity
{
public int one { get; set; }
[CompareValues]
public int two { get; set; }
public int three { get; set; }
}
CompareValues attribute:
[AttributeUsage ( AttributeTargets.Property |
AttributeTargets.Field,
Inherited = true)]
public class CompareValues : Attribute {
public CompareValues () { }
}
I can then do this
var test = new TestEntity ();
test.GetCompareValues<TestEntity> ();
In my GetCompareValues method I can find which fields in TestEntity use my CompareValues attribute.
I am trying to find a way to access the value of the fields that have the CompareValues attribute so that I can track the changes and log information about it.
If there is any other way to get this done by using another method please let me know.
Thank you.
You´re almost there. All you need to do is to get the properties value on the current instance - the instance on which you´ve called the method:
if(hasAttribute)
{
var value = property.GetValue(this, null);
}
Apart from this you won´t need generics here. Just use this:
var type = this.GetType();
which returns TestEntity in case of the instance being of your derived type.
This question already has answers here:
Comparing Object properties using reflection
(5 answers)
Closed 3 years ago.
I would like to know if there is a way to create a custom class out of an existing class in this manner:
original class:
public class Person
{
string name;
}
later in code:
var diffPerson = CreateDiffClass<Person>();
diffPerson.name.Value = "name";
diffPerson.name.Changed = false;
this diffPerson is not of Person type, instead it is custom created one, that for every variable in Person have one in itself so that the new variable is a tuple where T is the type of the variable.
I want it to create a system for comparing 2 instances of the same class. one old instance and one new and save the new value and if it changed
I don't really know how to describe it except showing in this example so I hope it is understandable..
I want this to be generic and work on any given class
Thanks
You can declare a generic class like this
public class CustomValue<T>
{
public T Value { get; set; }
public bool Changed { get; set; }
}
and then use it like this
public class Person
{
public CustomValue<string> Name;
}
later in code
var diffPerson = new Person();
diffPerson.Name = new CustomValue<string>();
diffPerson.Name.Value = "name";
diffPerson.Name.Changed = false;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I read the properties of a C# class dynamically?
I have to get values of class members using strings of their names only. I think I have to use Reflection but I am not realy sure how to. Can you help me?
MemberInfo member = typeof(MyClass).GetMember("membername");
GetMember reference.
If you know type of member you're looking for, you can use .GetMethod, .GetField, .GetProperty, etc.
If you don't know the type you are working with:
var myobject = someobject;
string membername = "somemember";
MemberInfo member = myobject.GetType().GetMember(membername);
Different member types have different means to getting the value. For a property you would do:
var myobject = someobject;
string propertyname = "somemember";
PropertyInfo property = myobject.GetType().GetProperty(membername);
object value = property.GetValue(myobject, null);
public class Foo
{
public string A { get; set; }
}
public class Example
{
public void GetPropertyValueExample()
{
Foo f = new Foo();
f.A = "Example";
var val = f.GetType().GetProperty("A").GetValue(f, null);
}
}