Tell me the flow of execution in the following scenario - c#-3.0

public class Temp
{
List<T> values = new List<T>;
static Temp()
{
System.Console.WriteLine("static constructor");
}
public Temp()
{
System.Console.WriteLine("general constructor");
}
}
Also please explain me when will the List object will be created and with what type it is created.
}

It appears the field gets initialized first, then the static constructor is called, then the constructor.
class Test
{
string variable = new Func<string>(() =>
{
Console.WriteLine("field initializer");
return "VARIABLE";
})();
static string staticvariable = new Func<string>(() =>
{
Console.WriteLine("static field initializer");
return "STATICVARIABLE";
})();
static Test()
{
System.Console.WriteLine("static constructor");
}
public Test()
{
System.Console.WriteLine("general constructor");
}
}
Test t = new Test();
outuput:
static field initializer
static constructor
field initializer
general constructor
[edit]
Oops sorry, it was a non-static field and I didn't notice it.

The static ctor will be called first.
Then values list will be second and the the ctor.
Read about beforefieldinit here.

Related

Passing parameter from ViewModel to ViewModel in .NET MAUI using CommunityToolkit.MVVM

My receiving Viewmodel (QuestionsPageViewModel) is not receiving the TopidId after passing it through Shell navigation as shown in the code below. I have placed the breakpoint at the LoadQuestions method in the QuestionsPageViewModel. When it is called, TopicId is null.
What am I missing?
HomePageViewModel
//This is in a command executed after clicking a button. And this is working fine
await Shell.Current.GoToAsync($"{nameof(QuestionsPage)}?TopicId={pack.TopicId}");
QuestionsPageViewModel
[INotifyPropertyChanged]
[QueryProperty(nameof(TopicId), nameof(TopicId))]
public partial class QuestionsPageViewModel
{
public ObservableRangeCollection<Question> QuestionsList { get; set; } = new();
[ObservableProperty]
string? title;
[ObservableProperty]
public string topicId;
public QuestionsPageViewModel()
{
LoadQuestions();
}
async void LoadQuestions()
{
Title = Utilities.ConvertTopicIdToString(short.Parse(TopicId));
try
{
using (var context = new DataContext())
{
QuestionPack questionPack = context.QuestionPacks
.First(x => x.TopicId == short.Parse(TopicId));
var questions = JsonConvert.DeserializeObject<List<Question>>(questionPack.Questions);
QuestionsList.AddRange(questions);
}
}
catch (Exception ex)
{
await Shell.Current.DisplayAlert("Error", $"Something went wrong: {ex}", "Cancel");
}
}
}
}
First of all, your field topicId should be private. CommumityToolkit.Mvvm will generate for you the public property.
Secondly, topicId is null because you're checking its value in a function called in the constructor. While you're executing the constructor, the shell navigation parameters are not initialized yet.
If you want to be sure that LoadQuestions() will be called after topicId is initialized, CommumityToolkit.Mvvm since version 8.0.0 should generate a partial method that can be used to execute some code after an ObservableProperty changes its value. In your case the name of this method should be OnTopicIdChanged(string value).
Try adding in your viewmodel this method and remove the function call from the constructor:
partial void OnTopicIdChanged(string value)
{
LoadQuestions();
}

Get and Set attribute values of a class using aspectJ

I am using aspectj to add some field to a existing class and annotate it also.
I am using load time weaving .
Example :- I have a Class customer in which i am adding 3 string attributes. But my issues is that I have to set some values and get it also before my business call.
I am trying the below approach.
In my aj file i have added the below, my problem is in the Around pointcut , how do i get the attribute and set the attribute.
public String net.customers.PersonCustomer.getOfflineRiskCategory() {
return OfflineRiskCategory;
}
public void net.customers.PersonCustomer.setOfflineRiskCategory(String offlineRiskCategory) {
OfflineRiskCategory = offlineRiskCategory;
}
public String net.customers.PersonCustomer.getOnlineRiskCategory() {
return OnlineRiskCategory;
}
public void net.customers.PersonCustomer.setOnlineRiskCategory(String onlineRiskCategory) {
OnlineRiskCategory = onlineRiskCategory;
}
public String net.customers.PersonCustomer.getPersonCommercialStatus() {
return PersonCommercialStatus;
}
public void net.customers.PersonCustomer.setPersonCommercialStatus(String personCommercialStatus) {
PersonCommercialStatus = personCommercialStatus;
}
#Around("execution(* net.xxx.xxx.xxx.DataMigration.populateMap(..))")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
Object arguments[] = joinPoint.getArgs();
if (arguments != null) {
HashMap<String, String> hMap = (HashMap) arguments[0];
PersonCustomer cus = (PersonCustomer) arguments[1];
return joinPoint.proceed();
}
If anyone has ideas please let me know.
regards,
FT
First suggestion, I would avoid mixing code-style aspectj with annotation-style. Ie- instead of #Around, use around.
Second, instead of getting the arguments from the joinPoint, you should bind them in the pointcut:
Object around(Map map, PersonCustomer cust) :
execution(* net.xxx.xxx.xxx.DataMigration.populateMap(Map, PersonCustomer) && args(map, cust) {
...
return proceed(map, cust);
}
Now, to answer your question: you also need to use intertype declarations to add new fields to your class, so do something like this:
private String net.customers.PersonCustomer.OfflineRiskCategory;
private String net.customers.PersonCustomer.OnlineRiskCategory;
private String net.customers.PersonCustomer.PersonCommercialStatus;
Note that the private keyword here means private to the aspect, not to the class that you declare it on.

Autofac wiring question - beginner

Beginners question:
Given two classes: Myclass5 and Myclass6 how can one wire up following factory method (returned as Func)
such that
myclass5 and myclass6 instances and IMyClass that they depend on are all retrieved via autofac (assuming that these three instances are registered).
public static MyClass4 FactoryMethod(int nu)
{
if (nu == 1)
return new MyClass5(....);
if (nu == 4)
return new MyClass6(....);
throw new NotImplementedException();
}
public abstract class MyClass4
{
}
public class MyClass5 : MyClass4
{
public MyClass5(int nu, IMyClass a)
{
}
}
public class MyClass6 : MyClass4
{
public MyClass6(int nu, IMyClass a)
{
}
}
For FactoryMethod to be able to create the instances, it requires access to a container. I would suggest create a delegate type for the factory method, which makes it easy to take dependency on it. Registration goes like this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.Register((c, p) =>
{
var context = c.Resolve<IComponentContext>();
return new FactoryMethod(nu =>
{
var nuParameter = TypedParameter.From(nu);
switch (nu)
{
case 1:
return context.Resolve<MyClass5>(nuParameter);
case 4:
return context.Resolve<MyClass6>(nuParameter);
default:
throw new NotImplementedException();
}
});
});
var container = cb.Build();
At resolve time, you can then take a dependency on the FactoryMethod delegate type and use it to resolve instances:
var factory = container.Resolve<FactoryMethod>();
var instance5 = factory(1);
var instance6 = factory(1);
Note: the delegate instance we're creating needs a context. We cannot use the c parameter directly since that context is only temporary. Thus we must resolve a IComponentContext to "bake" into the lambda.
Update: if you would like to extract the factory implementation into a method that is not dependent on the container I would suggest the following:
public class FactoryMethodImpl
{
readonly Func<int, MyClass5> _factory5;
readonly Func<int, MyClass6> _factory6;
public FactoryMethodImpl(Func<int, MyClass5> factory5, Func<int, MyClass6> factory6)
{
_factory5 = factory5;
_factory6 = factory6;
}
public MyClass4 Create(int nu)
{
switch (nu)
{
case 1:
return _factory5(nu);
case 4:
return _factory6(nu);
default:
throw new NotImplementedException();
}
}
}
Now, change the registration code to this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.RegisterType<FactoryMethodImpl>().SingleInstance();
cb.Register(c=> new FactoryMethod(c.Resolve<FactoryMethodImpl>().Create));

How can I dump the normal properties on an IEnumerable in Linqpad

If I have an object that among other things is an IEnumerable and I dump this object I get the enumerated values.
Is there a way to get Linqpad to list the other properties:
Se example below:
Can I get Dump to include Hello and digits properties?
void Main()
{
var t = new test();
var d = new Dictionary<string,string> {{"Hello","World"},{"Good by","Sky"}};
t.Dump();
d.Dump();
}
// Define other methods and classes here
public class test : IEnumerable
{
public string Hello { get { return "World"; }}
public List<int> digits { get { return new List<int> {0,1,2,3,4,5,6,7,8,9}; }}
public IEnumerator GetEnumerator() { yield return "Hej"; }
}
You could write a DumpPayload extension method as follows:
void Main()
{
var t = new test();
t.DumpPayload();
}
public static class Extensions
{
public static void DumpPayload (this IEnumerable o)
{
if (o == null)
{
o.Dump();
return;
}
var d = new Dictionary<string,object>();
foreach (var member in o.GetType().GetProperties())
try
{
d[member.Name] = member.GetValue (o, null);
}
catch (Exception ex)
{
d[member.Name] = ex;
}
d["AsEnumerable"] = o;
d.Dump();
}
}
If you put this extension method into "My Extensions", it will be available to all queries.
Another solution is to implement ICustomMemberProvider in the test class:
public class test : IEnumerable, ICustomMemberProvider
{
public string Hello { get { return "World"; }}
public List<int> digits { get { return new List<int> {0,1,2,3,4,5,6,7,8,9}; }}
public IEnumerator GetEnumerator() { yield return "Hej"; }
IEnumerable<string> ICustomMemberProvider.GetNames()
{
return "Hello Enumerator".Split();
}
IEnumerable<Type> ICustomMemberProvider.GetTypes ()
{
return new [] { typeof (string), typeof (IEnumerable) };
}
IEnumerable<object> ICustomMemberProvider.GetValues ()
{
return new object [] { Hello, this.OfType<Object>() };
}
}
Note that if the test class is defined in another assembly, you don't need to reference LINQPad in order to implement ICustomMemberProvider. You can just paste in the following definition into your project and LINQPad will pick it up:
namespace LINQPad
{
public interface ICustomMemberProvider
{
IEnumerable<string> GetNames ();
IEnumerable<Type> GetTypes ();
IEnumerable<object> GetValues ();
}
}
As far as I can tell if the object you're trying to dump implements IEnumerable then LINQPad always wants to dump it as an IEnumerable list. Getting rid of the interface correctly shows the Hello and digits properties in the dumped info.
Going from this link it appears you can write your own dump which accomplishes something like LINQPad by enumerating the collection and all it's properties then outputting the whole thing as an XHTML string. I haven't tried this.
Use a Serializer?
Json.NET will do all of this for you in a json format.
Newtonsoft.Json.JsonConvert.SerializeObject(t, Newtonsoft.Json.Formatting.Indented)
if you don't want json, then pick a serializer you do want, or you'll just have to do what a serializer would do, use reflection to iterate the properties on the object.

understanding func<T, TResult> C#

I am trying to refactor some of my code to use Func
I have created a sample to try to understand how it works but I am getting compilation error. In the e.g. below when I am trying to access the parameter attributes or return the return value the compiler complain.
Clarifications please.
using System;
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
ParamInput input = new ParamInput();
input.ReservationID = 10;
Test testMethod = new Test();
Func<ParamInput, ReservationResult> methodToInvoke = testMethod.GetStatus;
ReservationResult result = TestFn(methodToInvoke, input);
}
static Result TestFn<Param, Result>(Func<Param, Result> methodToInvoke, Param parameter) where Result : new()
{
Result result = new Result();
try
{
result = methodToInvoke(parameter);
}
catch (Exception exception)
{
result.status = string.Format("Error-{0} during reserving {1}",
parameter.ReservationID,
exception.Message);
}
return result;
}
}
class Test
{
public ReservationResult GetStatus(ParamInput msg)
{
ReservationResult result = new ReservationResult();
result.status = string.Format("The ReservationID-{0}", msg.ReservationID);
return result;
}
}
class ParamInput
{
public int ReservationID { get; set; }
}
class ReservationResult
{
public string status { get; set; }
}
}
Annotated compile errors:
error CS1061: 'Result' does not contain a definition for 'status'
error CS1061: 'Param' does not contain a definition for 'ReservationID'
Code using generic type arguments can only compile if the compiler knows the member of the generic type. It doesn't know that the Result type argument has a "status" member. It certainly doesn't if you invoke TestFn<object, object>().
You'll need to use a constraint to make this work. You already do, but new() isn't strong enough. Something like "where Result : IResult" for example, where IResult is an interface type that has a status property. Or a base class. The compiler can now be 100% sure that any allowed concrete instance of the generic method will execute without causing runtime errors. Since it can only ever be compiled when it was invoked with a type that has a "status" property.
All the same applies to the Param type argument. The usefulness of a generic method here rapidly disappears when you do this, it is not the proper usage. Unless you can leverage IResult, like you can IEnumerable.
Compiles...
You ought to descibe what you aim is in your question.
See Hans' answer for details that might help you understand the error.
Your problem is that you're saying the function should take a Result that is instantiable, but you are not saying it has to have a property called "status".
namespace chsarp
{
class Program
{
static void Main(string[] args)
{
Func<int, string> m = Test.GetStatus;
var t = TestFn(m, 10);
}
static string TestFn<TParam>(Func<TParam, string> m, TParam p)
{
try { return m(p); }
catch (Exception exception)
{
return string.Format("Reserving \"{0}\" failure exception: {1}", p, exception);
}
}
}
static class Test
{
public static string GetStatus(int inp)
{
return string.Format("The ReservationID-{0}", inp);
}
}
}