Func as Variable in a class - c#

I would like to use a function as a variable for me to assign.
Something like this
Class:
public class Func
{
public string Name { get; set; }
public string Content { get; set; }
public Function function { get; set; } //Not sure what type for a func
}
Func:
public void Click_Event(object sender,EventArgs e)
{
//Some code here.
}
List to assign the func:
List<Func> funcList = new List<Func>();
Func func = new Func();
func.Name = "Name";
func.Content = "Hello World";
func.function = Click_Event; //This is what I really want to do.
funcList.Add(func);
Is there anyway to achieve this?
Edited
Some of the comment below said that Reflection may cause the performance issue, but I use it and doesn't seen any slow issue currently. I use it when I first start the app only.
This is the sample code I use it.
MethodInfo method = this.GetType().GetMethod("FuncName"); //Or using nameof
btnFunc.AddHandler(Button.ClickEvent, Delegate.CreateDelegate(Button.ClickEvent.HandlerType, this, method, false));

Try using a delegate:
A delegate is a data structure that refers to a static method or to a
class instance and an instance method of that class.
https://learn.microsoft.com/en-us/dotnet/api/system.delegate?view=netframework-4.8
Another option to look into would be an Action or Func

After a several research, I have found another way to solve this.
Save the function name as a string instead of as a Action or delegate
Then use System.Reflection.MethodInfo and btn.AddHandler to use it.
By this way, the function must be public.

Related

Generically get the name of the current class?

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
}
}

Delegate/Action is not passing value

I have a very basic understanding of using this technique so I probably and missing something simple. All I want to do is add a variable that holds the TOTAL items but the variable seems to be getting initialized back to 0 when I check it. My best guess is something is going out of scope and I am losing the value.
I call a function that passes a delegate(?)
[TestMethod]
public void Batch_Update_Is_Working()
{
DataTable dt = ExcelHelper.ReadAsDataTable(pathFileName);
EncompassBoxHelper.UpdateBoxes(ec, dt, progess => UpdateProgressBar(pi));
}
Inside the function I want to pass a value back.
public static void UpdateBoxes(EncompassConnection ec, DataTable dt, Action<ProgressInfo> updateProgress)
{
Session s = EncompassSession.Instance(ec.Url, ec.Name, ec.Password);
updateProgress(new ProgressInfo(dt.Rows.Count));
This is where the value is stored. In ItemsTotal. All good so far.
public class ProgressInfo
{
public int itemsProcessed { get; set; }
public int itemsTotal { get; set; }
public ProgressInfo()
{
}
public ProgressInfo(int it)
{
itemsTotal = it;
}
}
Now when it goes to the callback the value is 0??? pi.itemsProcessed is suppose to be 100.
public void UpdateProgressBar(ProgressInfo pi)
{
pi.itemsProcessed++;
Debug.WriteLine("Progress Info.ItemsProcessed: " + pi.itemsProcessed);
Debug.WriteLine("Progress Info.ItemsTotal: " + pi.itemsTotal);
}
Change your
EncompassBoxHelper.UpdateBoxes(ec, dt, progess => UpdateProgressBar(pi));
to
EncompassBoxHelper.UpdateBoxes(ec, dt, UpdateProgressBar);
Instead of sending the UpdateProgressBar() method to match the delegate expected in UpdateBoxes parameter, you're creating a new one by converting lambda expression, telling it to call itself specifically with a parameter of pi, instead of the one, that should be passed inside UpdateBoxes method (the new ProgressInfo(dt.Rows.Count) object).
Looks like your pi variable is not being passed by reference so it is never really getting updated. Honestly changing a value like pi.itemsProcessed++ in your delegate function is not very common although there are ways to do it like this.
Once your delegate supports passing in a variable with the "ref" keyword, then you should be able to call your delegate with something like this:
progess => UpdateProgressBar(ref pi)
You could also make pi a static variable and then it can be updated from your delegate as well so you don't have to worry about passing it around.

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";
}

the use of Lambda and action delegate

i got few line of code where configure method is calling and passing just the string value but ConfigureWith function expect delegate. can anyone help me to understand how ConfigureWith() method will work. thanks
MailTemplate
.ConfigureWith(mt => mt.MailBody = "hello world")
.ConfigureWith(mt => mt.MailFrom = "rdingwall#gmail.com")
.DoSomeOtherStuff()
.Build();
The implementation for this would be:
public class MailTemplate
{
// regular auto properties
public string MailFrom { get; set; }
public string MailBody { get; set; }
public MailTemplate ConfigureWith(Action<MailTemplate> func)
{
func(this);
return this;
}
}
As written it seems entirely pointless, you may as well just set the property on the MailTemplate directly.
Typically in a fluent builder like this you would save the Actions being passed in with each ConfigureWith call and then execute them later.
It might help if you explain in more detail what you hope to achieve with the fluent syntax you are creating. As written it also will not compile since the first call expects a static method. Can you show the real code?
You might also want to look at other answers on StackOverflow regarding fluent methods (e.g. Tips for writing fluent interfaces in C# 3)
I see that the example above is from an answer to a different question you asked earlier. I'm still not entirely sure what you're trying to do, and as Ian Mercer suggested, it's pretty pointless as written. But if you're just trying to understand what it does, then let's first get a working example:
using System;
namespace ScratchApp
{
internal class Program
{
private static void Main(string[] args)
{
var mailTemplate = BuildMailTemplate(
mt => mt.MailBody = "hello world",
mt => mt.MailFrom = "rdingwall#gmail.com");
}
private static MailTemplate BuildMailTemplate(
Action<MailTemplate> configAction1,
Action<MailTemplate> configAction2)
{
var mailTemplate = new MailTemplate();
mailTemplate.ConfigureWith(configAction1)
.ConfigureWith(configAction2)
.DoSomeOtherStuff()
.Build();
return mailTemplate;
}
}
public class MailTemplate
{
public string MailFrom { get; set; }
public string MailBody { get; set; }
public MailTemplate DoSomeOtherStuff()
{
// Do something
return this;
}
public MailTemplate Build()
{
// Build something
return this;
}
public MailTemplate ConfigureWith(Action<MailTemplate> func)
{
func(this);
return this;
}
}
}
This is as pointless as before, but it builds. What's happening when you're calling .ConfigureWith() is that instead of passing a normal value, you're passing it a function. In the example above, I'm actually declaring the functions as parameters that get passed into the BuildMailTemplate() method, and which in turn get executed when the template is being built and configured. You can get a feel for how it works by stepping through the code, line-by-line (e.g., F11 in Visual Studio), and setting breakpoints in the lambda expressions themselves, and then looking at the call stack.
If you're confused about the syntax for lambdas - arrow syntax is indeed a bit complex when you're first getting used to it - then feel free to check out the MSDN article on it, or just Google "c# lambdas" to your heart's delight.

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