Generically get the name of the current class? - c#

When logging data, I want a generic reference to the containing class. That way, if the code is moved elsewhere, the class name will change accordingly. (Otherwise, if the code moves to nameof(Class2), it will still be logged incorrectly as nameof(Class1)). For example:
class Class_Name {
ICommand Command_Name =>
new RelayCommand(() =>
{
// An loggable event occurs
// Is there a smart and uncomplicated way of doing this generically?
var provenance = $"{nameof(Class_Name)}.{nameof(Command_Name)}";
// The event of whatever kind gets logged
});
}
// OR
void Method_Name() {
var provenance = $"{nameof(Class_Name)}.{nameof(Method_Name)}";
}
}
Using a generic nameof(this), where this should refer to the class itself, causes a compilation error: CS8081: Expression does not have a name. Using this.GetType() causes the same problem.
Not really understanding why the this keyword does not refer to the containing class in this context. Is there a way to refer to the current class generically?

If you combine the suggestion in the comments (this.GetType().Name) with a [CallerMemberName] attribute via a helper method, you can accomplish what you're looking for in a reusable fashion.
public class Class_Name
{
public void Method_Name()
{
var provenance = CreateProvenance();
Console.WriteLine(provenance);
}
private string CreateProvenance([CallerMemberName] string methodName = "")
{
return $"{this.GetType().Name}.{methodName}";
}
}
This outputs "Class_Name.Method_Name".
You can even turn this into a handy extension method that allows you to call it from any method.
public class Class_Name
{
public void Method_Name()
{
var provenance = this.CreateProvenance();
Console.WriteLine(provenance);
}
}
public static class ProvenanceExtensions
{
public static string CreateProvenance(this object context,
[CallerMemberName] string methodName = "")
{
return $"{context.GetType().Name}.{methodName}";
}
}
As Jeppe Stig Nielsen pointed out, you may not want the inheriting runtime type to be used, which is what context.GetType().Name will return. If you want to get the compile-time type instead, you can use generics.
public static class ProvenanceExtensions
{
public static string CreateProvenance<T>(this T context,
[CallerMemberName] string methodName = "")
{
return $"{typeof(T).Name}.{methodName}";
}
}

By design:
A nameof expression is evaluated at compile time and has no effect at
run time.
To access the type dynamically, in the runtime, you may use the GetType method. Just rememeber not to combine it with the nameof.
class Class_Name {
void Method_Name() {
// An event occurs
// Is there a smart and uncomplicated way of doing this generically?
var provenance = $"{this.GetType().Name}.{MethodBase.GetCurrentMethod().Name}";
// The event of whatever kind gets logged
}
}

Related

How can I add a default constructor and have it call another constructor and use the default values?

I have this code:
public class NewFrame
{
public NewFrame(string iconSource = Const.Car,
string iconColor = Const.Red)
{
When I try and use it then it's telling me I am missing a default constructor. How can I add one of these and still make the code use the default values for iconBackgroundColor and IconSource? I thought that adding in those defaults with the = Const. would make it work but it seems like it doesn't think my constructor is a default (with no params).
You just have to add another empty overload and call the required constructor with defaults. See below:
public class NewFrame
{
public NewFrame() : this(Const.Car, Const.Red){
}
public NewFrame(string iconSource,
string iconColor)
{
...
}
}
By having two optional parameters, you don't actually create 4 different constructor declarations under the hood (one with both parameters, one with the first parameter, one with the second parameter, and one with neither). There is still only one constructor, with two parameters. It's just that C# recognises that the parameters are optional, and has syntactic sugar to let you omit them when you call the constructor.
However, if you use reflection to create an instance of your class (probably whatever the thing that requires a default constructor is doing), and you attempt to invoke the parameterless constructor, it won't find one, because there is no syntactic sugar in reflection.
Here is an example:
class MainClass
{
public static void Main(string[] args)
{
Type t = typeof(MainClass);
object o = Activator.CreateInstance(t, 1);
Console.WriteLine(o);
}
public MainClass(int a = 10)
{
}
}
If you use typeof(MainClass).GetConstructors(), it will tell you that there is only one.
To actually declare a default constructor, you can do:
public class NewFrame
{
public NewFrame(string iconSource = Const.Car,
string iconColor = Const.Red)
{
...
}
public NewFrame() : this(Const.Car, Const.Red) { }
}
For what it's worth, when I do something like this, I take the route that #VyacheslavBenedichuk's answer is showing.
I'm not sure what your complaint is. This code compiles for me:
public class TestConstructor
{
public TestConstructor(string what = Const.Car, string color = Const.Red)
{
}
public static void Test()
{
var tc = new TestConstructor();
}
public class Const
{
public const string Car = "car";
public const string Red = "red";
}
}
What do your definitions of Const.Car and Const.Red look like? Where are you seeing the error?
But, if you use something that requires a default constructor, then this will not work. For example, this will fail at runtime:
var tc2 = Activator.CreateInstance(typeof(TestConstructor));
Please, when you are reporting an error, describe it exactly - in particular say whether it's a runtime or a compile-time error, the exact wording of the error, and the context in which the error occurs. In this case (the call to CreateInstance) will result in a System.MissingMethodException: 'No parameterless constructor defined for this object.'
In this case, you need to follow #VyacheslavBenedichuk's advice

What is the difference between returning a value inside a get, and assigning the property?

If I wanted to keep this handy for non async methods that return task.
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
public static Task CompletedTaskB { get; } = Task.CompletedTask;
Should one be preferred over the other for any kind of context? Or are they the same? I also wonder the same with strings and basically anything i do with properties ie:
get {return "some string"; } vs { get; } = "some string";
EDIT: I would like to clarify my usage of the above prop. I have several event handlers which have Task as a return type, offered to me by a library i'm using. an example of one such event:
private Task Client_MessageReceived(Message message)
{
Task.Run(async ()=> await HandleMessageReceived(message));
// here is where i would use it
return CompletedTask; // A OR B?
}
private async Task HandleMessageReceived(Message message)
{
// Do stuff with message that might take long and block the handler
}
My intention is to save a completed task in a field (i'm choosing a readonly property in this case) and just keep using it to satisfy the task return. I am wondering if one of the above examples, keeps using the same completed task, and the other one keeps asking for another completed task every time?
If you go to SharpLab and look at the code for:
public class C
{
public void M()
{
}
public string Greetig_1
{
get{return "hello";}
}
public string Greeting_2{get;} = "hello";
}
You can see that Greeting_2 is backed by a member variable:
public class C
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly string <Greeting_2>k__BackingField = "hello";
public string Greeting_1
{
get
{
return "hello";
}
}
public string Greeting_2
{
[CompilerGenerated]
get
{
return <Greeting_2>k__BackingField;
}
}
public void M()
{
}
}
This follows through to the IL level. As Greeting_2 is backed by a member variable that variable is initialized in the constructor.
In your example with Task.CompletedTask what you end up with is:
public static Task CompletedTaskB { get; } = Task.CompletedTask;
Caching the Task, whereas:
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
Make a call to get the CompletedTask object in Task each time. In reality this will be inline by the JIT. The approach also has the advantage of not adding an additional (hidden) member variable to your class, which may be an issue if you've got lots of instances and are concerned about memory usage.
They are not the same.
A properties get method is called every time you access it. By default when you create a property, it will have a hidden field behind it so:
public static Task CompletedTaskB { get; set; }
will actually generate this behind the scenes:
private static Task _completedTaskB;
public static Task CompletedTaskB
{
get {
return _completedTaskB;
}
set {
_completedTaskB = value;
}
}
When you assign the property = Task.CompletedTask, you are setting its initial value which is equivalent to :
_completedTaskB = Task.CompletedTask;
When you then access the property, it will read from the private field.
I notice though that you are defining this as readonly (only a getter not a setter) so you will not be able to assign the variable. Instead you will have to use:
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
This will return Task.CompletedTask all the time.
In general the difference between:
{ get; set; } = "some string";
and
get {return "some string"; }
is that the first is an initial assignment whereas the latter is a method that is called whenever you access the property.
When you assign a value to the property right at the definition, some "magic" happens behind the scenes.
The compiler creates a hidden backing field, and the value is assigned to that backing field in the constructor of the class.
In other words, you can think of the two classes below as working the same way.
class AssignedImplicit {
public string Prop {get;} = "example";
}
class AssignedExplicit {
private readonly string Prop_BackingField;
public AssignedExplicit() {
Prop_BackingField = "example";
}
public string Prop { get { return Prop_BackingField; } }
}
When you just define a get method without assigning, the backing field is not created, and no work is added to the constructor.
This is true for strings, or for any other type.
If you assign a value to the property, the work of constructing/fetching that value is put into the constructor of your class. If you create the value in the get method, then the work is put into the get method.

Using IsValueCreated before accessing LazyLoadObject.Value

I'm working with some C# code that's using .Net 4 Lazy loads and I'm not super familiar with it. I'm trying to figure out if this particular code is useless or not.
Originally the property and code below where in the same class, but now I've moved the code to an external class that no longer has access to the private "lazyRecords" property. I'm wondering what the point of checking "lazyRecords.IsValueCreated" is since the lazyRecords.Value has not been invoked yet, wouldn't it always be false? Or is it checking to see if another thread somehow invoked the Value? Or is it doing this in case of a thread exception that resulted in not loading the object?
Property:
private Lazy<List<Record>> lazyRecords;
public List<Record> Records
{
get
{
return lazyRecords.Value;
}
set
{
lazyRecords = new Lazy<List<Record>>(() => value);
}
}
Code:
public Category LoadCategory(BaseClient client)
{
Category category = new Category();
category.Records = client.RecordClient.GetRecordsByCategoryID(category.ID);
if (lazyRecords.IsValueCreated)
{
category.WorldRecord = category.Records.FirstOrDefault();
}
else
{
category.WorldRecord = client.RecordClient.GetWorldRecord(category.ID);
}
}
The code is pretty useless, yes. To help you understand why, consider this very minimal version of Lazy (the real class has more options and logic to take care of multiple threads, but this is the rough idea):
public class Lazy<T>
{
private readonly Func<T> _creator;
private T _cachedValue;
public Lazy(Func<T> creator) => _creator = creator;
public bool IsValueCreated { get; private set; }
public T Value
{
get
{
if (!IsValueCreated)
{
_cachedValue = _creator();
IsValueCreated = true;
}
return _cachedValue;
}
}
}
The delegate passed to the constructor is called on demand, the first time the Value is requested. In the code you've posted there is no point to this because the delegate simply returns the value passed into the setter.
As to the LoadCategory method, the code you posted is hard to decipher. It directly accesses lazyRecords, implying it's a method of the same class. But then it accesses Records on a different object.

Execute function kept in the attribute upon property change

I have a property with has an attribute, which in turn has Func<object, object>, I want that function to be executed (using the updated property's value as in T) upon the property change. What's the slickest way of doing so?
Note: I'm aware of the facts that Attributes are static and aren't designed to be executed upon their assignees change/invocaction. I just need to get it working as close as can to the prototype I've created.
Some code:
using System;
using System.Windows;
namespace AnnotatedBinding
{
public class AnnotatedPropertyAttribute: Attribute
{
// static
public AnnotatedPropertyAttribute(Func<object, object> evaluator)
{
Evaluator = evaluator;
}
public Func<object, object> Evaluator
{
get; private set;
}
}
public class Test
{
[AnnotatedProperty(Test.TestEvaluator)] // not compiling!, guess it's fixable by passing in a member info and then calling Reflection Invoke?
public string TestProperty
{
get; set;
}
public static Func<object, object> TestEvaluator = (x) => MessageBox.Show(x.ToString());
}
public class Shell
{
public void Run()
{
var test = new Test();
test.TestProperty = "blah";// I want my message box here
test.TestProperty = "blah";// and I don't want it here
}
}
}
Your attribute on the TestProperty does not compile because delegates are not allowed as attribute arguments. See this answer from Eric Lippert for details about which types are allowed.
Regarding a workaround using reflection: You could certainly specify the type owning the method, and the name of the method in the attribute since System.Type and string are valid attribute argument types. Something like this:
[AnnotatedProperty(typeof(Test), "TestEvaluator")]
public string TestProperty { get; set; }
However, this still won't do anything with the delegate when the property is set. Attributes are only metadata that you can read out during runtime using reflection (more specifically using MemberInfo.GetCustomAttributes(...)), analyse them and perform any operation based on the attribute values. This all needs to be done manually. Unfortunately, the .NET framework does not offer the functionality to automatically perform some operation based on the attributes that are applied to a member. This would make life a lot easier for property change notifications as well.
So you would have to implement the handling of the attributes manually. That means, implementing the get and set accessors, checking whether the attribute is applied to that property, determine the delegate that should be executed, and exeute it using reflection. Of course, that does not make sense because you would rather add a call to the method in the setter instead.
tl;dr:
Possible solution: You should have a look at PostSharp, a library supporting aspect-oriented programming in .NET. It can be used to inject boiler-plate code into methods or other members after compilation. It does this by analyzing your MSIL code and searching for so-called "aspects" (which are actually attributes, like yours). If found, it modifies the MSIL as specified by the attribute. You would have to derive your attribute from a PostSharp base attribute/aspect and then override the appropriate methods. In your case, you would have to derive from the LocationInterceptionAspect and then override the OnSetValue(...) method. In this method you would determine the delegate using the attribute arguments (as given above) and then call this using reflection. "Intercepting Properties and Fields" in the PostSharp documentation gives a very good introduction how to do this.
I think you would end up with something like this:
public class ExecuteDelegateOnPropertySetAspect : LocationInterceptionAspect
{
public ExecuteDelegateOnPropertySetAspect(Type methodOwner, string methodName, object[] arguments)
{
this.MethodOwner = methodOwner;
this.MethodName = methodName;
this.Arguments = arguments;
}
public Type MethodOwner { get; set; }
public string MethodName { get; set; }
public object[] Arguments { get; set; }
public override void OnSetValue(LocationInterceptionArgs args)
{
// get method with the specified name from the specified owner type
MethodInfo method = this.MethodOwner.GetMethod(this.MethodName);
// method must be static, otherwise we would need an instance to call it
if (method != null && method.IsStatic)
{
if (method.GetParameters().Length == this.Arguments.Length)
{
// call the method with the given arguments
method.Invoke(null, this.Arguments);
}
}
// execute the original setter code
args.ProceedSetValue();
}
}
And in your code you would apply this aspect to your properties:
public class Test
{
public static void TestMethod(string someMessage)
{
MessageBox.Show(someMessage);
}
[ExecuteDelegateOnPropertySetAspect(typeof(Test), "TestMethod", new object[] { "Hello world!" })]
public string TestProperty { get; set; }
}
Note that I omitted most of the error and null checking to keep it simple and short.
You seem to have misunderstood the concept of properties in C#.
The properties have a getter and setter function. They will automatically get executed when you set the property or get its value.
So all you need to do is to change the set function of your property to something like this:
public class Test
{
private string _testProperty;
private bool testPropertyIsSet = false;
public string TestProperty
{
get { return this._testProperty; }
set
{
_testProperty = value;
if (!testPropertyIsSet)
{
// Do something here when your property gets set for the first time
}
testPropertyIsSet = true;
}
}
}
Then call it:
public void Run()
{
var test = new Test();
test.TestProperty = "blah";
test.TestProperty = "blah2";
}

C# Extension methods on "members"

I have some extension methods which could be used like this:
MyType myObject;
string displayName = myObject.GetDisplayName(x => x.Property);
The problem here is that it needs an instance, even if the extension method only needs the type MyType. So if there is no instance, it needs to be called like this:
string displayName = BlahBlahUtility.GetDisplayName((MyTpe x) => x.Property);
Which is not so nice anymore.
Is there a way to write better syntax for such cases?
What I actually want to do is this (pseudo language):
string displayName = MyType.Property.GetDisplayName()
Which of course does not work with C#.
But what about something like this:
string displayName = ((MyType x) => x.Property).GetDisplayName();
This is also not possible (after a lambda, a dot is not accepted).
Any ideas?
Edit:
My "favorite syntax" MyType.Property.GetDisplayName() seems to be misleading. I don't talk about static properties here. I know that this syntax won't be possible. I just tried to show in pseudo language, what information is necessary. This would be ideal, every additional stuff is just syntactical overhead. Any working syntax that is close to this would be great.
I don't want to write a certain extension method. I want an easy, readable and compile time safe syntax, using any language feature.
Have a look at the Express and Reflect classes in the Lokad Shared Libraries. Think they may help out with what you are trying to do. Read more here:
Strongly Typed Reflection in Lokad Shared
How to Find Out Variable or Parameter Name in C#?
From your comment: "I want an easy and compile time safe syntax to get information about members".
This is a very frequently requested feature and has been discussed in the C# team's meetings for about a decade, but has never been prioritised high enough to be included.
This blog post explains why:
http://blogs.msdn.com/ericlippert/archive/2009/05/21/in-foof-we-trust-a-dialogue.aspx
So for now, you're just going to be fighting against a missing feature. Maybe you could post more information about your broader problem and see if people can suggest different approaches.
Update
Without more info about your problem this is just guesswork. But if you have a property that represents a value but also carries additional "meta" information, you could always represent that as a new type and use an "injection" step to set everything up.
Here's a suggested abstract interface to such a "meta property":
public interface IMetaProperty<TValue>
{
TValue Value { get; set; }
string DisplayName { get; }
event Action<TValue, TValue> ValueChanged;
}
The value of the property is just another sub-property, with its type defined by the user.
I've put in the display name, and also as a bonus you've got an event that fires when the value changes (so you get "observability" for free).
To have properties like this in a class, you'd declare it like this:
public class SomeClass
{
public IMetaProperty<string> FirstName { get; private set; }
public IMetaProperty<string> LastName { get; private set; }
public IMetaProperty<int> Age { get; private set; }
public SomeClass() { MetaProperty.Inject(this); }
}
Note how the setters on the properties are private. This stops anyone from accidentally setting the property itself instead of setting the Value sub-property.
So this means the class has to set up those properties so they aren't just null. It does this by calling a magic Inject method, which can work on any class:
public static class MetaProperty
{
// Make it convenient for us to fill in the meta information
private interface IMetaPropertyInit
{
string DisplayName { get; set; }
}
// Implementation of a meta-property
private class MetaPropertyImpl<TValue> : IMetaProperty<TValue>,
IMetaPropertyInit
{
private TValue _value;
public TValue Value
{
get { return _value; }
set
{
var old = _value;
_value = value;
ValueChanged(old, _value);
}
}
public string DisplayName { get; set; }
public event Action<TValue, TValue> ValueChanged = delegate { };
}
public static void Inject(object target)
{
// for each meta property...
foreach (var property in target.GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType &&
p.PropertyType.GetGenericTypeDefinition()
== typeof(IMetaProperty<>)))
{
// construct an implementation with the correct type
var impl = (IMetaPropertyInit)
typeof (MetaPropertyImpl<>).MakeGenericType(
property.PropertyType.GetGenericArguments()
).GetConstructor(Type.EmptyTypes).Invoke(null);
// initialize any meta info (could examine attributes...)
impl.DisplayName = property.Name;
// set the value
property.SetValue(target, impl, null);
}
}
}
It just uses reflection to find all the IMetaProperty slots hiding in the object, and fills them in with an implementation.
So now a user of SomeClass could say:
var sc = new SomeClass
{
FirstName = { Value = "Homer" },
LastName = { Value = "Simpson" },
Age = { Value = 38 },
};
Console.WriteLine(sc.FirstName.DisplayName + " = " + sc.FirstName.Value);
sc.Age.ValueChanged += (from, to) =>
Console.WriteLine("Age changed from " + from + " to " + to);
sc.Age.Value = 39;
// sc.Age = null; compiler would stop this
If you're already using an IOC container you may be able to achieve some of this without going directly to reflection.
It looks like you're trying to create a static extension method?
DateTime yesterday = DateTime.Yesterday(); // Static extension.
Instead of
DateTime yesterday = DateTime.Now.Yesterday(); // Extension on DateTime instance.
If this is what you're trying to pull off, I do not believe it is possible in the current version of C#.
It sounds like you are integrating layers a little too tightly. Normally in this type of situation I would let the presentation layer decide the implementation of GetDisplayName() instead of making it an extension of the property itself. You could create an interface called MyTypeDisplayer or whatever you fancy, and let there be multiple implementations of it not limiting you to a single display implementation.
The issue here is that one cannot get a reference to non-static methods via instance MyType.[Member]. These can only be seen through a reference to an instance of the type. You also cannot build an extension method on-top of a type declaration, only on an instance of a type - that is the extension method itself has to be defined using an instance of a type (this T x).
One can however define the expression like this to get a reference to static members:
((MyType x) => MyType.Property)
One could do something similar to string displayName = ((MyType x) => x.Property).GetDisplayName();
The first issue is guaranteeing that the compiler treats your (x=> x.Property) as an Expression rather than an action/func etc...
To do this one might need to do this:
string displayName = ((Expression<Func<PropertyType>>)((MyType x) => x.Property).GetDisplayName();
The extension method would then have to be defined like this:
public static string GetDisplayName<T>(this Expression<Func<T>> expression)
You might also have to define an extension method on top of Expression<Action>> and Expression<Action<T>> if your members are also methods.
You can do a dot after an Expression - this is where the Compile method would reside.
Appended:
I think the static call to the extension method in cases that one doesn't have an instance of the type one needs to do "reflection" on to determine a Members name would be the cleanest syntax still - this way you could still use the extension method when using an instance of a type and fall back to the static call definition => MyExtensionClass.GetDisplayName(TypeOfX x => TypeOfX.StaticMember OR x.Property/Member) when one doesn't have an instance
If you interface your properties, you could make the extension on the interface instead:
namespace Linq1
{
class Program
{
static void Main(string[] args)
{
MyType o = new MyType();
o.Property.GetDisplayName();
}
}
public class MyType
{
public IDisplayableProperty Property { get; set; }
}
public interface IDisplayableProperty
{
string GetText();
}
public class MyProperty1 : IDisplayableProperty
{
public string GetText() { return "MyProperty2"; }
}
public class MyProperty2 : IDisplayableProperty
{
public string GetText() { return "MyProperty2"; }
}
public static class Extensions
{
public static string GetDisplayName(this IDisplayableProperty o)
{
return o.GetText();
}
}
}

Categories