Consider the following class:
[DebuggerDisplay("{GetType().Name,nq}: FileName = {FileName,nq}")]
public class FileWrapper
{
public string FileName { get; set; }
public bool IsTempFile { get; set; }
public string TempFileName { get; set; }
}
I would like to add a debugger display based on the IsTempFileName property. I would like to add the string , TempFileName = {TempFileName,nq} when the instance is a temp file. How would I achieve something this?
You can use the conditional operator (?:)
[DebuggerDisplay("{GetType().Name,nq}: FileName = {FileName,nq}{IsTempFile ? \", TempFileName: \" + TempFileName : System.String.Empty,nq}")]
IsTempFile == false
IsTempFile == true
You can use whatever expression is valid.
However, keep in mind that the debugger will evaluate these expressions a lot, so the more complicated you make them, the more you will start to noticed reduced debugging speed (e.g. when stepping through code).
Another major thing to consider is that the expression is evaluated by the debugger for the language using the class.
If both the class and all its potential users are in C#, there is no problem and you can use things like the ternary operator.
However, if your class is also to be used from another language, then:
there's no guarantee the debugger will even use the [DebuggerDisplay] attribute at all,
if it does, there's no guarantee that it will try to evaluate {expression} blocks, and
there's a very good chance that it will fail to evaluate your C# expression if you start doing anything fancy (like using ?:)
The safest thing would be to add a private property to compute the debugger value:
[DebuggerDisplay("{DebugValue,nq}")]
public class FileWrapper {
public string FileName { get; set; }
public bool IsTempFile { get; set; }
public string TempFileName { get; set; }
private string DebugValue {
get {
var text = string.Format("{0}: FileName={1}", this.GetType(), this.FileName);
if (this.IsTempFile)
text += string.Format(", TempFileName={0}", this.TempFileName);
return text;
}
}
}
It's a private property, so it doesn't get in the way of any potential subclasses.
First, upvote "sloth" answer before mine....because they got me going on the right direction.
Second, Here is an article:
https://devblogs.microsoft.com/visualstudio/customize-object-displays-in-the-visual-studio-debugger-your-way/
Below is the name of the article and the author, in case the link above dies in the future.
Customize object displays in the Visual Studio debugger YOUR way
Leslie Richardson
Program Manager, Visual Studio Debugging & Diagnostics
Third, here is a slightly more generic example based on a null or not null child collection:
[System.Diagnostics.DebuggerDisplay("ParentName = '{ParentName}', MyKidsCount='{null == MyKids ? 0 : MyKids.Count}'")]
public class MyParent
{
public string ParentName { get; set; }
public ICollection<MyKid> MyKids { get; set; }
}
You can use it with the Extensions method.
using System;
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;
namespace ConsoleApplicationDebuggerDisplay
{
class Program
{
static void Main(string[] args)
{
MyObject o1 = new MyObject();
MyObject o2 = new MyObject();
o1.Items = new int[] { 1, 2, 3, 4 };
}
}
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class MyObject
{
[DebuggerDisplay("{Items.ToDebuggerDisplay(),nq}")]
public int[] Items { get; set; }
[DebuggerBrowsable(DebuggerBrowsableState.Never), Browsable(false)]
internal string DebuggerDisplay
{
get
{
return string.Format("{{Items={0} ...}}"
, Items.ToDebuggerDisplay()
);
}
}
}
internal static class Extensions
{
public static bool IsNull(this object o)
{
return object.ReferenceEquals(o, null);
}
public static bool IsNotNull(this object o)
{
return !object.ReferenceEquals(o, null);
}
public static string ToDebuggerDisplay<T>(this System.Collections.Generic.IEnumerable<T> items)
{
if (items.IsNull())
return "null";
return string.Format("{{Count={0}}}", items.Count());
}
}
}
Watch
Related
I am trying to print two methods that i have created but i cant figure out how to do it.
My project consists of Language.cs file in addition to Program.cs
This method in Language.cs:
public static void PrettyPrintAll(IEnumerable<Language> langs)
{
foreach (var printsAll in langs)
{
Console.WriteLine(printsAll.Prettify());
}
}
Prints out this method that is also in Language.cs:
public string Prettify()
{
return $"{Year}, {Name}, {ChiefDeveloper}, {Predecessors}";
}
this method prints out every query result (is also in Language.cs):
public static void PrintAll(IEnumerable<Object> sequence)
{
foreach (var prints in sequence)
{
Console.WriteLine(prints);
}
}
Language class code other than the methods above:
namespace ProgrammingLanguages
{
public class Language
{
public static Language FromTsv(string tsvLine)
{
string[] values = tsvLine.Split('\t');
Language lang = new Language(
Convert.ToInt32(values[0]),
Convert.ToString(values[1]),
Convert.ToString(values[2]),
Convert.ToString(values[3]));
return lang;
}
public int Year
{ get; set; }
public string Name
{ get; set; }
public string ChiefDeveloper
{ get; set; }
public string Predecessors
{ get; set; }
public Language(int year, string name, string chiefDeveloper, string predecessors)
{
Year = year;
Name = name;
ChiefDeveloper = chiefDeveloper;
Predecessors = predecessors;
}
All the methods are within the Language.cs file.
My issue is that i do not understand how to print them, i have tried in many ways but always get an error code The name 'PrintAll' does not exist in the current context or something like that.
In main this is how i have tried to call the method PrintAll:
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year}
{languagePrint.Name} {languagePrint.ChiefDeveloper}");
PrintAll(stringLanguage);
The static method PrintAll() belongs to the class Language and calling it from another class requier to prepend the class name first, such as Language.PrintAll()
public static void Main()
{
// some code ...
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year} {languagePrint.Name} {languagePrint.ChiefDeveloper}");
// PrintAll(stringLanguage); <-- This won't work because there is no method PrintAll() in the current class
// This now refers to the correct class where the method belongs
Language.PrintAll(stringLanguage);
}
Another way to do that would be to include the static part of the class Language in the class where Main is (I assume the class Program) :
// replace namespace by the correct namespace of the class
using static namespace.Language;
class Program
{
public static void Main()
{
// some code ...
var stringLanguage = languages.Select(languagePrint => $"{languagePrint.Year} {languagePrint.Name} {languagePrint.ChiefDeveloper}");
// This now works because the static parts were imported
PrintAll(stringLanguage);
}
}
However, I discourage using this, because this may lead to confusion
Thanks in advance!
We have some Automation tests using the selenium web driver which are great and provide a really good regression pack.
The problem is now we have feature toggles in our code. So I need to say ignore these tests unless that feature toggle is turned On/ Off. I can't find anything really searching Google.
Ideally I don't want a 'if' statement at the top of the Feature tests but it looks like it's going to be the main way. My initial thoughts where to create a custom attribute
public class IsFeatureFlagTurnedOn : Attribute
{
public IsFeatureFlagTurnedOn(string featureToggleName)
{
FeatureToggleName = featureToggleName;
}
public string FeatureToggleName {get;}
}
public class MyTests
{
[TestMethod]
[IsFeatureFlagTurnedOn("MyFeature1")]
public void ItShould()
{
// only run if MyFeature1 is turned on
}
}
I some how need to hook into the MSTest pipeline and say if this attribute is present and the logic for MyFeature1 is turned off then don't run this test - Looked at dynamically adding the [Ignore] but with no luck.
This is running through VSTS and I could use [TestCategories] but I'd have to keep updating the pipeline to which feature is turned on/off which I don't want to do.
Any help or suggestions would be great!
MSTest v2 now has a lot of extensibility points, and you can achieve this by extending the TestMethodAttribute. First we add two attribute arguments, a string for a property name and a Type that has the property. Then we override the Execute method and invoke the property via reflection. If the result is true, we'll execute the test as normal, otherwise we return an 'inconclusive` test result.
public class TestMethodWithConditionAttribute : TestMethodAttribute
{
public Type ConditionParentType { get; set; }
public string ConditionPropertyName { get; set; }
public TestMethodWithConditionAttribute(string conditionPropertyName, Type conditionParentType)
{
ConditionPropertyName = conditionPropertyName;
ConditionParentType = conditionParentType;
}
public override TestResult[] Execute(ITestMethod testMethod)
{
if (ConditionParentType.GetProperty(ConditionPropertyName, BindingFlags.Static | BindingFlags.Public)?.GetValue(null) is bool condiiton && condiiton)
{
return base.Execute(testMethod);
}
else
{
return new TestResult[] { new TestResult { Outcome = UnitTestOutcome.Inconclusive } };
}
}
}
Now we can use our new attribute like this:
[TestClass]
public class MyTests
{
[TestMethodWithCondition(nameof(Configuration.IsMyFeature1Enabled), typeof(Configuration))]
public void MyTest()
{
//...
}
}
public static class Configuration
{
public static bool IsMyFeature1Enabled => false;
}
The above is a very generic solution. You could also customize it a little more to your particular use case to perhaps avoid quite so much verbosity in the attribute declaration:
public class TestMethodForConfigAttribute : TestMethodAttribute
{
public string Name { get; set; }
public TestMethodForConfigAttribute(string name)
{
Name = name;
}
public override TestResult[] Execute(ITestMethod testMethod)
{
if (IsConfigEnabled(Name))
{
return base.Execute(testMethod);
}
else
{
return new TestResult[] { new TestResult { Outcome = UnitTestOutcome.Inconclusive } };
}
}
public static bool IsConfigEnabled(string name)
{
//...
return false;
}
}
And use it like:
[TestClass]
public class MyTests
{
[TestMethodForConfig("MyFeature1")]
public void MyTest()
{
//...
}
}
Based on my reading of this, you may need to use Assert.Inconclusive
public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.
There is tons of info about skipping Properties based on conditionals, but I would like to skip the entire object based on conditions within the object's class. I would like a solution that is contained within the object's class if at all possible. Keep in mind this is a collection of myObj that I am serializing.
public class myObj
{
bool conditional;
ShouldSerialize()
{
return conditional;
}
}
Or
public class myObj
{
[JsonCondition]
public bool conditional{get;}
}
Or even
[JsonCondition(typeof(MyConditionChecker))]
public class myObj
{
public bool conditional{get;}
}
class MyConditionChecker: JsonCondition
{
public override bool CanConvert(object sourceObj)
{
return (sourceObj as myObj).conditional;
}
}
What I got from your comments you would be best served creating your own wrapper around Json that applies the filtering.
public interface IConditionalSerializer
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional<T>(IEnumerable<T> input)
where T : IConiditionalSerializer
{
return JsonConvert.SerializeObject(input.Where(e => e.ShouldBeSerialized()));
}
}
public class Demo : IConditionalSerializer
{
public bool ShouldBeSerialized() => false;
}
You might also replace the interface with a reflection approach, but keep in mind the performance loss.
public interface IConiditionChecker
{
bool ShouldBeSerialized(object instance);
}
public class ConditionAttribute : Attribute
{
public Type ConditionChecker { get; set; }
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let att = entry.GetType().GetCustomAttribute<ConditionAttribute>()
let hasChecker = att != null && att.ConditionChecker != null
let checker = hasChecker ? (IConiditionChecker)Activator.CreateInstance(att.ConditionChecker) : null
where checker.ShouldBeSerialized(entry)
select entry);
return JsonConvert.SerializeObject(matches);
}
}
[Condition(ConditionChecker = typeof(SomeChecker))]
public class Demo
{
}
Edit: Based on your comment you could do this. Only must decide wether to use opt-in or opt-out in the where-statement. It must ether be casted != null && casted.ShouldBeSerialized or what it currently says.
public interface IShouldBeSerialized
{
bool ShouldBeSerialized();
}
public static class FilteredSerializer
{
public static string SerializeConditional(IEnumerable<object> input)
{
var matches = (from entry in input
let casted = entry as IShouldBeSerialized
where casted == null || casted.ShouldBeSerialized()
select entry);
return JsonConvert.SerializeObject(matches);
}
}
public class Demo : IShouldBeSerialized
{
public bool ShouldBeSerialized()
{
return false;
}
}
If you're able to use the JSON.NET serializer, in terms of not serializing specific items within a collection, you could make the main collection non serializable, then add another filtered collection that does serialize.
public class Manager
{
[JsonIgnore]
public Employee[] Employees { get; set; }
[JsonProperty("Employees")]
public Employee[] SerializableEmployees
{
get { return Employees.Where(e => e.Name != "Bob").ToArray(); }
set { Employees = value; }
}
}
Alternatively, you could mark your class with the [JsonConverter] attribute and use a custom converter to check your condition. A similar approach that ignores a class entirely is detailed here.
I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}