Using Roslyn, I'm to get the constant value of the following string parameter in this method call:
inst.someMethod($"{Constants.SomeValue}");
static class Constants
{
public static readonly string SomeValue= "some value";
}
I got an instance of InterpolatedStringExpressionSyntax type for the $"{Constants.SomeValue}" parameter.
Next, I need to get its value (which is the "Some value" string), and I tried to call semanticModel.GetConstantValue(expr); but it returns null
How can I get that value?
1) SemanticModel.GetConstantValue works only for compile time constant members, so you cannot use it to get a value of readonly field.
2) If you want to get a value of readonly field you actually need to analyze field initializer and constructors in the common cases to determine where and how this field was created and so on.
But in you simple example above, when you have a static class and static readonly field with initializer you can make something looks ike this:
InterpolatedStringExpressionSyntax interpolatedExpression = // you received it before
// as you know that your member is the first contet of InterpolatedStringExpressionSyntax
var symbolInfo = semanticModel.GetSymbolInfo(((interpolatedExpression).Contents[0] as InterpolationSyntax).Expression);
if (!(symbolInfo.Symbol is null))
{
// assume that exists only a one declaration
var fieldDeclaration = symbolInfo.Symbol.DeclaringSyntaxReferences[0].GetSyntax() as VariableDeclaratorSyntax;
if (!(fieldDeclaration is null))
{
// retrieves text from `SomeValue = "some value"`
var text = (fieldDeclaration.Initializer.Value as LiteralExpressionSyntax)?.Token.Text;
}
}
Related
Is there a way to make a function use its optional parameter's value? For example, say I have,
public void myFunction(bool required, string optional = "This is optional") {...}
and I want to do something like this,
string possiblyNull = null; // the result of another function
myFunction(true, possiblyNull ?? possiblyNull : optional)
C# compiler embeds the parameter’s default value whenever arguments are left out at the call site. And in your case your want to call your method with that parameter. So, it is not possible, so you have to use that check either outside or inside of your method. If you really want to prevent using if clause while calling your mehtod, then you can change signature of your method so:
public void myFunction(bool required, string optional)
{
optional = optional ?? "This is optional";
...
}
And then call it so:
string possiblyNull = null; // the result of another function
myFunction(true, possiblyNull)
You can't get the default value at the call site. You'd need to have a check outside the method call.
string possiblyNull = null;
// ...
if (possiblyNull == null)
myFunction(true);
else
myFunction(true, possiblyNull);
If your concern is that
You don't want to just make null the default because that would mean the default wouldn't appear in Intellisense and the caller wouldn't see the default
You could make some value the default and then check for null, and if it's null replace it with the default, but that would mean putting the default in two places
You could do this:
private const string OptionalValue = "This is optional!";
public void myFunction(bool required, string optional = OptionalValue)
{
optional = optional ?? OptionalValue;
}
Now you get both. The default shows up in Intellisense and it's not repeated.
If it's just that you
might need to pass a null value
want to get the default value
have to do so frequently enough that it's annoying
can't modify the original method
you could create an extension for the class containing the method:
public static class Extension
{
// I can't think of how this function name would not be awkward.
public static void MyFunctionThatReplacesNullWithDefault(
this ClassWithOptionalMethod target, bool required, string optional = null)
{
if(optional == null)
target.myFunction(required);
else
target.myFunction(required, optional);
}
}
you are quite there but you only need to remove possiblyNull: while you passing the parameter to the method,
you can do like this...
public partial class MainWindow : Window
{
private string optional = "Test";
string possiblyNull = null;
public MainWindow()
{
InitializeComponent();
// here you can check null
myFunction(true, possiblyNull ?? optional);
// Or
myFunction(true);
}
public void myFunction(bool required, string optional = "This is optional")
{
MessageBox.Show(optional);
}
}
When attempt to fill an array in C# with my custom type class, the array populates with the class's location in the namespace. However, I need the array to populate with the values I specified with that type.
I have tried defining my array using each of these implementations with the same results:
List<FieldName> fieldNames = new List<FieldName>() { "event_ref", "user_id", "sys_time" };
FieldName[] fieldNames = { "event_ref", "user_id", "sys_time" };
In both cases the values that get implemented in the lower function calls (nothing fancy) is ElectronicSJP.DatabaseIF.FieldName for all three of the fields.
Upon setting a breakpoint, I can see that fieldNames is populated as so:
The values that I specified are at the next level down, if that table is expanded. My class for FieldName is defined as such:
class FieldName
{
private string name = "";
public static implicit operator string(FieldName fn)
{
return (fn == null) ? null : fn.name;
}
public static implicit operator FieldName(string fn)
{
return new FieldName { name = fn };
}
}
I suspect that I may need to add another implicit operator, or two, so I could use some help with that or any other ideas you think could fix this problem. Thanks.
When the debugger shows an object, or list of objects, it will show the type rather than a particular field.
In order to see a "user friendly value", one can either override the toString method that exists on the Object class, or you can decorate the property you want shown with the DebuggerDisplay Attribute (credit to Adam V up above in the comments!)
example:
public override string ToString()
{
return name;
}
Link to how to override a method. https://msdn.microsoft.com/en-us/library/ms173154.aspx
I have to following in vb.net and am having a rough time converting to c#. The fieldlist is a class that has several properties however only 2 are relevant for the below procedure. The code to call the procedure looks like myClass.Fields("Test") = 123456. The converters all drop the fieldname from the property. If I add it back then I get The name 'value' does not exist in the current context.
VB.net - works fine in VB
Public WriteOnly Property Fields(ByVal fieldName As String) As Object
Set(ByVal value As Object)
If mvarFieldData Is Nothing Then mvarFieldData = New FieldList
If mvarFieldData(fieldName) Is Nothing Then
mvarFieldData.Add(fieldName, value)
Else
mvarFieldData(fieldName).FieldValue = value
End If
End Set
End Property
c# - I'm doing something wrong here.
public object Fields(string fieldName)
{
set {
if (mvarFieldData == null)
{mvarFieldData = new FieldList();}
if (mvarFieldData[fieldName] == null)
{
mvarFieldData.Add(fieldName, value);
} else {
mvarFieldData[fieldName].FieldValue = value;
}
}
}
c# Converters(telerik) provide the below
public object Fields {
set {
if (mvarFieldData == null)
mvarFieldData = new FieldList();
if (mvarFieldData(fieldName) == null) {
mvarFieldData.Add(fieldName, value);
} else {
mvarFieldData(fieldName).FieldValue = value;
}
}
}
What is the scope of mVarFieldData, and what is it's exact type? It seems like it is a Collection of some sort.
The c# code above is not compilable as you are trying to mix a method syntax with a property syntax.
property:
public object Fields{ get; set{mvarFieldData = value;} }
Method:
public object Fields(string fieldname, object val){ mvarFieldData[fieldname] = val;}
By the looks of the decision making going on in the VB.Net property, I would think a public method may suit the situation better. I normally just use property's when a very minimum amount of validation is needed when setting a encapsulated type member.
Hope this helps.
You actually have a couple problems here.
Problem 1: Properties don't take arguments.
C# properties can't be passed an argument/parameter the way you're passing fieldname. There are a couple different ways you could solve this:
You can make an index property (used with myObject[fieldName] = blah rather than myObject.Fields[fieldName] = blah). Use the syntax public object this[string fieldName] to declare the property.
Since your property doesn't have a getter, you can just turn it into a single method with signature public void SetField(string fieldName, object value), called like so: myObject.SetField(fieldName, value).
You can expose mvarFieldData through a getter property: public Dictionary<?, ?> Fields { get { return mvarFieldData; } } which will let users access the dictionary (I assume that's what it is, based on usage) directly.
Problem 2: The key may not exist.
I'm not sure about dictionaries (or whatever similar structure mvarFieldData is) in VB.NET, but in C# there's a difference between a key whose value is null and a key that's not present in the structure.
var dict = new Dictionary<int, string>();
dict.Add(1, null);
if (dict[1] == null)
Console.WriteLine("This line will be displayed.");
if (dict[2] == null)
Console.WriteLine("The line above this one will throw an exception.");
In addition to your present code, you need a check for mvarFieldData.ContainsKey(fieldName) before you start checking the value associated with fieldName.
I have created the following class based on a Singleton Pattern:
public sealed class UTrans
{
private static volatile UTrans _instance;
private static readonly object syncRoot = new Object();
private UTrans(){}
private static UTrans Instance
{
get
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
_instance = new UTrans();
}
}
return _instance;
}
}
}
Within this Class I have created an enum property and string property
private static MethodType _method; // Alphabectic 1 - 50
public static MethodType Method
{
get { return _method; }
set { _method = value; }
}
private static string _uName;
public static string UserName
{
get { return _uName; }
set { _uName = value; }
}
I also have some methods that take a number of arguments in this class. When I call the class instance in code, if the user assigns values to the properties; those values will be used. Otherwise, the values passed as arguments will be used.
This works fine in the case of the UserName property by checking for a null value on the property:
var un = UserName ?? user;
However I cannot perform the same check for the enumeration property because it seems that the property automatically assumes the 1st value of the enumeration if one is not assigned.
I tried to circumvent the issue by assigning the 1st value of the enum as "Unspecified". Then I may proceed to code as such:
var processMethod = TranslateMethodType(Method) == "Unspecified" ? method : Method;
Where TranslateMethodType is a private method that converts the selected enumeration to a equivalent string value.
I don't believe this is the most elegant approach to the issue though and would like some feedback on possible alternatives to this issue.
Is there a way to check that a value has not been set for the MethodType property by the user of the class without having to add an "Unspecified" value as the first value since this value is ONLY there as a way to indicate no value was set?
Obviously, this may not be the case if the user decides to use the value and it would yield undesirable results to construct the code this way.
Can a enumeration Method be marked as nullable???
Can a enumeration Method be marked as nullable???
Yes.
public Nullable<MyEnum> Bob(){
//stuff
}
var bob = Bob() ?? MyEnum.Default;
Yes, you can make the Method field/property nullable.
private static MethodType? _method; // Alphabectic 1 - 50
public static MethodType? Method
{
get { return _method; }
set { _method = value; }
}
Then you can do
var processMethod = Method == null ? method : Method.Value;
or
var processMethod = Method.HasValue ? Method.Value: method;
You can mark it as nullable however what you're experiencing is expected behaviour.
Value types that are members of a reference type are initialized to 0. This is why you should always provide a value of 0 for your enums. If you don't, then users of your class will never know that the class has invalid state.
here a solution is given to get value of a property of a class by supplying its name . now I wonder how I can do the same in this condition :
I have a class MyClass . this class ha a property of type Foo named foo . the Foo has a property of type Bar named bar . and bar has a string property named value .
properties are not static .
I want to be able to get value of foo.bar.value by passing the string "foo.bar.value" as propertyName . in other word I want to pass the property path to get its value .
is it possible ?
You can do this with a recursive method. Each call takes the value with the first word in path and call the method again with the rest of the part.
public object GetPropertyValue(object o, string path)
{
var propertyNames = path.Split('.');
var value = o.GetType().GetProperty(propertyNames[0]).GetValue(o, null);
if (propertyNames.Length == 1 || value == null)
return value;
else
{
return GetPropertyValue(value, path.Replace(propertyNames[0] + ".", ""));
}
}
This assumes that the properties are named like the classes. i.e. that the property of Type Foo is also named Foo. Without this assumption, the question is lacking some crucial information.
You can use the string.Split method to separate the string foo.bar.value at the dots. You will then have an array with one element per property name.
Iterate over that array and use PropertyInfo.GetValue to retrieve the value of the properties. The value returned in one operation is the instance passed to GetValue in the following iteration.
string props = "foo.bar.value";
object currentObject = // your MyClass instance
string[] propertyChain = props.Split('.');
foreach (string propertyName in propertyChain) {
if (propertyName == "") {
break;
}
PropertyInfo prop = currentObject.GetType().GetProperty(propertyName);
currentObject = prop.GetValue(currentObject);
if (currentObject == null) {
// somehow handle the situation that one of the properties is null
}
}
Update: I have added a safeguard to ensure this will work even if props is empty. In that case, currentObject will remain a reference to the original MyClass instance.
Assuming FOO is static, you can get the class from a string like this:
C# Reflection: How to get class reference from string?
...and then use the rest of the post you've linked to to get the property and value from there:
Get property Value by its stringy name
If FOO isn't static, you'll need to use reflection on the instance (which would negate the requirement to pass in the name of the class as a string, since you can get the class from the instance with GetType()) - remembering that Bar won't have a value in the class unless it is static.
As You pointing to answer of the question here , You need to make use of Reglection to achieve same thing.
With help of reflection you can read value of property.
something like this,
// dynamically load assembly from file Test.dll
Assembly testAssembly = Assembly.LoadFile(#"c:\Test.dll");
// get type of class Calculator from just loaded assembly
Type calcType = testAssembly.GetType("Test.Calculator");
// create instance of class Calculator
object calcInstance = Activator.CreateInstance(calcType);
// get info about property: public double Number
PropertyInfo numberPropertyInfo = calcType.GetProperty("Number");
// get value of property: public double Number
double value = (double)numberPropertyInfo.GetValue(calcInstance, null);
you need a put the code in one function and than split string as per you requirement
public object getvalue(string propname)
{
//above code with return type object
}
String[] array = string.Split("foo.bar.value");
//call above method to get value of property..
Read for detail : http://www.csharp-examples.net/reflection-examples/