.NET, Winforms, C# 8
I am trying to define an interface that has read only properties that default to false. The plan is to only override properties that implement the interface on the ones that need a value of true:
Interface:
public interface IMenuActionInterface
{
public bool CanConnect => false;
public bool CanDisconnect => false;
}
Implementing class:
public class Connect : IMenuActionInterface
{
public bool CanConnect => true;
}
When I do this I am expecting the variable test to have two properties - CanConnect (value true) and CanDisconnect (value false). The variable only has a single property "CanConnect".
IMenuActionInterface test = new Connect();
Why? Is what I want to do possible?
EDIT
As #DavidG points out below the variable test DOES have both properties. When I hover Visual Studio 2022 does not display the value. Bug?
Related
I need to call a protected variable from a public class into an if statement in a private method of another public class
I am programing a video game in unity and I need to use a bool variable (that shows if the character is out of stamina) in an if statement to determine whether or not the character can run
This is what my code looks like excluding everything unrelated to the problem
Public class CharacterStats : MonoBehaviour
{
[SerialzeField] protected bool Tired;
}
Public class PlayerMovement : MonoBehaviour
{
Private void HandleRunning()
{
If (Input.GetKeyDown(KeyCode.LeftShift) && X != True)
{
Speed = RunSpeed;
}
}
}
X is where I want the Tired variable to be.
Use a public readonly property like e.g.
public class CharacterStats : MonoBehaviour
{
// Keep you serialized field protected
[SerialzeField] protected bool tired;
// Have a public read-only accessor property
public bool Tired => tired;
}
and then e.g.
public class PlayerMovement : MonoBehaviour
{
// Somehow you will need to get a reference to the CharacterStats instance
// e.g. via the Inspector
[SerializeField] private CharacterStats stats;
[SerializeField] private float RunSpeed;
private float Speed;
private void HandleRunning()
{
if (Input.GetKeyDown(KeyCode.LeftShift) && !stats.IsTired)
{
Speed = RunSpeed;
}
}
}
Alternatively (and my apologies to #aybe who had answered this) you can actually directly serialize a property using explicitely
[field: SerializeField] public bool Tired { get; protected set; }
this is a property which can be accessed by everyone but only this and inherited classes (and due to the serialization now the Inspector) have the permission to set the value.
In general: Fix your casing! In c# all keywords are lower key!
I would like to be able to simulate a failure of an arbitrary test in order to check that my TearDown logic works correctly. A unit test on a unit test, if you please.
But really, I have TearDown in some fixtures that produces attachments on failures. I must be able to show off this feature, but it is hard to produce a failure when you most need it.
So, I want to create a test parameter specifying the name of a test I wish to fail. Now, I can easily write an attribute implementing IWrapTestMethod or IApplyToContext, but then I need to apply it on every test method.
Is there a way to implement it without touching every test and/or fixture? By some kind of an assembly level attribute or assembly level setup method that would run before each and every test?
It is crucial that this logic would not prevent the TearDown methods from running, so ITestAction throwing an exception from BeforeTest does not fit the bill.
Can this be done?
I found the solution:
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using System;
using System.Reflection;
[assembly: Common.EnableFailureSimulation]
namespace Common
{
public class SimulateFailureMethodInfoWrapper : IMethodInfo
{
private readonly IMethodInfo m_mi;
public SimulateFailureMethodInfoWrapper(IMethodInfo mi)
{
m_mi = mi;
}
public ITypeInfo TypeInfo => m_mi.TypeInfo;
public MethodInfo MethodInfo => m_mi.MethodInfo;
public string Name => m_mi.Name;
public bool IsAbstract => m_mi.IsAbstract;
public bool IsPublic => m_mi.IsPublic;
public bool ContainsGenericParameters => m_mi.ContainsGenericParameters;
public bool IsGenericMethod => m_mi.IsGenericMethod;
public bool IsGenericMethodDefinition => m_mi.IsGenericMethodDefinition;
public ITypeInfo ReturnType => m_mi.ReturnType;
public T[] GetCustomAttributes<T>(bool inherit) where T : class => m_mi.GetCustomAttributes<T>(inherit);
public Type[] GetGenericArguments() => m_mi.GetGenericArguments();
public IParameterInfo[] GetParameters() => m_mi.GetParameters();
public object Invoke(object fixture, params object[] args)
{
var res = m_mi.Invoke(fixture, args);
Assert.Fail("Failure simulation");
return res;
}
public bool IsDefined<T>(bool inherit) where T : class => m_mi.IsDefined<T>(inherit);
public IMethodInfo MakeGenericMethod(params Type[] typeArguments) => m_mi.MakeGenericMethod(typeArguments);
}
[AttributeUsage(AttributeTargets.Assembly)]
public class EnableFailureSimulationAttribute : Attribute, ITestAction
{
private static string s_failTestMethod = GetParameterByName("!");
public ActionTargets Targets => ActionTargets.Test;
public void AfterTest(ITest test)
{
}
public void BeforeTest(ITest test)
{
if (test.MethodName == s_failTestMethod && test is Test testImpl)
{
testImpl.Method = new SimulateFailureMethodInfoWrapper(testImpl.Method);
s_failTestMethod = "!";
}
}
}
}
An alternative approach would be to use Moq and mock the IMethodInfo interface instead of having the real SimulateFailureMethodInfoWrapper class.
Anyway, this seems to work perfectly.
I have a class i want to change the properties of in the editor. So i made my class System.Serializable and made the variables public that i want to be able to change.
Like so:
[System.Serializable]
public class UIOptionsRing
{
public float Radius, DistanceBetweenPoints, StartOffset, GapInDegrees;
public int? GapAfterElementNumer = 3; //this var doesnt show up
public Vector3 CircleCenter;
public GameObject CircleElementsContainer;
}
But the problem i am having is that the GapAfterElementNumer is not show up in the editor at all the other fields are. How i can i make it so that int? also shows up?
Nullable types are not serialized in Unity Editor because it's serializer doesn't support null.
There's a small workaround if you're not going to serialize this class to json using JsonUtility.
The key idea is that you have to create your own nullable int. Something like
public class IntNullable
{
public int Value;
public bool HasValue;
}
Just like it's done inside .NET. Then you can create a Custom Editor for IntNullable or your UIOptionsRing. In this editor you can make a filed for int value and a button "Set Null", which will change the value of HasValue variable. And further you need to work with this custom IntNullable in your code.
Unity not only can't show nullable fields in the inspector, it cannot serialize them. In order to support this we need to make a custom version of System.Nullable (as #vmchar explains) that is serializable and then give it a property drawer. Making a seamless replacement for System.Nullable is not necessarily obvious, so I've included this example. It should be a drop in replacement for nullable ( int? can be replaced with SN<int> and all else should work due to the implicit casts) along with a basic custom property drawer.
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
/// <summary>
/// Serializable Nullable (SN) Does the same as C# System.Nullable, except it's an ordinary
/// serializable struct, allowing unity to serialize it and show it in the inspector.
/// </summary>
[System.Serializable]
public struct SN<T> where T : struct {
public T Value { get {
if (!HasValue)
throw new System.InvalidOperationException("Serializable nullable object must have a value.");
return v;
} }
public bool HasValue { get { return hasValue; } }
[SerializeField]
private T v;
[SerializeField]
private bool hasValue;
public SN(bool hasValue, T v) {
this.v = v;
this.hasValue = hasValue;
}
private SN(T v) {
this.v = v;
this.hasValue = true;
}
public static implicit operator SN<T>(T value) {
return new SN<T>(value);
}
public static implicit operator SN<T>(System.Nullable<T> value) {
return value.HasValue ? new SN<T>(value.Value) : new SN<T>();
}
public static implicit operator System.Nullable<T>(SN<T> value) {
return value.HasValue ? (T?)value.Value : null;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(SN<>))]
internal class SNDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
// Draw label
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// Don't make child fields be indented
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// Calculate rects
var setRect = new Rect(position.x, position.y, 15, position.height);
var consumed = setRect.width + 5;
var valueRect = new Rect(position.x + consumed, position.y, position.width - consumed, position.height);
// Draw fields - pass GUIContent.none to each so they are drawn without labels
var hasValueProp = property.FindPropertyRelative("hasValue");
EditorGUI.PropertyField(setRect, hasValueProp, GUIContent.none);
bool guiEnabled = GUI.enabled;
GUI.enabled = guiEnabled && hasValueProp.boolValue;
EditorGUI.PropertyField(valueRect, property.FindPropertyRelative("v"), GUIContent.none);
GUI.enabled = guiEnabled;
// Set indent back to what it was
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
#endif
It's performance may not be on par with System.Nullable, but it should be fine for most purposes. It's been serving me well so far in Unity 2021.1 with C# 4 enabled.
An improvement on vmchar's answer, which allows null assignment:
[Serializable]
public struct NullableInt
{
public int Value;
public bool HasValue;
public NullableInt(int value)
{
Value = value;
HasValue = true;
}
public static implicit operator NullableInt(int value) => new NullableInt(value);
public static implicit operator NullableInt(NullableNull value) => new NullableInt();
public static implicit operator int(NullableInt value) => value.Value;
public static implicit operator int? (NullableInt value) => value.HasValue ? value.Value : new int?();
}
public sealed class NullableNull
{
private NullableNull()
{ }
}
Is there any way to declare dependency property inside viewmodel? I want to declare a dependency property inside viewmodel and change it's value through command.
public class MyViewModel : Prism.Windows.Mvvm.ViewModelBase
{
public bool IsPaneVisible
{
get { return (bool)GetValue(IsPaneVisibleProperty); }
set { SetValue(IsPaneVisibleProperty, value); }
}
public static readonly DependencyProperty IsPaneVisibleProperty =
DependencyProperty.Register("IsPaneVisible", typeof(bool), typeof(MyViewModel), new PropertyMetadata(0));
public ICommand VisibilityChangeCommand { get; set; }
public MyViewModel()
{
VisibilityChangeCommand = new DelegateCommand(OnVisibilityChange);
}
private void OnVisibilityChange()
{
IsPaneVisible = !IsPaneVisible;
}
}
Problem is, I am getting some compilation error in IsPaneVisible' getter/setter : "GetValue does not exist in the current context". Is there any alternative way to do this?
A DependencyProperty is used on a DependencyObject, an example of this is a UserControl. Prism's ViewModelBase is no DependencyObject, mainly because this type is platform specific. To support binding from a viewmodel, we typically use INotifyPropertyChanged.
Prism implements this interface in the BindableBase base class, from which ViewModelBase derives as well. You define your properties like this:
private string _imagePath;
public string ImagePath
{
get { return _imagePath; }
set { SetProperty(ref _imagePath, value); }
}
If you install the Prism Template Pack Visual Studio extension, you can use the propp code snippet.
I want to bind my services to ListBox but I can't bind it.
//Service class
public class Service {
private String serviceName;
public Service(String serviceName) {
this.serviceName = serviceName;
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
}
// SignUpBean class
public class SignUpBean {
private List<Service> services;
public List<Service> getServices() {
return services;
}
public void setServices(List<Service> services) {
this.services = services;
}
}
The following is my Main Editor
public class SignUpEditor extends SimplePanelimplements Editor<SignUpBean> {
public ListBox services;
public void SignUpEditor (){
services.addItem("Service1");
services.addItem("Service2");
setWidget(services);
}
}
I am not getting any error but I think I have to use ListEditor or CompositeEditor. But i don't know about it. Can anyone suggest how to bind Service to ListBox
ListBox suppose to be a LeafValueEditor. Conceptually we don't edit the list in the ListBox. Rather We select a value from the list which will be displayed in the selection. So, ListBox holds only one value and thus ListBox must be leaf value Editor.
Currently there is no GWT support to directly bind the list to ListBox. We have to write an adapter which extends ListEditor ( Refer HasDataEditor class for more detail ). This approach is strange.
Simple approach is to write an adapter which implements LeafValueEditor< List < String > >. In adapter's setValue method we should iterate over the list and call listBox.addItem for each value in the list.
I don't recommend either approaches simply because ListBox's LIST is NON EDITABLE and only VALUE is EDITABLE. I recommend doing addItems manually without using Editors.
UPDATED : HasDataAdapter is an example ListEditor. Refer that implementation. You may get some idea.