How to use conditional statement IF ELSE on property attribute - c#

I want to show MyProperty1 or MyProperty2 based on MyPropertySelected. How to use a conditional statement if or else based on MyPropertySelected? Thanks.
// [Browsable(true)
// ????? conditional statement IF ELSE in here..
// IF (MyPropertySelected) MyProperty1 will be show ELSE MyProperty2 will be show.
public bool MyPropertySelected { get; set; }
// [Browsable(true) or [Browsable(false) depending on MyPropertySelected condition.
public int MyProperty1 { get; set; }
// [Browsable(true) or [Browsable(false) depending on MyPropertySelected condition.
public int MyProperty2 { get; set; }

You're confusing apples with oranges.
Attributes are metadata and a property value acquires its value on run-time.
In other words: attribute is something that you'll access using reflection and those aren't tied to a particular object but to the type of the object (i.e. the class).
Another issue is that you want to add an attribute to a property based on a condition that can't work in compile-time.
Your MyPropertySelected won't get any value until its enclosing class gets instantiated - that's creating an object, for example: MyClass a = new MyClass()-, meaning that adding or not adding the attribute would never be a compile-time choice.
I want to be clear: you can't do what you want purely using attributes!
You can't conditionally apply attributes based on run-time values.
Finally, I suspect you want to make something Browsable based on a condition, like your own question says. You can't do that.
Ok ok, but what...?
You can workaround your situation with a different software design.
1)
First, create an interface that will have any of the properties that would be browsable or not. But don't apply the attribute [Browsable(bool)] to the interface properties.
2)
Create two classes that implements the previously created interface.
In the first class, implement the interface properties and put a [Browsable(true)] attribute on them. In the second class, do the same, but this time put a [Browsable(false)] on them.
3)
Some code that creates the instance of the object will be the one that will also decide which one will be instantiated.
That is, externalizing MyPropertySelected outside of both classes and performing the whole condition switch in the caller.
public interface IBrowsableProperties
{
int Property1 { get;set; }
int Property2 { get;set; }
}
public class A : IBrowsableProperties
{
[Browsable(true)]
public int Property1 { get;set; }
[Browsable(true)]
public int Property1 { get;set; }
}
public class B : IBrowsableProperties
{
[Browsable(false)]
public int Property1 { get;set; }
[Browsable(false)]
public int Property1 { get;set; }
}
// Somewhere in some method...
bool propertySelected = true;
IBrowsableProperties instance = null;
if(propertySelected)
{
instance = new A();
}
else
{
instance = new B();
}
// ... do stuff with your instance of IBrowsableProperties!
UPDATE
I've reviewed some of your question's comments and I've found you're working with PropertyGrid control.
Anyway, you can apply the concept in your case. PropertyGrid can be inherited. You can create both PropertyGrid1 and PropertyGrid2 derived classes that both implement the proposed interface!

You probably want an intermediary property like this:
class Foo
{
public bool MyPropertySelected
{
get;
set;
}
public readonly int MyProperty
{
get
{
return MyPropertySelected ? MyProperty1 : MyProperty2;
}
}
private int MyProperty1
{
get;
set;
}
private int MyProperty2
{
get;
set;
}
}

Related

Want to avoid returning writable references inside of a complex read-only class (game state)

I'm writing a little game, and the game has a State class to keep track of game state. The State class is only intended to be modifiable by Commands (command pattern). The State class includes lists of other classes - e.g. a Faction class, which contains members like resources, a list of owned Units, etc.
How can I make the deep innards of State readable from other classes, without also leaking writable references inside of State itself?
Currently, I have specialized getters like State.GetOwnerOfUnitAtLocation(x), which only return safe values (int factionid etc.), but I am beginning to need a lot of these, and the class is getting really unwieldy. I would prefer to have those methods in more appropriate locations (Map.Units.GetOwner(x) or something), but I don't know how to expose the internals of State to other classes in a safe way.
Relatedly, Command is an interface that currently lives inside of the State class, along with all the actual commands that implement it, so that it can modify private members of State. Is there a better way to implement this?
Edit: A selection of code from State to illustrate the first issue:
public partial class State
{
public int Turn {get; private set;} = 1;
private Dictionary<Vector2, FactionsMgr.Faction> _unit_map = new Dictionary<Vector2, FactionsMgr.Faction>();
public int GetUnitRemainingMobility(Vector2 pos)
{
if (IsUnitAt(pos))
{
FactionsMgr.Faction owner = _unit_map[pos];
int taken_movement = owner.units[pos]._taken_movement;
int max_mobility = UnitsMgr.GetMaxMobility(owner.units[pos].type);
return max_mobility - taken_movement;
}
else
{
GD.Print("Warning: GetUnitRemainingMobility asked for unknown unit: ", pos);
return -1;
}
}
}
Since FactionsMgr.Faction is mutable, let's suppose that it has writable properties like this:
class Faction {
public int Foo { get; set; }
public string Bar { get; set; }
public float Baz { get; set; }
public SomeOtherMutableThing AnotherThing { get; set; }
}
You should create a corresponding read only interface for it, and make Faction implement it:
interface IReadOnlyFaction {
// exclude all members that can change Faction's state
int Foo { get; }
string Bar { get; }
float Baz { get; }
IReadOnlySomeOtherMutableThing AnotherThing { get; }
}
interface IReadOnlySomeOtherMutableThing {
// do the same thing there...
}
class Faction: IReadOnlyFaction {
public int Foo { get; set; }
public string Bar { get; set; }
public float Baz { get; set; }
public SomeOtherMutableThing AnotherThing { get; set; }
// you need an explicit interface implementation here, unless you are using C# 9
IReadOnlySomeOtherMutableThing IReadOnlyFaction.AnotherThing => AnotherThing;
}
Then, you can declare public members in State as of type IReadOnlyFaction, and delegate them to a private member of type Faction. The private member is also what the Command class will modify.
private Faction someFaction;
public IReadOnlyFaction SomeFaction => someFaction;
That is the general case. However, if you have collections of these mutable types, like your dictionary of _unit_map, you would need to do a bit more work.
You would still have a public read only member and a private mutable member, but the delegating process is less straightforward. You would need a wrapper.
private Dictionary<Vector2, FactionsMgr.Faction> _unit_map = new();
public IReadOnlyDictionary<Vector2, IReadOnlyFaction> UnitMap;
// ...
// in the constructor of State...
// using the ReadOnlyDictionaryWrapper class from the linked answer
UnitMap = new ReadOnlyDictionaryWrapper<Vector2, FactionsMgr.Faction, IReadOnlyFaction>(_unit_map);

Auto restrict runtime access to a property

Is it possible to have a class with unknown amount or types of properties, that will restrict the property access if needed, in runtime.
For example, if we have the following class:
public class SomeClass
{
public string SomeProperty { get; set; }
}
Then, accessing the class property outcome will depend on some runtime state, that is controllable by classes that are aggregated to it in some way.
A possible solution, would be to add some public boolean variable that can be set, then determain the behaviour by it.
For example:
public class SomeClass
{
public bool CanAccess { get; set; }
private string _someProperty;
public string SomeProperty
{
get
{
if (CanAccess)
{
return _someProperty;
}
throw new Exception();
}
set
{
if (CanAccess)
{
_someProperty = value;
}
throw new Exception();
}
}
}
This solution however, will require the class implementor to:
Do it right
Do it for all properties
I am not sure it is possible, but I want to implement that class in some way that will eliminate the need to check this "CanAccess" feild for every property.
This further means that if in the future I add some more properties to that class, they will also comply that "CanAccess" state automatically.
Thanks for helping.

How to verify completeness of save/load system

I am making a save/load system for a big game project in C#.
Each class that has to be saved implements a method DoSnapshot().
Inside the method, the programmer must make a call to a function for every field in the class - either DoSnapshot(foo) if foo should be saved, or Ignore(foo) if it should not.
I have a DoSnapshot method for many primitive types like DoFloat, DoString as well as versions for complex types.
I have 100s of classes and the project is still being developed.
Is it possible to add some kind of verification that all of the fields in each class are either used in a Snapshot() or an Ignore() call? Omitting fields would cause bugs.
The verification could either be runtime, or compile-time. I only want to use it during development, it will not be released to users.
You could add an attribute to the fields that need to be saved, and then loop over every property in your class in the DoSnapshot method. When the property has the attribute you're looking for, you call Snapshot, otherwise you call Ignore.
public class SomeClass : SomeBaseClass
{
[Required]
public string Foo { get; set; }
public string Bar { get; set; }
public override void DoSnapshot()
{
var properties = this.GetType().GetProperties();
foreach (var property in properties)
{
var isRequired = property.GetCustomAttributes(typeof (RequiredAttribute), false).Length > 0;
if (isRequired)
{
// Something
}
else
{
// SomethingElse
}
}
}
}
What i would do is create an attribute and "tag" each field if it should be saved or not. Then, at runtime, i would query the class using reflection to get all fields which should be serialized:
public class RandomClass
{
public string Foo { get; set; }
[Ignore]
public int Bar { get; set; }
}
public class IgnoreAttribute : Attribute
{
}
class Program
{
static void Main(string[] args)
{
var properties = typeof(RandomClass).GetProperties()
.Where(prop => !prop.IsDefined(typeof(IgnoreAttribute), false));
// Serialize all values
}
}

Using part of enum for internal usage?

I wanted to know what is a good option to solve this issue ,
I have a class that expose an enum : (this is just an example)
public class Foo
{
public State FooState { get; private set; }
public string SomeData { get; set; }
public Foo(State state)
{
FooState = state;
}
public Foo()
{
}
public enum State
{
None,
Bad,
Good
}
}
in one use of the class the user can adjust the state, and on the other he can't so the state is set on NONE and that good but i dont want the user to have the possibility of setting it to None. i Know that there isnt an internal enum field obviously, is there any way it can be done else, bare in mine that the Foo class cant be changed due to specification.
Clarification
The meaning of the class can not be change is that the design and purpose of the class can not change, not the class itself.
The state of the class is only in use when the c'tor get a value. i cant use two classes or use interface due to reflection use in the future. (i just cant use typeof)
I believe you can do this by providing two interfaces with different access level, implement them explicitly and instead of Foo type use one of the interfaces either for read-only or full access.
Since Foo can not be changed you can use Wrapper approach:
Foo foo = new Foo(State.Good);
FooWrapper fooWrapper = new FooWrapper(foo);
// would be read-write
(FooWrapper as IReaonlyState).State
// would be readonly
(FooWrapper as IWritableState).State
public interface IReadonlyState
{
State FooState { get; }
}
public interface IWritableState
{
State FooState { get; set; }
}
public class FooWrapper : IReadonlyState, IWritableState
{
Foo foo;
public FooWrapper(Foo foo)
{
this.foo = foo;
}
State IReadonlyState.FooState
{
get
{
return this.foo.FooState;
}
}
State IWritableState.FooState
{
get
{
return this.foo.FooState;
}
set
{
this.foo.FooState = value;
}
}
}
So, you want the consumer to be able to set both State=Bad and State=Good.
But if State==None you should be able to read, but not change it. Sounds like you need to implement the setter explicitly.

Changing property type in class that implements interface with object type property

I'm writing a TemplateEngine that will allow me to use my own markup in text based files. I'm wanting to add controls as plugins as the application matures. Currently i've got a structure like the following:
interface IControl
string Id
object Value
class Label : IControl
string Id
string Value
class Repeater : IControl
string Id
List<IControl> Value
Now you'll see the strange part right away in the Repeater class with the Value property. I was hoping that having the Value type as object in the interface would allow me the flexibility to expand the controls as i go along. The compiler doesn't like this and for good reason i guess.
Bottom line: I'm trying to get all control classes to implement the same interface but have different types for the Value property.
Does anyone have any suggestions how to accomplish this?
Note: Please don't go into suggesting things like use Spark View Engine for templating. There is a reason i'm creating extra work for myself.
Normally the Repeater would implement something different, like an IItemsControl for example.
EDIT 1
(removed for brevity)
EDIT 2
Ah okay, you can always use explicit interface implementation of course:
interface IControl
{
string Id { get; set; }
object Value { get; set; }
}
class Label : IControl
{
public string Id { get; set; }
public string Value { get; set; }
object IControl.Value
{
get { return this.Value; }
set { this.Value = (string)value; }
}
}
class Repeater : IControl
{
public string Id { get; set; }
public IList<IControl> Value { get; set; }
object IControl.Value
{
get { return this.Value; }
set { this.Value = (IList<IControl>)value; }
}
}
you could also use generics:
interface IControl<T>
{
string ID{get;set;}
T Value{get;set;}
}
class SomeControl : IControl<string>
{
public string ID{get;set}
public string Value{get;set;}
}
class SomeOtherControl : IControl<int>
{
public string ID{get;set}
public int Value{get;set;}
}
I like this better than the explicit interface idea if it's just one return value that needs to change. However, I think if you had several properties that each would return a different type, you wouldn't want to have IControl. At least, I wouldn't. In that case I would recommend the explicit interfaces.
Of course, this wouldn't work if you didn't have access to the source of IControl.
Edit: had a typo. Fixed
No, the compiler doesn't allow same name fields to be of different data types other than what is defined in the interface in derived classes.
The properties (since no fields are allowed in interface) should be implemented in the deriving classes and they need to have same data type. So, you cannot probably do it with properties without explicit declaration.
However, if you make Value to be returned by a function, then it works, but you need to check the return type because the return types should match for the function, otherwise you will get error that interface's function was not implemented.
interface IControl
{
object Value();
}
class A : IControl
{
string m_value = string.Empty;
public object Value() { return m_value; }
};
class B : IControl
{
List<IControl> m_value = new List<IControl>();
public object Value() { return m_value; }
};
....
object o = new B().Value();
if (o is List<IControl>)
MessageBox.Show("List");
[Update]
You have to be careful if explicitly defining the body of the properties. Having one name for two properties would be dangerous if implementation is not done carefully.
These two properties if contain different definition, it would be unexplainable for the final use of the interface and classes.
public IList<IControl> Value
object IControl.Value
See this example:
...
class Repeater : IControl
{
List<IControl> m_Value = new List<IControl>();
public IList<IControl> Value
{
get { return this.m_Value; }
set { this.m_Value = (IList<IControl>)value; }
}
object IControl.Value
{
get
{
return this.m_Value;
}
set
{
this.m_Value = new List<IControl>();
this.m_Value.Add(new Label());
this.m_Value.AddRange((List<IControl>)value);
}
}
}
...
Repeater b = new Repeater();
IControl i = b;
List<IControl> list = new List<IControl>();
list.Add(new Repeater());
i.Value = list;
You can observe that the list container in Repeater will have different values when data is added via IControl (because of the explicit definition of IContainer.Value).

Categories

Resources